1 /* Copyright (c) 1995-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  * 2nd module to implement pli vpi_ routines
30  */
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <stdarg.h>
37 
38 #ifdef __DBMALLOC__
39 #include "../malloc.h"
40 #endif
41 
42 #include "v.h"
43 #include "cvmacros.h"
44 
45 #include "vpi_user.h"
46 #include "cv_vpi_user.h"
47 
48 /* local prototypes */
49 static void mk2_exprclass_handle(struct h_t *, struct expr_t *,
50  struct itree_t *, struct task_t *);
51 static int32 iconnbit_lvalue(struct mod_pin_t *, struct net_pin_t *,
52  struct itree_t *);
53 static vpiHandle bld_inmod_port_iter(struct h_t *);
54 static vpiHandle bld_fjlist_iter(struct st_t *, struct itree_t *,
55  struct task_t *);
56 static vpiHandle bld_listofstmts_iter(struct st_t *, struct itree_t *,
57  struct task_t *);
58 static vpiHandle bld_listofexprs_iter(struct expr_t *, struct itree_t *,
59  struct task_t *);
60 static int32 termexpr_matches(struct expr_t *, struct net_t *, int32);
61 static int32 bld_net_tchkterms(struct net_t *, struct itree_t *, int32);
62 static int32 bld_net_pathterms(struct net_t *, struct itree_t *, int32);
63 static int32 bld_delay_iter(union del_u, word32, struct itree_t *,
64  struct task_t *);
65 static vpiHandle bld_dig_attrlist_iter(struct h_t *, struct attr_t *);
66 static vpiHandle bld_netmdport_iter(struct h_t *);
67 static int32 bld_net_mdpins(struct net_t *, struct mod_t *, struct itree_t *);
68 static vpiHandle bld_netbitmdport_iter(struct h_t *);
69 static int32 cmp_drvld_bitndx(struct net_t **, struct h_t *, char *);
70 static int32 bld_netbit_mdpins(struct net_t *, int32, struct mod_t *,
71  struct itree_t *);
72 static vpiHandle bld_neticonnport_iter(struct h_t *);
73 static int32 bld_net_iconns(struct net_t *, struct itree_t *);
74 static int32 same_vpi_handle(struct h_t *, int32, int32, struct h_t *,
75  struct hrec_t *);
76 static vpiHandle bld_netbiticonnport_iter(struct h_t *);
77 static int32 bld_netbit_iconns(struct net_t *, int32, struct itree_t *);
78 static vpiHandle net_lds_iter(struct h_t *);
79 static int32 bld_net_lds(struct net_t *, struct itree_t *);
80 static int32 fill_ld_handle(struct h_t *, struct hrec_t *, struct net_pin_t *);
81 static vpiHandle bit_lds_iter(struct h_t *);
82 static int32 bld_bit_lds(struct net_t *, int32, struct itree_t *, int32);
83 static int32 fill_bit_ld_handle(struct h_t *, struct hrec_t *, int32, int32, int32,
84  struct net_pin_t *);
85 static vpiHandle bit_xl_ldsdrvs_iter(struct h_t *, int32);
86 static vpiHandle net_drvs_iter(struct h_t *);
87 static int32 bld_net_drvs(struct net_t *, struct itree_t *);
88 static int32 fill_drv_handle(struct h_t *, struct hrec_t *, struct net_pin_t *);
89 static vpiHandle bit_drvs_iter(struct h_t *hp);
90 static int32 bld_bit_drvs(struct net_t *, int32, struct itree_t *, int32);
91 static int32 fill_bit_drv_handle(struct h_t *, struct hrec_t *, int32, int32, int32,
92  struct net_pin_t *);
93 static vpiHandle reg_drvs_iter(struct h_t *);
94 static vpiHandle cnvt_name_to_handle(char *, struct symtab_t *,
95  struct itree_t *);
96 static vpiHandle bld_symhandle(char *, struct sy_t *, struct symtab_t *,
97  struct itree_t *);
98 static int32 validate_property(char *, int32);
99 static int32 modprop_vpiget(struct h_t *, int32);
100 static void notpropof_err(word32, int32);
101 static word32 to_vpi_reghtyp(word32);
102 static int32 netprop_vpiget(struct h_t *, int32);
103 static int32 regprop_vpiget(struct h_t *, int32);
104 static int32 arrprop_vpiget(struct h_t *, int32);
105 static int32 arrwrdprop_vpiget(struct h_t *, int32);
106 static int32 paramprop_vpiget(struct h_t *, int32);
107 static int32 portprop_vpiget(struct h_t *, int32);
108 static int32 get_param_constyp(struct net_t *);
109 static int32 gateprop_vpiget(struct h_t *, int32);
110 static int32 tcallprop_vpiget(struct h_t *, int32);
111 static int32 funcdefprop_vpiget(struct h_t *, int32);
112 static int32 contaprop_vpiget(struct h_t *, int32);
113 static int32 fcallprop_vpiget(struct h_t *, int32);
114 static int32 tchkprop_vpiget(struct h_t *, int32);
115 static int32 to_vpi_tchktyp(word32);
116 static int32 tchktermprop_vpiget(struct h_t *, int32);
117 static int32 to_vpi_edgeval(word32);
118 static int32 pthprop_vpiget(struct h_t *, int32);
119 static int32 pthtermprop_vpiget(struct h_t *, int32);
120 static int32 exprclass_prop_vpiget(struct h_t *, int32);
121 static int32 get_vpi_const_typ(struct expr_t *);
122 static int32 iodecl_prop_vpiget(struct h_t *, int32);
123 static int32 udpiodecl_get(struct h_t *, int32);
124 static int32 udpdefnprop_vpiget(struct h_t *, int32);
125 static int32 udptabentryprop_vpiget(struct h_t *, int32);
126 static int32 dig_attrprop_vpiget(struct h_t *, int32);
127 static char *modstrprop_vpiget(struct h_t *, int32);
128 static char *netstrprop_vpiget(struct h_t *, int32);
129 static char *portstrprop_vpiget(struct h_t *, int32);
130 static char *gatestrprop_vpiget(struct h_t *, int32);
131 static char *tcallstrprop_vpiget(struct h_t *, int32);
132 static char *fcallstrprop_vpiget(struct h_t *, int32);
133 static char *taskstrprop_vpiget(struct h_t *, int32);
134 static char *iodeclstrprop_vpiget(struct h_t *, int32);
135 static char *dig_attrstrpop_vpiget(struct h_t *, int32);
136 
137 
138 /* extern prototypes (maybe defined in this module) */
139 extern vpiHandle vpi_handle_by_name(char *, vpiHandle);
140 extern vpiHandle vpi_handle_by_index(vpiHandle, PLI_INT32);
141 extern int32 vpi_get(PLI_INT32, vpiHandle);
142 extern word32 __ntyp_to_vpivarhtyp(struct net_t *);
143 extern word32 __to_vpinetbithtyp(word32);
144 extern word32 __from_vpi_vartyp(word32);
145 extern int32 __expr_optype_get(struct expr_t *);
146 extern char *vpi_get_str(int32, vpiHandle);
147 extern char *__to_vpionam(char *, word32);
148 extern char *__to_vpiopchar(char *, int32);
149 extern void __still_comp_err(char *);
150 extern int32 __validate_handle(char *, struct h_t *);
151 extern int32 __get_vpinet_index(struct net_t **, struct h_t *);
152 
153 extern vpiHandle __bld_port_iterator(struct h_t *);
154 extern vpiHandle __bld_neticonn_iter(struct h_t *);
155 extern vpiHandle __bld_paramassign_stmt_iter(struct h_t *);
156 extern vpiHandle __bld_udpline_iter(struct h_t *);
157 extern vpiHandle __bld_primterm_iterator(struct h_t *);
158 extern vpiHandle __bld_loc_lds_iterator(struct h_t *, int32);
159 extern vpiHandle __bld_lds_iterator(struct h_t *, int32);
160 extern int32 __bld_xl_drvld_vtxtab(struct net_t *, int32, struct itree_t *, int32);
161 extern vpiHandle __bld_loc_drvs_iterator(struct h_t *, int32);
162 extern vpiHandle __bld_drvs_iterator(struct h_t *, int32);
163 extern vpiHandle __bld_arrwrd_iterator(struct h_t *);
164 extern vpiHandle __bld_bitof_iterator(struct h_t *);
165 extern vpiHandle __bld_systf_iterator(struct h_t *);
166 extern vpiHandle __bld_tfargexpr_iterator(struct h_t *);
167 extern vpiHandle __bld_pthterm_iterator(struct h_t *, word32);
168 extern vpiHandle __bld_stmt_iterator(struct h_t *);
169 extern vpiHandle __bld_netin_tchkterms(struct h_t *);
170 extern vpiHandle __bld_netin_pthterms(struct h_t *);
171 extern vpiHandle __bld_caseitems_iter(struct h_t *);
172 extern vpiHandle __bld_casi_exprs_iter(struct h_t *);
173 extern vpiHandle __bld_operands_iter(struct h_t *);
174 extern vpiHandle __bld_allcbs_iter(struct h_t *);
175 extern vpiHandle __bld_delay_expr_iter(struct h_t *);
176 extern vpiHandle __bld_iodecl_stmt_iter(struct h_t *);
177 extern struct task_t *__find_qualnam_task(char *, struct mod_t *,
178  struct task_t *);
179 extern void __xmrpush_refgrp_to_targ(struct gref_t *);
180 extern int32 __move_to_npprefloc(struct net_pin_t *);
181 extern void __get_bidnpp_sect(struct net_t *, struct net_pin_t *, int32 *,
182  int32 *);
183 extern int32 __exprtype_get(struct expr_t *);
184 extern struct xstk_t *__eval2_xpr(register struct expr_t *);
185 extern vpiHandle __nil_iter_err(word32);
186 extern void __notstrpropof_err(word32, int32);
187 extern struct pviter_t *__alloc_iter(int32, vpiHandle *);
188 extern void __init_hrec(struct hrec_t *);
189 extern void __grow_htab(int32);
190 extern void __grow_htab2(int32);
191 extern word32 __to_vpi_stmttyp(struct st_t **);
192 extern int32 __ip_indsrch(char *);
193 extern struct sy_t *__get_sym(char *, struct symtab_t *);
194 extern struct sy_t *__get_nongia_sym(char *, struct symtab_t *);
195 extern vpiHandle __mk_handle(word32, void *, struct itree_t *,
196  struct task_t *);
197 extern int32 __is_scope_sym(struct sy_t *);
198 extern word32 __to_vpi_tasktyp(word32);
199 extern word32 __gate_to_vpiprimtyp(struct gate_t *);
200 extern int32 __to_vpi_primtyp(struct gate_t *);
201 extern int32 __primtermprop_vpiget(struct h_t *, int32);
202 
203 extern void __getarr_range(struct net_t *, int32 *, int32 *, int32 *);
204 extern void __getwir_range(struct net_t *, int32 *, int32 *);
205 extern int32 __get_arrwide(struct net_t *);
206 extern int32 __wide_vval_is0(register word32 *, int32);
207 extern char *__msgexpr_tostr(char *, struct expr_t *);
208 extern char *__msg2_blditree(char *, struct itree_t *);
209 extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
210 extern void __extract_delval(word64 *, int32 *, union del_u, word32);
211 extern void __cnv_ticks_tonum64(word64 *, word64, struct mod_t *);
212 extern void __grow_xstk(void);
213 extern void __chg_xstk_width(struct xstk_t *, int32);
214 extern void __ld_arr_val(register word32 *, register word32 *, union pck_u,
215  int32, int32, int32);
216 extern struct expr_t *__bld_rng_numxpr(word32, word32, int32);
217 extern char *__my_realloc(char *, int32, int32);
218 extern void __my_free(char *, int32);
219 extern char *__my_malloc(int32);
220 extern int32 __unnormalize_ndx(struct net_t *, int32);
221 extern int32 __to_vpi_netproptyp(word32 ntyp);
222 extern struct expr_t *__glbnam_to_expr(char *);
223 extern char *__to_glbcmp_nam(struct expr_t *);
224 extern int32 __comp_ndx(register struct net_t *, register struct expr_t *);
225 extern struct expr_t *__sim_alloc_newxnd(void);
226 extern int32 __expr_is_vpiconst(struct expr_t *);
227 extern char *__to_vpipnam(char *, int32);
228 extern word32 __map_tovpi_stren(word32);
229 extern char *__strab2_tostr(char *, word32 *, int32, int32, int32);
230 extern int32 __name_vpi_hasdot(char *);
231 extern void __free_iterator(vpiHandle);
232 extern void __free_xtree(struct expr_t *);
233 extern int32 __allocfill_cval_new(word32 *, word32 *, int32);
234 extern struct attr_t *__find_attrspec(struct h_t *);
235 
236 extern void __arg_terr(char *, int32);
237 extern void __vpi_terr(char *, int32);
238 extern void __vpi_err(int32, int32, char *, ...);
239 
240 /* vpi only storage */
241 extern struct t_vpi_error_info *__last_eip;/* if err, ptr to wrk eifo or nil */
242 
243 /*
244  * ROUTINES TO BUILD ITERATORS (2nd GROUP)
245  */
246 
247 /*
248  * build an expression from expr_t record
249  *
250  * this is shell that allocates empty handle and call v2 for filling it
251  * needed because need to fill only for building iterators containing exprs
252  *
253  * if allocated, caller must see xp free bit
254  */
__mk_exprclass_handle(struct expr_t * xp,struct itree_t * xin_itp,struct task_t * xin_tskp)255 extern vpiHandle __mk_exprclass_handle(struct expr_t *xp,
256  struct itree_t *xin_itp, struct task_t *xin_tskp)
257 {
258  vpiHandle href;
259  struct h_t *hp;
260 
261  /* here vpiNet is just place holder - fixed by caller */
262  href = __mk_handle(vpiNet, NULL, xin_itp, xin_tskp);
263  hp = (struct h_t *) href;
264  mk2_exprclass_handle(hp, xp, xin_itp, xin_tskp);
265  return(href);
266 }
267 
268 /*
269  *
270  * here handle content are expressions - bit handle from iterators
271  * use different representation
272  *
273  * select handles because they are not in handle index value
274  * must be expr. itree loc - when converting to net in must handle xmr
275  *
276  * this is version that expects handle to be allocated and filled
277  * (useful for filling iterator handles)
278  */
mk2_exprclass_handle(struct h_t * hp,struct expr_t * xp,struct itree_t * xin_itp,struct task_t * xin_tskp)279 static void mk2_exprclass_handle(struct h_t *hp,
280  struct expr_t *xp, struct itree_t *xin_itp, struct task_t *xin_tskp)
281 {
282  register struct hrec_t *hrp;
283  int32 otyp, biti;
284  struct itree_t *xitp;
285  struct task_t *xtskp;
286  struct net_t *np;
287  struct expr_t *idndp;
288  struct sy_t *syp;
289 
290  hrp = hp->hrec;
291  switch (xp->optyp) {
292   case ID:
293    syp = xp->lu.sy;
294    xitp = xin_itp;
295    if (xp->locqualnam)
296     xtskp = __find_qualnam_task(xp->ru.qnchp, xin_itp->itip->imsym->el.emdp,
297      xin_tskp);
298    else xtskp = NULL;
299    goto fill_id_handle;
300   case GLBREF:
301    __push_itstk(xin_itp);
302    __xmrpush_refgrp_to_targ(xp->ru.grp);
303    xitp = __inst_ptr;
304    __pop_itstk();
305    __pop_itstk();
306    xtskp = xp->ru.grp->targtskp;
307 
308    /* xmr expressions can also be scopes objects (i.e. not net/reg or var) */
309    syp = xp->lu.sy;
310    switch (syp->sytyp) {
311     case SYM_I: case SYM_M:
312      /* DBG remove -- */
313      if (xtskp != NULL) __vpi_terr(__FILE__, __LINE__);
314      /* --- */
315      hrp->htyp = vpiModule;
316      hrp->hu.hmdp = xitp->itip->imsym->el.emdp;
317      hp->hin_itp = xitp;
318      hrp->hin_tskp = NULL;
319      return;
320     /* notice function here must be function call */
321     case SYM_TSK: case SYM_LB:
322      {
323       struct task_t *tskp;
324       struct symtab_t *sytp;
325 
326       tskp = syp->el.etskp;
327       /* DBG remove --- */
328       if (tskp != xtskp) __vpi_terr(__FILE__, __LINE__);
329       /* --- */
330       hrp->htyp = __to_vpi_tasktyp(tskp->tsktyp);
331       hrp->hu.htskp = xtskp;
332       hp->hin_itp = xitp;
333       sytp = xtskp->tsksymtab->sytpar;
334       /* DBG remove */
335       if (sytp == NULL) __vpi_terr(__FILE__, __LINE__);
336       /* --- */
337       if (sytp->sypofsyt->sytyp != SYM_I)
338        xin_tskp = sytp->sypofsyt->el.etskp;
339       else xin_tskp = NULL;
340       hrp->hin_tskp = xin_tskp;
341      }
342      return;
343     default:
344      break;
345    }
346 
347 fill_id_handle:
348    /* this is both net/reg and variable (int32,real.time) but not bit select */
349    np = xp->lu.sy->el.enp;
350    otyp = __ntyp_to_vpivarhtyp(np);
351    hrp->htyp = otyp;
352    hrp->hu.hanyp = (void *) np;
353    hp->hin_itp = xitp;
354    hrp->hin_tskp = xtskp;
355    break;
356   case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM:
357    hrp->htyp = vpiConstant;
358    hrp->hu.hxp = xp;
359    goto fill_itloc;
360   case OPEMPTY:
361    /* this is vpi Null Op operation */
362    hrp->htyp = vpiOperation;
363    hrp->hu.hxp = xp;
364    goto fill_itloc;
365   case LSB:
366    idndp = xp->lu.x;
367    /* SJM 08/23/00 - branches never XMRs */
368    /* SJM 08/23/00 - if select from xmr, must change itree loc */
369    if (idndp->optyp == GLBREF)
370     {
371      __push_itstk(xin_itp);
372      __xmrpush_refgrp_to_targ(idndp->ru.grp);
373      xin_itp = __inst_ptr;
374      __pop_itstk();
375      __pop_itstk();
376      xin_tskp = idndp->ru.grp->targtskp;
377     }
378 
379    np = idndp->lu.sy->el.enp;
380    if (np->n_isarr) hrp->htyp = vpiMemoryWord;
381    else hrp->htyp = __to_vpinetbithtyp(np->ntyp);
382    /* DBG remove -- */
383    /* must never see parameter bit select or parameter array index */
384    /* because must be converted to constant during translate/load */
385    if (np->n_isaparam) __vpi_terr(__FILE__, __LINE__);
386    /* --- */
387 
388    /* try to optimize to bith ndx form */
389    if (!__expr_is_vpiconst(xp->ru.x))
390     {
391 bld_expr_bsel:
392      hrp->hu.hxp = xp;
393      goto fill_itloc;
394     }
395    biti = __comp_ndx(np, xp->ru.x);
396    if (biti == -1) goto bld_expr_bsel;
397    hrp->hu.hnp = np;
398    hrp->hi = biti;
399    hrp->bith_ndx = TRUE;
400    goto fill_itloc;
401   case PARTSEL:
402    hrp->htyp = vpiPartSelect;
403    hrp->hu.hxp = xp;
404    /* SJM 08/23/00 - if xmr part select, must change itree loc */
405    if (xp->lu.x->optyp == GLBREF)
406     {
407      idndp = xp->lu.x;
408      __push_itstk(xin_itp);
409      __xmrpush_refgrp_to_targ(idndp->ru.grp);
410      xin_itp = __inst_ptr;
411      __pop_itstk();
412      __pop_itstk();
413      xin_tskp = idndp->ru.grp->targtskp;
414     }
415    goto fill_itloc;
416   case FCALL:
417    if (xp->lu.x->lu.sy->sytyp == SYM_SF) hrp->htyp = vpiSysFuncCall;
418    else
419     {
420      /* SJM 08/23/00 - if xmr user fcall, must change itree loc */
421      if (xp->lu.x->optyp == GLBREF)
422       {
423        idndp = xp->lu.x;
424        __push_itstk(xin_itp);
425        __xmrpush_refgrp_to_targ(idndp->ru.grp);
426        xin_itp = __inst_ptr;
427        __pop_itstk();
428        __pop_itstk();
429        xin_tskp = idndp->ru.grp->targtskp;
430       }
431      hrp->htyp = vpiFuncCall;
432     }
433    hrp->hu.hxp = xp;
434    goto fill_itloc;
435   default:
436    hrp->htyp = vpiOperation;
437    hrp->hu.hxp = xp;
438 fill_itloc:
439    hp->hin_itp = xin_itp;
440    hrp->hin_tskp = xin_tskp;
441   }
442 }
443 
444 /*
445  * build a parameter assign statement iterator
446  *
447  * this is internally same as parameter (gets valus from net)
448  *
449  * FIXME - not handle left hand side select parameter assigns in PLI
450  */
__bld_paramassign_stmt_iter(struct h_t * hp)451 extern vpiHandle __bld_paramassign_stmt_iter(struct h_t *hp)
452 {
453  register int32 pi, pi2;
454  register struct h_t *hp2;
455  struct hrec_t *hrp2, *hrp;
456  int32 nparams;
457  vpiHandle ihref;
458  struct pviter_t *iterp;
459  struct mod_t *mdp;
460  struct task_t *tskp;
461 
462  if (hp == NULL)
463   {
464    return(__nil_iter_err(vpiParamAssign));
465   }
466 
467  ihref = NULL;
468  mdp = hp->hin_itp->itip->imsym->el.emdp;
469  hrp = hp->hrec;
470  switch (hrp->htyp) {
471   case vpiModule:
472    nparams = mdp->mprmnum + mdp->mlocprmnum;
473    if (nparams <= 0) return(NULL);
474    iterp = __alloc_iter(nparams, &ihref);
475    for (pi = 0, pi2 = 0; pi < mdp->mprmnum; pi++)
476     {
477      hp2 = &(iterp->scanhtab[pi2++]);
478      hrp2 = hp2->hrec;
479      hrp2->htyp = vpiParamAssign;
480      hrp2->hu.hnp = &(mdp->mprms[pi]);
481      hp2->hin_itp = hp->hin_itp;
482     }
483    for (pi = 0; pi < mdp->mlocprmnum; pi++)
484     {
485      hp2 = &(iterp->scanhtab[pi2++]);
486      hrp2 = hp2->hrec;
487      hrp2->htyp = vpiParamAssign;
488      hrp2->hu.hnp = &(mdp->mlocprms[pi]);
489      hp2->hin_itp = hp->hin_itp;
490     }
491    break;
492   case vpiTask: case vpiFunction:
493    tskp = hrp->hu.htskp;
494 bld_tskiter:
495    nparams = tskp->tprmnum + tskp->tlocprmnum;
496    if ((nparams = tskp->tprmnum) <= 0) return(NULL);
497    iterp = __alloc_iter(nparams, &ihref);
498 
499    for (pi = 0, pi2 = 0; pi < tskp->tprmnum; pi++)
500     {
501      hp2 = &(iterp->scanhtab[pi2++]);
502      hrp2 = hp2->hrec;
503      hrp2->htyp = vpiParamAssign;
504      hrp2->hu.hnp = &(tskp->tsk_prms[pi]);
505      hp2->hin_itp = hp->hin_itp;
506      hrp2->hin_tskp = tskp;
507     }
508    for (pi = 0; pi < tskp->tlocprmnum; pi++)
509     {
510      hp2 = &(iterp->scanhtab[pi2++]);
511      hrp2 = hp2->hrec;
512      hrp2->htyp = vpiParamAssign;
513      hrp2->hu.hnp = &(tskp->tsk_locprms[pi]);
514      hp2->hin_itp = hp->hin_itp;
515      hrp2->hin_tskp = tskp;
516     }
517    break;
518   case vpiNamedBegin: case vpiNamedFork:
519    tskp = hrp->hu.htskp;
520    goto bld_tskiter;
521   default:
522    __vpi_err(1851, vpiError,
523     "unable to construct vpiParamAssign iterator for %s object",
524      __to_vpionam(__wrks2, hrp->htyp));
525  }
526  return(ihref);
527 }
528 
529 
530 /*
531  * build a IO decl iterator
532  *
533  * this is internally same as parameter (property values from net_t)
534  */
__bld_iodecl_stmt_iter(struct h_t * hp)535 extern vpiHandle __bld_iodecl_stmt_iter(struct h_t *hp)
536 {
537  register int32 ni, nports;
538  register struct h_t *hp2;
539  register struct net_t *np;
540  register struct hrec_t *hrp2;
541  vpiHandle ihref;
542  struct pviter_t *iterp;
543  struct mod_t *mdp;
544  struct task_t *tskp;
545  struct udp_t *udpp;
546  struct mod_pin_t *mpp;
547 
548  if (hp == NULL) return(__nil_iter_err(vpiIODecl));
549  ihref = NULL;
550  switch (hp->hrec->htyp) {
551   case vpiModule:
552    mdp = hp->hin_itp->itip->imsym->el.emdp;
553    /* module port is normal net form */
554    np = &(mdp->mnets[0]);
555    for (nports = 0; nports < mdp->mnnum; nports++, np++)
556     { if (np->iotyp != NON_IO) nports++; }
557    if (nports <= 0) return(NULL);
558 
559    iterp = __alloc_iter(nports, &ihref);
560    np = &(mdp->mnets[0]);
561    for (nports = 0, ni = 0; nports < mdp->mnnum; nports++, np++)
562     {
563      if (np->iotyp != NON_IO) continue;
564 
565      hp2 = &(iterp->scanhtab[ni]);
566      hrp2 = hp2->hrec;
567      hrp2->htyp = vpiIODecl;
568      hrp2->hu.hnp = np;
569      hp2->hin_itp = hp->hin_itp;
570      ni++;
571     }
572    break;
573   case vpiTask: case vpiFunction:
574    /* normal io decl handle is net - alt form only for udp is mod_port */
575    tskp = hp->hrec->hu.htskp;
576 bld_tsk_iodecls:
577    mdp = hp->hin_itp->itip->imsym->el.emdp;
578    np = &(tskp->tsk_regs[0]);
579    for (nports = 0, ni = 0; ni < tskp->trnum; nports++, np++)
580     { if (np->iotyp != NON_IO) nports++; }
581    if (nports <= 0) return(NULL);
582 
583    iterp = __alloc_iter(nports, &ihref);
584    np = &(tskp->tsk_regs[0]);
585    for (nports = 0, ni = 0; nports < tskp->trnum; nports++, np++)
586     {
587      if (np->iotyp != NON_IO) continue;
588 
589      hp2 = &(iterp->scanhtab[ni]);
590      hrp2 = hp2->hrec;
591      hrp2->htyp = vpiIODecl;
592      hrp2->hu.hnp = np;
593      hp2->hin_itp = hp->hin_itp;
594      hrp2->hin_tskp = tskp;
595      ni++;
596     }
597    break;
598   case vpiNamedBegin: case vpiNamedFork:
599    tskp = hp->hrec->hu.htskp;
600    goto bld_tsk_iodecls;
601   case vpiUdpDefn:
602    /* here io decl port is alternative mod port form */
603    /* LOOKATME - maybe should change Cver d.s. to store udp ports as nets */
604    udpp = hp->hrec->hu.hudpp;
605    /* DBG remove --- */
606    if (hp->hin_itp != NULL) __vpi_terr(__FILE__, __LINE__);
607    /* --- */
608    for (nports = 0, mpp = udpp->upins; mpp != NULL; mpp = mpp->mpnxt)
609     {
610      /* DBG remove --- */
611      if (mpp->mptyp == IO_UNKN || mpp->mptyp == IO_BID)
612       __vpi_terr(__FILE__, __LINE__);
613      /* --- */
614      nports++;
615     }
616    /* DBG remove --- */
617    if (nports <= 0) __vpi_terr(__FILE__, __LINE__);
618    /* --- */
619    iterp = __alloc_iter(nports, &ihref);
620    for (nports = 0, mpp = udpp->upins; mpp != NULL; mpp = mpp->mpnxt,
621     nports++)
622     {
623      hp2 = &(iterp->scanhtab[nports]);
624      hrp2 = hp2->hrec;
625      hrp2->htyp = vpiIODecl;
626      /* this must be actual udp port, not index since no table as with mod */
627      hrp2->hu.hmpp = mpp;
628      /* use unused itp field to point to containing */
629      hp2->hin_itp = (struct itree_t *) udpp;
630      /* alt form for io decl indicates in udp */
631      hrp2->htyp2 = vpiUdpDefn;
632     }
633    break;
634   default:
635    __vpi_err(1851, vpiError,
636     "unable to construct vpiIODecl iterator for %s object",
637     __to_vpionam(__wrks2, hp->hrec->htyp));
638  }
639  return(ihref);
640 }
641 
642 /*
643  * build a udp table line iterator
644  *
645  * note in Cver get value can only get string form - user must decompose
646  */
__bld_udpline_iter(struct h_t * rhp)647 extern vpiHandle __bld_udpline_iter(struct h_t *rhp)
648 {
649  register int32 uli;
650  register struct utline_t *utlp;
651  register struct hrec_t *hrp;
652  int32 nulines;
653  vpiHandle ihref;
654  struct udp_t *udpp;
655  struct h_t *hp;
656  struct pviter_t *iterp;
657 
658  if (rhp == NULL) return(__nil_iter_err(vpiTableEntry));
659  if (rhp->hrec->htyp != vpiUdpDefn)
660   {
661    __vpi_err(1838, vpiError,
662     "vpiTableEntry type 1-to-many iterator requires vpiUdpDefn object - %s illegal",
663     __to_vpionam(__wrks1, rhp->hrec->htyp));
664    return(NULL);
665   }
666  udpp = rhp->hrec->hu.hudpp;
667  for (nulines = 0, utlp = udpp->utlines; utlp != NULL; utlp = utlp->utlnxt)
668   nulines++;
669  /* this empty udp legal */
670  if (nulines <= 0) return(NULL);
671 
672  /* build the design wide iterator of all udps */
673  iterp = __alloc_iter(nulines, &ihref);
674  for (uli = 0, utlp = udpp->utlines; utlp != NULL; utlp = utlp->utlnxt, uli++)
675   {
676    hp = &(iterp->scanhtab[uli]);
677    hrp = hp->hrec;
678    hrp->htyp = vpiTableEntry;
679    hrp->hu.hutlp = utlp;
680    hp->hin_itp = (struct itree_t *) udpp;
681    hrp->hi = uli;
682   }
683  return(ihref);
684 }
685 
686 /*
687  * build an iterator for every word32 in array
688  *
689  * notice this builds a handle for every word32 better for large
690  * few bit (1) arrays to use vpi_handle_by_index
691  *
692  * in order to get parent of this handle, need to look at handle in
693  * iterator - only way to build arrword or vector bit handle
694  */
__bld_arrwrd_iterator(struct h_t * hp)695 extern vpiHandle __bld_arrwrd_iterator(struct h_t *hp)
696 {
697  register int32 ai, iti;
698  register struct hrec_t *hrp2;
699  int32 awid;
700  vpiHandle ihref;
701  struct net_t *np;
702  struct h_t *hp2;
703  struct pviter_t *iterp;
704 
705  if (hp == NULL) return(__nil_iter_err(vpiMemoryWord));
706  if (hp->hrec->htyp != vpiMemory)
707   {
708    __vpi_err(1857, vpiError,
709     "vpiMemoryWord 1-to-many iterator from object %s illegal - must be vpiMemory",
710     __to_vpionam(__wrks1, hp->hrec->htyp));
711    return(NULL);
712   }
713  /* know hp is array (not array word32) handle */
714  np = hp->hrec->hu.hnp;
715  awid = __get_arrwide(np);
716  /* DBG remove --- */
717  if (awid <= 0) __vpi_terr(__FILE__, __LINE__);
718  /* --- */
719  iterp = __alloc_iter(awid, &ihref);
720  for (iti = 0, ai = awid - 1; ai >= 0; ai--, iti++)
721   {
722    hp2 = &(iterp->scanhtab[iti]);
723    hrp2 = hp2->hrec;
724    hrp2->htyp = vpiMemoryWord;
725    hrp2->hu.hnp = np;
726    hrp2->hi = ai;
727    hrp2->bith_ndx = TRUE;
728    hp2->hin_itp = hp->hin_itp;
729    hrp2->hin_tskp = hp->hrec->hin_tskp;
730   }
731  return(ihref);
732 }
733 
734 /*
735  * build an iterator for every bit of a reg or net or associated object
736  *
737  * also for ports, wire drivers for vectored nets, and scheduled wire driver
738  * put value events
739  *
740  * notice there is no one-to-many connection for vpi_ driver to bit driver
741  */
__bld_bitof_iterator(struct h_t * hp)742 extern vpiHandle __bld_bitof_iterator(struct h_t *hp)
743 {
744  register int32 i, iti;
745  register struct hrec_t *hrp2;
746  vpiHandle ihref;
747  struct net_t *np;
748  struct h_t *hp2;
749  struct mod_t *mdp;
750  struct mod_pin_t *mpp;
751  struct pviter_t *iterp;
752 
753  if (hp == NULL) return(__nil_iter_err(vpiBit));
754  switch (hp->hrec->htyp) {
755   case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
756    np = hp->hrec->hu.hnp;
757    if (!np->n_isavec) return(NULL);
758    /* know nwid never 0 or will not get here */
759    iterp = __alloc_iter(np->nwid, &ihref);
760    /* SJM - 06/14/99 - need 2 indices since bit of always [h:l] order */
761    for (i = np->nwid - 1, iti = 0; i >= 0; i--, iti++)
762     {
763      hp2 = &(iterp->scanhtab[iti]);
764      hrp2 = hp2->hrec;
765      hrp2->htyp = __to_vpinetbithtyp(np->ntyp);
766      hrp2->hu.hnp = np;
767      hrp2->hi = i;
768      hrp2->bith_ndx = TRUE;
769      hp2->hin_itp = hp->hin_itp;
770      hrp2->hin_tskp = hp->hrec->hin_tskp;
771     }
772    break;
773   case vpiPort:
774    mdp = hp->hin_itp->itip->imsym->el.emdp;
775    mpp = &(mdp->mpins[hp->hrec->hu.hpi]);
776    /* returns nil for scalar port - no bits */
777    if (mpp->mpwide == 1) return(NULL);
778    iterp = __alloc_iter(mpp->mpwide, &ihref);
779    /* for port bit handles itp determines port list, hu.hpi port, and hi */
780    /* must be h:0 to match bits of connected vector */
781    /* SJM - 06/14/99 - need 2 indices since bit of always [h:l] order */
782    for (i = mpp->mpwide - 1, iti = 0; i >= 0; i--, iti++)
783     {
784      hp2 = &(iterp->scanhtab[iti]);
785      hrp2 = hp2->hrec;
786      hrp2->htyp = vpiPortBit;
787      hrp2->hu.hpi = hp->hrec->hu.hpi;
788      hrp2->hi = i;
789      hp2->hin_itp = hp->hin_itp;
790      hrp2->hin_tskp = hp->hrec->hin_tskp;
791     }
792    break;
793   default:
794    __vpi_err(1859, vpiError,
795     "vpiBit 1-to-many iterator from object %s illegal",
796     __to_vpionam(__wrks1, hp->hrec->htyp));
797    return(NULL);
798   }
799  return(ihref);
800 }
801 
802 /*
803  * build iterator of primitive (gate) terminals
804  *
805  * notice needed so parent is primitive (gate) not scope
806  */
__bld_primterm_iterator(struct h_t * hp)807 extern vpiHandle __bld_primterm_iterator(struct h_t *hp)
808 {
809  register int32 pi;
810  register struct hrec_t *hrp2;
811  vpiHandle ihref;
812  struct gate_t *gp;
813  struct itree_t *itp;
814  struct h_t *hp2;
815  struct hrec_t *hrp;
816  struct pviter_t *iterp;
817 
818  if (hp == NULL) return(__nil_iter_err(vpiPrimTerm));
819  hrp = hp->hrec;
820  if (hrp->htyp != vpiGate && hrp->htyp != vpiUdp && hrp->htyp != vpiSwitch)
821   {
822    __vpi_err(1855, vpiError,
823     "vpiPrimTerm 1-to-many iterator from %s illegal - member of primitive class required",
824     __to_vpionam(__wrks1, hrp->htyp));
825    return(NULL);
826   }
827  gp = hrp->hu.hgp;
828  itp = hp->hin_itp;
829  /* DBG remove --- */
830  if (gp->gpnum == 0) __vpi_terr(__FILE__, __LINE__);
831  /* --- */
832  iterp = __alloc_iter((int32) gp->gpnum, &ihref);
833  for (pi = 0; pi < (int32) gp->gpnum; pi++)
834   {
835    hp2 = &(iterp->scanhtab[pi]);
836    hrp2 = hp2->hrec;
837    hrp2->htyp = vpiPrimTerm;
838    hrp2->hi = pi;
839    hrp2->hu.hgp = gp;
840    hp2->hin_itp = itp;
841   }
842  return(ihref);
843 }
844 
845 
846 /*
847  * build iterators for vpi Port selector
848  *
849  * iterator for reg/wire is all in module ports that the handle connects to
850  */
__bld_port_iterator(struct h_t * hp)851 extern vpiHandle __bld_port_iterator(struct h_t *hp)
852 {
853  if (hp == NULL) return(__nil_iter_err(vpiPort));
854  switch (hp->hrec->htyp) {
855   case vpiModule: return(bld_inmod_port_iter(hp));
856   case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
857    /* iterator is usually 1 port net connects to (only more if jumpered) */
858    /* this returns port handles even if selects (i.e. any overlap) */
859    return(bld_netmdport_iter(hp));
860   case vpiNetBit: case vpiRegBit: case vpiVarSelect:
861    /* iterator is usually the one port the bit connects to */
862    /* this returns port bit handles for the one bit */
863    return(bld_netbitmdport_iter(hp));
864   default:
865    __vpi_err(1861, vpiError,
866     "vpiPort 1-to-many iterator from %s illegal - for in module or hiconn module ports",
867     __to_vpionam(__wrks1, hp->hrec->htyp));
868   }
869  return(NULL);
870 }
871 
872 /*
873  * build ports in module iterator (easiest)
874  * since in module and have inst. do not need parent handle
875  */
bld_inmod_port_iter(struct h_t * hp)876 static vpiHandle bld_inmod_port_iter(struct h_t *hp)
877 {
878  register int32 pi;
879  register struct h_t *hp2;
880  register struct hrec_t *hrp2;
881  struct mod_t *mdp;
882  struct itree_t *itp;
883  struct pviter_t *iterp;
884  vpiHandle ihref;
885 
886  itp = hp->hin_itp;
887  mdp = itp->itip->imsym->el.emdp;
888  if (mdp->mpnum <= 0) return(NULL);
889  iterp = __alloc_iter(mdp->mpnum, &ihref);
890  for (pi = 0; pi < mdp->mpnum; pi++)
891   {
892    hp2 = &(iterp->scanhtab[pi]);
893    hrp2 = hp2->hrec;
894    hrp2->htyp = vpiPort;
895    /* using index so can get instance port index too */
896    hrp2->hu.hpi = pi;
897    hp2->hin_itp = itp;
898   }
899  return(ihref);
900 }
901 
902 /*
903  * build a statement iterator from a named or unnamed? block
904  * unnamed blocks usually marked with bit (but S_UNLBK in fork-join)
905  */
__bld_stmt_iterator(struct h_t * hp)906 extern vpiHandle __bld_stmt_iterator(struct h_t *hp)
907 {
908  register struct hrec_t *hrp;
909  struct st_t *stp;
910  struct task_t *tskp;
911 
912  if (hp == NULL) return(__nil_iter_err(vpiStmt));
913  hrp = hp->hrec;
914  switch (hrp->htyp) {
915   case vpiFork:
916    return(bld_fjlist_iter(hrp->hu.hstp, hp->hin_itp, hrp->hin_tskp));
917 
918   case vpiBegin:
919    stp = hrp->hu.hstp;
920    /* this statement only for use in fork-join */
921    if (stp->stmttyp == S_UNBLK)
922     {
923      /* pass first statement of block */
924      stp = stp->st.sbsts;
925      /* here iterator is in same scope as unnamed block */
926      return(bld_listofstmts_iter(stp, hp->hin_itp, hrp->hin_tskp));
927     }
928    if (!stp->st_unbhead) __vpi_terr(__FILE__, __LINE__);
929    /* normal un-named block just has bit set in first statement */
930    return(bld_listofstmts_iter(stp, hp->hin_itp, hrp->hin_tskp));
931 
932   case vpiNamedFork:
933    tskp = hrp->hu.htskp;
934    return(bld_fjlist_iter(tskp->tskst, hp->hin_itp, tskp));
935 
936   case vpiNamedBegin:
937    tskp = hrp->hu.htskp;
938    /* here these are in the named block scope not the task stmt */
939    /* notice hin taskp is name block task itself */
940    return(bld_listofstmts_iter(tskp->tskst, hp->hin_itp, tskp));
941   default:
942    __vpi_err(1869, vpiError,
943     "vpiStmt 1-to-many iterator from %s illegal - for blocks only",
944    __to_vpionam(__wrks1, hrp->htyp));
945  }
946  return(NULL);
947 }
948 
949 /*
950  * build a fork-join iterator - each statement from list
951  */
bld_fjlist_iter(struct st_t * stp,struct itree_t * itp,struct task_t * tskp)952 static vpiHandle bld_fjlist_iter(struct st_t *stp, struct itree_t *itp,
953  struct task_t *tskp)
954 {
955  register int32 si, fji;
956  register struct st_t *fjstp;
957  int32 snum;
958  vpiHandle ihref;
959  struct pviter_t *iterp;
960  struct h_t *hp;
961  struct hrec_t *hrp;
962  struct st_t *stp3;
963 
964  /* these do not go into iterators */
965  for (snum = fji = 0;; fji++)
966   {
967    if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
968 
969    /* DBG remove -- */
970    /* think can not have goto here */
971    if (fjstp->rl_stmttyp == S_GOTO) __vpi_terr(__FILE__, __LINE__);
972    /* -- */
973    /* SJM 09/24/01 - for these inserted stmts, add next to iterator */
974    if (fjstp->rl_stmttyp == S_REPSETUP || fjstp->rl_stmttyp == S_FORASSGN
975     || fjstp->rl_stmttyp == S_REPDCSETUP) fjstp = fjstp->stnxt;
976    snum++;
977   }
978 
979  /* LOOKATME - can this be none */
980  if (snum <= 0) return(NULL);
981 
982  iterp = __alloc_iter(snum, &ihref);
983  for (fji = 0, si = 0;; fji++, si++)
984   {
985    if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
986 
987    /* these do not go into iterator */
988    /* SJM 09/24/01 - for these inserted stmts, add next to iterator */
989    if (fjstp->rl_stmttyp == S_REPSETUP || fjstp->rl_stmttyp == S_FORASSGN
990     || fjstp->rl_stmttyp == S_REPDCSETUP) fjstp = fjstp->stnxt;
991 
992    hp = &(iterp->scanhtab[si]);
993    stp3 = fjstp;
994    hrp = hp->hrec;
995    hrp->htyp = __to_vpi_stmttyp(&stp3);
996 
997    /* skipping special setup stmts, no need to use next */
998    if (hrp->htyp == vpiNamedBegin || hrp->htyp == vpiNamedFork)
999     hrp->hu.htskp = fjstp->st.snbtsk;
1000    else hrp->hu.hstp = fjstp;
1001 
1002    hp->hin_itp = itp;
1003    hrp->hin_tskp = tskp;
1004   }
1005  return(ihref);
1006 }
1007 
1008 /*
1009  * build statement iterator from the first statement
1010  */
bld_listofstmts_iter(struct st_t * stp,struct itree_t * itp,struct task_t * in_tskp)1011 static vpiHandle bld_listofstmts_iter(struct st_t *stp, struct itree_t *itp,
1012  struct task_t *in_tskp)
1013 {
1014  register int32 si;
1015  register struct st_t *stp2;
1016  register struct hrec_t *hrp;
1017  int32 snum;
1018  vpiHandle ihref;
1019  struct pviter_t *iterp;
1020  struct h_t *hp;
1021  struct st_t *stp3;
1022 
1023  for (snum = 0, stp2 = stp; stp2 != NULL; stp2 = stp2->stnxt)
1024   {
1025    if (stp2->rl_stmttyp == S_GOTO) break;
1026    if (stp2->rl_stmttyp == S_REPSETUP || stp2->rl_stmttyp == S_FORASSGN
1027     || stp2->rl_stmttyp == S_REPDCSETUP) continue;
1028    snum++;
1029   }
1030  /* LOOKATME - can this be none */
1031  if (snum <= 0) return(NULL);
1032  iterp = __alloc_iter(snum, &ihref);
1033  for (stp2 = stp, si = 0; stp2 != NULL; stp2 = stp2->stnxt)
1034   {
1035    if (stp2->rl_stmttyp == S_GOTO) break;
1036    /* these do not go into iterators */
1037    if (stp2->rl_stmttyp == S_REPSETUP || stp2->rl_stmttyp == S_FORASSGN
1038     || stp2->rl_stmttyp == S_REPDCSETUP)
1039     continue;
1040 
1041    /* his works for named begin and fj blocks because hu if statement */
1042    /* links in d.s. for going between 2 */
1043    hp = &(iterp->scanhtab[si++]);
1044    hrp = hp->hrec;
1045    /* know will never be for assign or repeat where need to move to nxt */
1046    stp3 = stp2;
1047    hrp->htyp = __to_vpi_stmttyp(&stp3);
1048 
1049    /* skipping special setup stmts, no need to use next */
1050    if (hrp->htyp == vpiNamedBegin || hrp->htyp == vpiNamedFork)
1051     hrp->hu.htskp = stp2->st.snbtsk;
1052    else hrp->hu.hstp = stp2;
1053 
1054    hp->hin_itp = itp;
1055    hrp->hin_tskp = in_tskp;
1056   }
1057  return(ihref);
1058 }
1059 
1060 /*
1061  * convert from v.h stmt type to handle constant for stmt class
1062  *
1063  * tricky because for for assign and repeat setup added pseudo
1064  * statements must move to next and return type of next, i.e. the repeat
1065  * or for statement itself
1066  *
1067  * here ignore unnamed block header since know only called for block contents
1068  */
__to_vpi_stmttyp(struct st_t ** stpp)1069 extern word32 __to_vpi_stmttyp(struct st_t **stpp)
1070 {
1071  struct task_t *tskp;
1072  struct st_t *stp;
1073 
1074  stp = *stpp;
1075  switch ((byte) stp->stmttyp) {
1076   /* blocks statements */
1077   case S_NAMBLK:
1078    /* use task type for statement type */
1079    tskp = stp->st.snbtsk;
1080    if (tskp->tsktyp == FORK) return(vpiNamedFork);
1081    if (tskp->tsktyp == Begin) return(vpiNamedBegin);
1082    __vpi_terr(__FILE__, __LINE__);
1083    break;
1084   case S_UNBLK: return(vpiBegin);
1085   /* the statement is the header that points to the contents fj stlst */
1086   case S_UNFJ: return(vpiFork);
1087 
1088   /* atomic statements */
1089   case S_IF:
1090    if (stp->st.sif.elsest == NULL) return(vpiIf);
1091    return(vpiIfElse);
1092   case S_WHILE: return(vpiWhile);
1093   case S_FOREVER: return(vpiForever);
1094   case S_REPEAT: return(vpiRepeat);
1095   case S_WAIT: return(vpiWait);
1096   case S_CASE: return(vpiCase);
1097   case S_FOR: return(vpiFor);
1098   case S_REPDCSETUP:
1099    *stpp = stp->stnxt;
1100    /* DBG remove --- */
1101    if (stp->stnxt == NULL) __vpi_terr(__FILE__, __LINE__);
1102    if (stp->stnxt->stmttyp == S_FORASSGN || stp->stnxt->stmttyp == S_REPSETUP
1103     || stp->stnxt->stmttyp == S_REPDCSETUP)
1104     __vpi_terr(__FILE__, __LINE__);
1105    /* --- */
1106    /* this is always assign mayhbe non blocking or rhs dctrl */
1107    return(vpiAssignment);
1108   case S_DELCTRL:
1109    if (stp->st.sdc->dctyp == DC_DELAY) return(vpiDelayControl);
1110    if (stp->st.sdc->dctyp == DC_EVENT) return(vpiEventControl);
1111    if (stp->st.sdc->dctyp == DC_RHSEVENT ||
1112     stp->st.sdc->dctyp == DC_RHSDELAY) return(vpiAssignment);
1113    __vpi_terr(__FILE__, __LINE__);
1114    break;
1115   case S_CAUSE: return(vpiEventStmt);
1116   /* properties in vpi_ distinguish */
1117   case S_PROCA: case S_NBPROCA: case S_RHSDEPROCA:
1118    return(vpiAssignment);
1119   case S_FORASSGN:
1120    /* need the following for - always followed by for */
1121    *stpp = stp->stnxt;
1122    /* DBG remove --- */
1123    if (stp->stnxt == NULL) __vpi_terr(__FILE__, __LINE__);
1124    if (stp->stnxt->stmttyp == S_FORASSGN || stp->stnxt->stmttyp == S_REPSETUP
1125     || stp->stnxt->stmttyp == S_REPDCSETUP)
1126     __vpi_terr(__FILE__, __LINE__);
1127    /* --- */
1128    return(vpiFor);
1129   case S_REPSETUP:
1130    *stpp = stp->stnxt;
1131    /* DBG remove --- */
1132    if (stp->stnxt == NULL) __vpi_terr(__FILE__, __LINE__);
1133    if (stp->stnxt->stmttyp == S_FORASSGN || stp->stnxt->stmttyp == S_REPSETUP
1134     || stp->stnxt->stmttyp == S_REPDCSETUP)
1135     __vpi_terr(__FILE__, __LINE__);
1136    /* --- */
1137    return(vpiRepeat);
1138   case S_QCONTA:
1139    if (stp->st.sqca->qcatyp == ASSIGN) return(vpiAssignStmt);
1140    if (stp->st.sqca->qcatyp == FORCE) return(vpiForce);
1141    __vpi_terr(__FILE__, __LINE__);
1142    break;
1143   case S_QCONTDEA:
1144    if (stp->st.sqcdea.qcdatyp == DEASSIGN) return(vpiRelease);
1145    if (stp->st.sqcdea.qcdatyp == RELEASE) return(vpiDeassign);
1146    __vpi_terr(__FILE__, __LINE__);
1147    break;
1148   case S_DSABLE: return(vpiDisable);
1149   case S_TSKCALL:
1150    if (stp->st.stkc.tsksyx->lu.sy->sytyp == SYM_STSK) return(vpiSysTaskCall);
1151    return(vpiTaskCall);
1152 
1153   case S_NULL: case S_STNONE: return(vpiNullStmt);
1154   default: __vpi_terr(__FILE__, __LINE__);
1155  }
1156  return(0);
1157 }
1158 
1159 /*
1160  * build the top level all vpi_ systf iterator
1161  *
1162  * original handles build from systf register not freeable but this
1163  * iterator is
1164  * notice only thing can do with handles in itertor is get systf info
1165  */
__bld_systf_iterator(struct h_t * hp)1166 extern vpiHandle __bld_systf_iterator(struct h_t *hp)
1167 {
1168  register int32 ti;
1169  register struct hrec_t *hrp2;
1170  int32 num_vpi_systfs;
1171  vpiHandle ihref;
1172  struct pviter_t *iterp;
1173  struct h_t *hp2;
1174 
1175  if (hp != NULL)
1176   {
1177    __vpi_err(1866, vpiError,
1178     "vpi_iterate for vpiUserSystf requires NULL handle - %s illegal",
1179     __to_vpionam(__wrks1, hp->hrec->htyp));
1180    return(NULL);
1181   }
1182  num_vpi_systfs = __last_systf - __last_veriusertf;
1183  if (num_vpi_systfs <= 0) return(NULL);
1184  iterp = __alloc_iter(num_vpi_systfs, &ihref);
1185  for (ti = 0; ti < num_vpi_systfs; ti++)
1186   {
1187    hp2 = &(iterp->scanhtab[ti]);
1188    hrp2 = hp2->hrec;
1189    hrp2->htyp = vpiUserSystf;
1190    /* handle must be number (i.e. 1000 + tf_ number + pos.) */
1191    hrp2->hi = __last_veriusertf + ti + 1;
1192    /* this handle does not have itree loc. since not the call */
1193   }
1194  return(ihref);
1195 }
1196 
1197 /*
1198  * build task or function including system argument list iterator
1199  */
__bld_tfargexpr_iterator(struct h_t * hp)1200 extern vpiHandle __bld_tfargexpr_iterator(struct h_t *hp)
1201 {
1202  register struct hrec_t *hrp;
1203  struct expr_t *argxp;
1204  struct tskcall_t *tkcp;
1205 
1206  if (hp == NULL) return(__nil_iter_err(vpiArgument));
1207  hrp = hp->hrec;
1208  switch (hrp->htyp) {
1209   /* for func def. first argment is return value but for call 1st is arg */
1210   case vpiFuncCall: case vpiSysFuncCall:
1211    argxp = hrp->hu.hxp->ru.x;
1212    if (argxp == NULL) return(NULL);
1213    return(bld_listofexprs_iter(argxp, hp->hin_itp, hrp->hin_tskp));
1214   case vpiTask: case vpiSysTaskCall:
1215    tkcp = &(hrp->hu.hstp->st.stkc);
1216    if (tkcp->targs == NULL) return(NULL);
1217    return(bld_listofexprs_iter(tkcp->targs, hp->hin_itp, hrp->hin_tskp));
1218   default:
1219    __vpi_err(1879, vpiError,
1220     "vpiArgument 1-to-many iterator from %s illegal - for tasks and functions",
1221    __to_vpionam(__wrks1, hrp->htyp));
1222  }
1223  return(NULL);
1224 }
1225 
1226 /*
1227  * build list of expressions iterator (know at least one or not called)
1228  * passed with first arg - can be nil for no arguments
1229  */
bld_listofexprs_iter(struct expr_t * argx,struct itree_t * itp,struct task_t * tskp)1230 static vpiHandle bld_listofexprs_iter(struct expr_t *argx, struct itree_t *itp,
1231  struct task_t *tskp)
1232 {
1233  register int32 xi, numxps;
1234  register struct expr_t *xp2;
1235  vpiHandle ihref;
1236  struct pviter_t *iterp;
1237  struct h_t *hp;
1238 
1239  /* know there will always be 1 */
1240  for (numxps = 0, xp2 = argx; xp2 != NULL; xp2 = xp2->ru.x) numxps++;
1241  if (numxps <= 0) return(NULL);
1242  iterp = __alloc_iter(numxps, &ihref);
1243  for (xp2 = argx, xi = 0; xp2 != NULL; xp2 = xp2->ru.x, xi++)
1244   {
1245    hp = &(iterp->scanhtab[xi]);
1246    /* expr. object can also be scopes if xmr object */
1247    mk2_exprclass_handle(hp, xp2->lu.x, itp, tskp);
1248   }
1249  return(ihref);
1250 }
1251 
1252 /*
1253  * ROUTINES TO BUILD TCHK AND PATH ITERATORS
1254  */
1255 
1256 /*
1257  * build a module specify path iterator (indices and three types)
1258  */
__bld_pthterm_iterator(struct h_t * hp,word32 itype)1259 extern vpiHandle __bld_pthterm_iterator(struct h_t *hp, word32 itype)
1260 {
1261  register int32 pi;
1262  register struct hrec_t *hrp2;
1263  int32 numpes;
1264  struct spcpth_t *pthp;
1265  vpiHandle ihref;
1266  struct pviter_t *iterp;
1267  struct h_t *hp2;
1268  struct hrec_t *hrp;
1269  struct expr_t *xp;
1270 
1271  hrp = hp->hrec;
1272  if (hrp->htyp != vpiModPath)
1273   {
1274    __vpi_err(1858, vpiError,
1275     "%s 1-to-many iterator requires vpiModPath reference handle - %s illegal",
1276     __to_vpionam(__wrks1, itype), __to_vpionam(__wrks2, hrp->htyp));
1277    return(NULL);
1278   }
1279  pthp = hrp->hu.hpthp;
1280  if (itype == vpiModPathIn || itype == vpiModPathOut)
1281   {
1282    if (itype == vpiModPathIn) numpes = pthp->last_pein + 1;
1283    else numpes = pthp->last_peout + 1;
1284    goto bld_iter;
1285   }
1286  /* know itype already checked */
1287  /* DBG remove --- */
1288  if (itype != vpiModDataPathIn) __vpi_terr(__FILE__, __LINE__);
1289  /* --- */
1290 
1291  if ((xp = pthp->datasrcx) == NULL) return(NULL);
1292 
1293  if (xp->optyp != FCCOM) numpes = 1;
1294  /* FCCOM list */
1295  else { for (numpes = 0; xp != NULL; xp = xp->ru.x) numpes++; }
1296 
1297 bld_iter:
1298  if (numpes <= 0) return(NULL);
1299  iterp = __alloc_iter(numpes, &ihref);
1300  for (pi = 0; pi < numpes; pi++)
1301   {
1302    hp2 = &(iterp->scanhtab[pi]);
1303    hrp2 = hp2->hrec;
1304    hrp2->htyp = vpiPathTerm;
1305    hrp2->htyp2 = itype;
1306    hrp2->hu.hpthp = pthp;
1307    /* this is index, path term type determines how accessed */
1308    hrp2->hi = pi;
1309    hp2->hin_itp = hp->hin_itp;
1310   }
1311  return(ihref);
1312 }
1313 
1314 /*
1315  * routine to build iterator of vpi Tchk Terms that a net or bit is in
1316  *
1317  * notifier's not included since not really part of circuit (modeling addon)
1318  * and no a terminal
1319  * tchk terminals must be wires but not necessarily I/O ports
1320  */
__bld_netin_tchkterms(struct h_t * hp)1321 extern vpiHandle __bld_netin_tchkterms(struct h_t *hp)
1322 {
1323  register int32 hi;
1324  register struct hrec_t *hrp;
1325  int32 ndx, nterms;
1326  vpiHandle ihref;
1327  struct net_t *np;
1328  struct pviter_t *iterp;
1329 
1330  if (hp == NULL) return(__nil_iter_err(vpiTchkTerm));
1331  hrp = hp->hrec;
1332  if (hrp->htyp != vpiNet && hrp->htyp != vpiNetBit)
1333   {
1334 bad_bit:
1335    __vpi_err(1872, vpiError,
1336     "vpiTchkTerm 1-to-many iterator from %s illegal - vpiNet or constant vpiNetBit only",
1337     __to_vpionam(__wrks1, hrp->htyp));
1338    return(NULL);
1339   }
1340  if (hrp->htyp == vpiNetBit)
1341   {
1342    if (!hrp->bith_ndx) goto bad_bit;
1343    ndx = hrp->hi;
1344   }
1345  else ndx = -1;
1346  np = hrp->hu.hnp;
1347 
1348  nterms = bld_net_tchkterms(np, (struct itree_t *) hp->hin_itp, ndx);
1349  if (nterms <= 0) return(NULL);
1350 
1351  iterp = __alloc_iter(nterms, &ihref);
1352  memcpy(iterp->scanhtab, __ithtab, nterms*sizeof(struct h_t));
1353  memcpy(iterp->ihrectab, __ithrectab, nterms*sizeof(struct hrec_t));
1354 
1355  for (hi = 0; hi < nterms; hi++)
1356   {
1357    iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
1358   }
1359  return(ihref);
1360 }
1361 
1362 /*
1363  * build timing check terminals connected to net index ndx
1364  *
1365  * -1 for all of wire
1366  */
bld_net_tchkterms(struct net_t * np,struct itree_t * itp,int32 ndx)1367 static int32 bld_net_tchkterms(struct net_t *np, struct itree_t *itp, int32 ndx)
1368 {
1369  register int32 cnt;
1370  register struct net_pin_t *npp;
1371  register struct h_t *hp2;
1372  register struct hrec_t *hrp2;
1373  struct tchk_t *tcp;
1374  struct tchg_t *tchgp;
1375 
1376  __push_itstk(itp);
1377  /* for net bit, if any bit in range then entire terminal */
1378  for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
1379   {
1380    if (npp->npntyp != NP_TCHG) continue;
1381 
1382    /* will be one for each event, since just need tchk use only start ev */
1383    if (npp->chgsubtyp != NPCHG_TCSTART) continue;
1384 
1385    /* know tchk terminals are wires or selects (not globals) */
1386    tchgp = npp->elnpp.etchgp;
1387    tcp = tchgp->chgu.chgtcp;
1388    if (termexpr_matches(tcp->startxp, np, ndx))
1389     {
1390      if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
1391      hp2 = &(__ithtab[cnt]);
1392      hp2->hin_itp = itp;
1393 
1394      hrp2 = &(__ithrectab[cnt++]);
1395      __init_hrec(hrp2);
1396      /* not using alloc iter so need to set in iter bit explicitly */
1397      hrp2->in_iter = TRUE;
1398      hrp2->htyp = vpiTchkTerm;
1399      hrp2->htyp2 = vpiTchkRefTerm;
1400      hrp2->hu.htcp = tcp;
1401      /* only need to set cross link in newly added one */
1402      hp2->hrec = hrp2;
1403     }
1404    if (termexpr_matches(tcp->chkxp, np, ndx))
1405     {
1406      if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
1407      hp2 = &(__ithtab[cnt]);
1408      hp2->hin_itp = itp;
1409 
1410      hrp2 = &(__ithrectab[cnt++]);
1411      __init_hrec(hrp2);
1412      hrp2->in_iter = TRUE;
1413      hrp2->htyp = vpiTchkTerm;
1414      hrp2->htyp2 = vpiTchkDataTerm;
1415      hrp2->hu.htcp = tcp;
1416      /* only need to set cross link in newly added one */
1417      hp2->hrec = hrp2;
1418     }
1419   }
1420  __pop_itstk();
1421  return(cnt);
1422 }
1423 
1424 /*
1425  * return T if term matches net and bit (ndx == -1 for all)
1426  *
1427  * this require itree context to be pushed onto itstk
1428  */
termexpr_matches(struct expr_t * xp,struct net_t * np,int32 ndx)1429 static int32 termexpr_matches(struct expr_t *xp, struct net_t *np, int32 ndx)
1430 {
1431  int32 bi1, bi2;
1432  struct net_t *np2;
1433 
1434  if (xp == NULL) return(FALSE);
1435  if (xp->optyp == ID)
1436   {
1437    if (xp->lu.sy->el.enp == np) return(TRUE);
1438    return(FALSE);
1439   }
1440  if (xp->optyp == LSB)
1441   {
1442    np2 = xp->lu.x->lu.sy->el.enp;
1443    if (np != np2) return(FALSE);
1444    if (ndx == -1) return(TRUE);
1445    bi1 = __comp_ndx(np, xp->ru.x);
1446    if (bi1 == ndx) return(TRUE);
1447    return(FALSE);
1448   }
1449  else if (xp->optyp == PARTSEL)
1450   {
1451    np2 = xp->lu.x->lu.sy->el.enp;
1452    if (np != np2) return(FALSE);
1453    if (ndx == -1) return(TRUE);
1454    bi1 = (int32) __contab[xp->ru.x->lu.x->ru.xvi];
1455    bi2 = (int32) __contab[xp->ru.x->ru.x->ru.xvi];
1456    if (ndx > bi1 || ndx < bi2) return(FALSE);
1457    return(TRUE);
1458   }
1459  else __vpi_terr(__FILE__, __LINE__);
1460  return(FALSE);
1461 }
1462 
1463 /*
1464  * grow global work handle table (must add at least addnum)
1465  */
__grow_htab(int32 addnum)1466 extern void __grow_htab(int32 addnum)
1467 {
1468  register int32 iti;
1469  int32 old_ithtsiz, nnum, osize, nsize, ohrsize, nhrsize;
1470 
1471  /* only allocate if accessing driver/load style handles at all */
1472  if (__ithtsiz == 0)
1473   {
1474    nnum = 1000 + addnum;
1475    __ithtab = (struct h_t *) __my_malloc(nnum*sizeof(struct h_t));
1476    __ithrectab = (struct hrec_t *) __my_malloc(nnum*sizeof(struct hrec_t));
1477    __ithtsiz = nnum;
1478    return;
1479   }
1480  old_ithtsiz = __ithtsiz;
1481  osize = old_ithtsiz*sizeof(struct h_t);
1482  ohrsize = old_ithtsiz*sizeof(struct hrec_t);
1483  __ithtsiz = addnum + (3*__ithtsiz)/2;
1484  nsize = __ithtsiz*sizeof(struct h_t);
1485  nhrsize = __ithtsiz*sizeof(struct hrec_t);
1486  __ithtab = (struct h_t *) __my_realloc((char *) __ithtab, osize, nsize);
1487  __ithrectab = (struct hrec_t *) __my_realloc((char *) __ithrectab,
1488   ohrsize, nhrsize);
1489 
1490  /* SJM 10/23/00 - must reconnect all cross links in case relloced */
1491  /* just need to reset all in previous copied part */
1492  for (iti = 0; iti < old_ithtsiz; iti++)
1493   { __ithtab[iti].hrec = &(__ithrectab[iti]); }
1494 }
1495 
1496 /*
1497  * grow 2nd for subtree processing  global work handle table
1498  */
__grow_htab2(int32 addnum)1499 extern void __grow_htab2(int32 addnum)
1500 {
1501  register int32 iti;
1502  int32 old_ithtsiz2, nnum, osize, nsize, ohrsize, nhrsize;
1503 
1504  /* only allocate if accessing driver/load style handles at all */
1505  if (__ithtsiz2 == 0)
1506   {
1507    nnum = 1000 + addnum;
1508    __ithtab2 = (struct h_t *) __my_malloc(nnum*sizeof(struct h_t));
1509    __ithrectab2 = (struct hrec_t *) __my_malloc(nnum*sizeof(struct hrec_t));
1510    __ithtsiz2 = nnum;
1511    return;
1512   }
1513  old_ithtsiz2 = __ithtsiz2;
1514  osize = old_ithtsiz2*sizeof(struct h_t);
1515  ohrsize = old_ithtsiz2*sizeof(struct hrec_t);
1516  __ithtsiz2 = addnum + (3*__ithtsiz2)/2;
1517  nsize = __ithtsiz2*sizeof(struct h_t);
1518  nhrsize = __ithtsiz2*sizeof(struct hrec_t);
1519  __ithtab2 = (struct h_t *) __my_realloc((char *) __ithtab2, osize, nsize);
1520  __ithrectab2 = (struct hrec_t *) __my_realloc((char *) __ithrectab2,
1521   ohrsize, nhrsize);
1522 
1523  /* SJM 10/23/00 - must reconnect all cross links in case relloced */
1524  /* just need to reset all in previous copied part */
1525  for (iti = 0; iti < old_ithtsiz2; iti++)
1526   { __ithtab2[iti].hrec = &(__ithrectab2[iti]); }
1527 }
1528 
1529 /*
1530  * routine to build iterator of vpi path src and dst terms net is in
1531  *
1532  * vpiModDataPathTerm not include since not path source or dest (cond.)
1533  * paths must be wires that are input/inout (source) and output/inout (dest)
1534  *
1535  * path terms must be wires since input/inout are lvalues and path
1536  * destinations need delays so must be wire
1537  */
__bld_netin_pthterms(struct h_t * hp)1538 extern vpiHandle __bld_netin_pthterms(struct h_t *hp)
1539 {
1540  register int32 hi;
1541  register struct hrec_t *hrp;
1542  int32 ndx, nterms;
1543  vpiHandle ihref;
1544  struct net_t *np;
1545  struct pviter_t *iterp;
1546 
1547  if (hp == NULL) return(__nil_iter_err(vpiPathTerm));
1548  hrp = hp->hrec;
1549  if (hrp->htyp != vpiNet && hrp->htyp != vpiNetBit)
1550   {
1551 bad_bit:
1552    __vpi_err(1873, vpiError,
1553     "vpiPathTerm 1-to-many iterator from %s illegal - vpiNet or vpiNetBit (constant) only",
1554     __to_vpionam(__wrks1, hrp->htyp));
1555    return(NULL);
1556   }
1557  np = hrp->hu.hnp;
1558  if (hrp->htyp == vpiNetBit)
1559   {
1560    /* know this is T unless variable select - only works for constants */
1561    if (!hrp->bith_ndx) goto bad_bit;
1562    ndx = hrp->hi;
1563   }
1564  else ndx = -1;
1565 
1566  nterms = bld_net_pathterms(np, hp->hin_itp, ndx);
1567  if (nterms <= 0) return(NULL);
1568 
1569  iterp = __alloc_iter(nterms, &ihref);
1570  memcpy(iterp->scanhtab, __ithtab, nterms*sizeof(struct h_t));
1571  memcpy(iterp->ihrectab, __ithrectab, nterms*sizeof(struct hrec_t));
1572 
1573  for (hi = 0; hi < nterms; hi++)
1574   {
1575    iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
1576   }
1577  return(ihref);
1578 }
1579 
1580 /*
1581  * build path terminals connected to net index ndx
1582  *
1583  * ndx -1 for all of wire
1584  * on path sources and destinations here
1585  */
bld_net_pathterms(struct net_t * np,struct itree_t * itp,int32 ndx)1586 static int32 bld_net_pathterms(struct net_t *np, struct itree_t *itp, int32 ndx)
1587 {
1588  register int32 bi, pei;
1589  register struct net_pin_t *npp;
1590  register struct pthdst_t *pdp;
1591  register struct hrec_t *hrp2;
1592  int32 cnt, fr, to;
1593  struct h_t *hp2;
1594  struct h_t tmph;
1595  struct hrec_t tmphrec;
1596  struct tchg_t *tchgp;
1597  struct spcpth_t *pthp;
1598  struct pathel_t *pep;
1599 
1600  /* for net bit, if any bit in range then entire source terminal */
1601  /* first path sources - from path source load */
1602  for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
1603   {
1604    if (npp->npntyp != NP_TCHG) continue;
1605    /* will be one for each event, since just need tchk use only start ev */
1606    if (npp->chgsubtyp != NPCHG_PTHSRC) continue;
1607 
1608    /* know tchk terminals are wires or selects (not globals) */
1609    tchgp = npp->elnpp.etchgp;
1610    pthp = tchgp->chgu.chgpthp;
1611    for (pei = 0; pei <= pthp->last_pein; pei++)
1612     {
1613      pep = &(pthp->peins[pei]);
1614      if (np != pep->penp) continue;
1615      if (ndx != -1 && pep->pthi1 != -1 &&
1616       (ndx > pep->pthi1 || ndx < pep->pthi2)) continue;
1617 
1618      if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
1619      hp2 = &(__ithtab[cnt]);
1620      hp2->hin_itp = itp;
1621 
1622      hrp2 = &(__ithrectab[cnt++]);
1623      __init_hrec(hrp2);
1624      hrp2->in_iter = TRUE;
1625      hrp2->htyp = vpiModPathIn;
1626      hrp2->hu.hpthp = pthp;
1627      hrp2->hi = pei;
1628      /* only need to set cross link in newly added one */
1629      hp2->hrec = hrp2;
1630     }
1631   }
1632  /* path destinations (if any) are linked on wire */
1633  if (np->n_isapthdst)
1634   {
1635    if (ndx == -1) { fr = 0; to = np->nwid - 1; } else fr = to = ndx;
1636    for (bi = fr; bi <= to; bi++)
1637     {
1638      pdp = np->nu.rngdwir->n_du.pb_pthdst[bi];
1639      for (; pdp != NULL; pdp = pdp->pdnxt)
1640       {
1641        pthp = pdp->pstchgp->chgu.chgpthp;
1642        for (pei = 0; pei <= pthp->last_peout; pei++)
1643         {
1644          pep = &(pthp->peouts[pei]);
1645          if (ndx != -1 && pep->pthi1 != -1 &&
1646           (ndx > pep->pthi1 || ndx < pep->pthi2)) continue;
1647 
1648          __init_hrec(&tmphrec);
1649          tmphrec.htyp = vpiModPathOut;
1650          tmphrec.hu.hpthp = pthp;
1651          tmphrec.hi = pei;
1652          tmph.hin_itp = itp;
1653          /* need to set in iter bit */
1654          tmphrec.in_iter = TRUE;
1655          tmph.hrec = &tmphrec;
1656 
1657          /* if duplicated do not add */
1658          if (cnt != 0 && same_vpi_handle(__ithtab, 0, cnt, &tmph, &tmphrec))
1659           continue;
1660          if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
1661          hp2 = &(__ithtab[cnt]);
1662          hp2->hin_itp = tmph.hin_itp;
1663 
1664          hrp2 = &(__ithrectab[cnt++]);
1665          memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
1666          /* only need to set cross link in newly added one */
1667          hp2->hrec = hrp2;
1668         }
1669       }
1670     }
1671   }
1672  return(cnt);
1673 }
1674 
1675 /*
1676  * build a delay expression iterator - this is value that appears in source
1677  *
1678  * except in cver returns expression of the latest back annotated value
1679  * not the original source
1680  *
1681  * FIXME - for vpiDelayControl should be one to one expr op. not iterator?
1682  */
__bld_delay_expr_iter(struct h_t * rhp)1683 extern vpiHandle __bld_delay_expr_iter(struct h_t *rhp)
1684 {
1685  register struct hrec_t *rhrp;
1686  register int32 hi;
1687  int32 ndels, ndels2;
1688  vpiHandle ihref;
1689  struct h_t tmph;
1690  struct gate_t *gp;
1691  struct spcpth_t *pthp;
1692  struct tchk_t *tcp;
1693  struct delctrl_t *dctp;
1694  struct pviter_t *iterp;
1695 
1696  rhrp = rhp->hrec;
1697  switch (rhrp->htyp) {
1698   /* need the 3 cleass elements not the class name here */
1699   case vpiGate: case vpiUdp: case vpiSwitch:
1700    gp = rhrp->hu.hgp;
1701    if (gp->g_delrep == DT_NONE) return(NULL);
1702    ndels = bld_delay_iter(gp->g_du, gp->g_delrep, rhp->hin_itp,
1703     rhrp->hin_tskp);
1704    break;
1705   case vpiModPath:
1706    pthp = rhrp->hu.hpthp;
1707    if (pthp->pth_delrep == DT_NONE) __vpi_terr(__FILE__, __LINE__);
1708    ndels = bld_delay_iter(pthp->pth_du, pthp->pth_delrep, rhp->hin_itp,
1709     rhrp->hin_tskp);
1710    break;
1711   case vpiTchk:
1712    tcp = rhrp->hu.htcp;
1713    if (tcp->tc_delrep == DT_NONE) __vpi_terr(__FILE__, __LINE__);
1714    ndels = bld_delay_iter(tcp->tclim_du, tcp->tc_delrep, rhp->hin_itp,
1715     rhrp->hin_tskp);
1716    if (ndels != 1) __vpi_terr(__FILE__, __LINE__);
1717    tmph = __ithtab[0];
1718    if (tcp->tc_haslim2)
1719     {
1720      if (tcp->tc_delrep2 == DT_NONE) __vpi_terr(__FILE__, __LINE__);
1721      ndels2 = bld_delay_iter(tcp->tclim2_du, tcp->tc_delrep2, rhp->hin_itp,
1722       rhrp->hin_tskp);
1723      if (ndels2 != 1) __vpi_terr(__FILE__, __LINE__);
1724      __ithtab[1] = __ithtab[0];
1725      __ithtab[0] = tmph;
1726      ndels = 2;
1727     }
1728    break;
1729   case vpiDelayControl:
1730    dctp = rhrp->hu.hstp->st.sdc;
1731    if (dctp->dctyp != DC_DELAY && dctp->dctyp != DC_RHSDELAY)
1732     __vpi_terr(__FILE__, __LINE__);
1733    if (dctp->dc_delrep == DT_NONE) __vpi_terr(__FILE__, __LINE__);
1734    ndels = bld_delay_iter(dctp->dc_du, dctp->dc_delrep, rhp->hin_itp,
1735     rhrp->hin_tskp);
1736    if (ndels != 1) __vpi_terr(__FILE__, __LINE__);
1737    break;
1738   default:
1739    __vpi_err(1838, vpiError,
1740     "vpiDelay 1-to-many (iterator) method illegal for %s object",
1741     __to_vpionam(__wrks1, rhp->hrec->htyp));
1742    return(NULL);
1743   }
1744  /* DBG remove --- */
1745  if (ndels <= 0) __vpi_terr(__FILE__, __LINE__);
1746  /* --- */
1747 
1748  iterp = __alloc_iter(ndels, &ihref);
1749  memcpy(iterp->scanhtab, __ithtab, ndels*sizeof(struct h_t));
1750  memcpy(iterp->ihrectab, __ithrectab, ndels*sizeof(struct hrec_t));
1751 
1752  for (hi = 0; hi < ndels; hi++)
1753   {
1754    iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
1755   }
1756  return(ihref);
1757 }
1758 
1759 /*
1760  * fill it htab work iterator with delay expressions
1761  *
1762  * not called for DT_NONE
1763  */
bld_delay_iter(union del_u du,word32 drep,struct itree_t * itp,struct task_t * tskp)1764 static int32 bld_delay_iter(union del_u du, word32 drep, struct itree_t *itp,
1765  struct task_t *tskp)
1766 {
1767  register int32 i;
1768  int32 ndels;
1769  word64 tim[12], timval;
1770  struct mod_t *mdp;
1771  struct h_t tmph;
1772  struct hrec_t tmphrec, *hrp2;
1773  struct h_t *hp2;
1774  struct expr_t *xp;
1775  struct xstk_t *xsp;
1776 
1777  /* for expressions, value is same as source (not ticks) */
1778  if (drep == DT_1X)
1779   {
1780    if (__ithtsiz <= 1) __grow_htab(1);
1781    tmph.hrec = &(tmphrec);
1782    mk2_exprclass_handle(&tmph, du.d1x, itp, tskp);
1783    tmphrec.in_iter = TRUE;
1784    hp2 = &(__ithtab[0]);
1785    memcpy(hp2, &(tmph), sizeof(struct h_t));
1786    hrp2 = &(__ithrectab[0]);
1787    memcpy(hrp2, &(tmphrec), sizeof(struct hrec_t));
1788    hp2->hrec = hrp2;
1789    return(1);
1790   }
1791  if (drep == DT_4X)
1792   {
1793    if (__ithtsiz <= 3) __grow_htab(3);
1794    tmph.hrec = &(tmphrec);
1795    mk2_exprclass_handle(&tmph, du.d4x[0], itp, tskp);
1796    tmphrec.in_iter = TRUE;
1797 
1798    hp2 = &(__ithtab[0]);
1799    memcpy(hp2, &(tmph), sizeof(struct h_t));
1800    hrp2 = &(__ithrectab[0]);
1801    memcpy(hrp2, &(tmphrec), sizeof(struct hrec_t));
1802    /* only need to set cross link in newly added one */
1803    hp2->hrec = hrp2;
1804 
1805    tmph.hrec = &(tmphrec);
1806    mk2_exprclass_handle(&tmph, du.d4x[1], itp, tskp);
1807    tmphrec.in_iter = TRUE;
1808    hp2 = &(__ithtab[1]);
1809    memcpy(hp2, &(tmph), sizeof(struct h_t));
1810    hrp2 = &(__ithrectab[1]);
1811    memcpy(hrp2, &(tmphrec), sizeof(struct hrec_t));
1812 
1813    /* only need to set cross link in newly added one */
1814    hp2->hrec = hrp2;
1815 
1816    tmph.hrec = &(tmphrec);
1817    mk2_exprclass_handle(&tmph, du.d4x[2], itp, tskp);
1818    tmphrec.in_iter = TRUE;
1819    hp2 = &(__ithtab[2]);
1820    memcpy(hp2, &(tmph), sizeof(struct h_t));
1821    hrp2 = &(__ithrectab[2]);
1822    memcpy(hrp2, &(tmphrec), sizeof(struct hrec_t));
1823    /* only need to set cross link in newly added one */
1824    hp2->hrec = hrp2;
1825    /* 4x for in source expression has only 3 values (no to x) */
1826    return(3);
1827   }
1828  /* all other cases are constants - reconstruct source assuming no anotate */
1829  __push_itstk(itp);
1830  mdp = itp->itip->imsym->el.emdp;
1831  /* non expr. case, return as internal ticks constants */
1832  __extract_delval(tim, &ndels, du, drep);
1833  /* no t vpi time record here - always convert to number appearing in src */
1834  if (ndels > 0 && !mdp->mno_unitcnv)
1835   {
1836    for (i = 0; i < ndels; i++)
1837     {
1838      __cnv_ticks_tonum64(&timval, tim[i], mdp);
1839      tim[i] = timval;
1840     }
1841   }
1842  for (i = 0; i < ndels; i++)
1843   {
1844    if (i >= __ithtsiz) __grow_htab(1);
1845 
1846    /* create expresion for each delay and store in constant table for */
1847    /* module type of instance */
1848    xp = __sim_alloc_newxnd();
1849    xp->szu.xclen = TIMEBITS;
1850    xp->optyp = NUMBER;
1851 
1852    push_xstk_(xsp, 2);
1853    xsp->ap[0] = (word32) (tim[i] & WORDMASK_ULL);
1854    xsp->ap[1] = (word32) ((tim[i] >> 32) & WORDMASK_ULL);
1855    xsp->bp[0] = 0L;
1856    xsp->bp[1] = 0L;
1857    xp->ru.xvi = __allocfill_cval_new(xsp->ap, xsp->bp, 2);
1858    __pop_xstk();
1859 
1860    hp2 = &(__ithtab[i]);
1861    hrp2 = &(__ithrectab[i]);
1862    __init_hrec(hrp2);
1863    /* only need to set cross link in newly added one */
1864    hp2->hrec = hrp2;
1865 
1866    hrp2->in_iter = TRUE;
1867    hrp2->htyp = vpiConstant;
1868    hrp2->hu.hxp = xp;
1869    hp2->hin_itp = itp;
1870    hrp2->hin_tskp = tskp;
1871    /* because in iter can not be freed but copied needs free xpr on */
1872    hrp2->free_xpr = TRUE;
1873   }
1874  __pop_itstk();
1875  return(ndels);
1876 }
1877 
1878 /*
1879  * ROUTINES TO BUILD ATTRIBUTE ITERATOR
1880  */
1881 
1882 /*
1883  * build the attr_spec iterators
1884  */
__bld_dig_attr_iter(struct h_t * hp)1885 extern vpiHandle __bld_dig_attr_iter(struct h_t *hp)
1886 {
1887  struct net_t *np;
1888  struct gate_t *gp;
1889  struct inst_t *ip;
1890  struct mod_t *mdp;
1891  struct hrec_t *hrp;
1892 
1893  if (hp == NULL) return(__nil_iter_err(vpiAttribute));
1894 
1895  hrp = hp->hrec;
1896  switch (hp->hrec->htyp) {
1897   case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
1898   case vpiNamedEvent: case vpiRealVar:
1899   /* LOOKATME - is this defined in LRM - think so */
1900   case vpiMemory:
1901    np = hrp->hu.hnp;
1902    if (np->nattrs == NULL) return(NULL);
1903    return(bld_dig_attrlist_iter(hp, np->nattrs));
1904   case vpiModule:
1905    ip = hp->hin_itp->itip;
1906    mdp = ip->imsym->el.emdp;
1907 
1908    /* if dig attr attached to inst use it */
1909    if (ip->iattrs != NULL) return(bld_dig_attrlist_iter(hp, ip->iattrs));
1910    /* otherwise return mod attrs from mod */
1911    if (mdp->mattrs == NULL) return(NULL);
1912    return(bld_dig_attrlist_iter(hp, mdp->mattrs));
1913   case vpiGate: case vpiSwitch: case vpiUdp:
1914    gp = hrp->hu.hgp;
1915    if (gp->gattrs == NULL) return(NULL);
1916    return(bld_dig_attrlist_iter(hp, gp->gattrs));
1917   case vpiPort:
1918    __vpi_err(2113, vpiNotice,
1919     "vpiAttribute 1-to-many iterator for %s empty - attached to net",
1920     __to_vpionam(__wrks1, hp->hrec->htyp));
1921    return(NULL);
1922   default:
1923    __vpi_err(2032, vpiWarning,
1924     "vpiAttribute 1-to-many iterator for %s empty - attribute not yet stored",
1925     __to_vpionam(__wrks1, hp->hrec->htyp));
1926   }
1927  return(NULL);
1928 }
1929 
1930 /*
1931  * get object that is parent of attribute
1932  *
1933  * trick is storing digital attribute as object but offset count to
1934  * object's attribute record so using htyp2 as parent object htyp
1935  */
__get_digattr_parent(struct h_t * hp)1936 extern vpiHandle __get_digattr_parent(struct h_t *hp)
1937 {
1938  struct h_t *hp2;
1939  struct hrec_t *hrp;
1940 
1941  hrp = hp->hrec;
1942  hp2 = (struct h_t *) __mk_handle(hrp->htyp2, (void *) hrp->hu.hanyp,
1943   hp->hin_itp, hrp->hin_tskp);
1944  return((vpiHandle) hp2);
1945 }
1946 
1947 /*
1948  * build an attribute iterator of otyp objects from one attr table
1949  *
1950  * FIXME - should store as table so can access value using index not
1951  * list search
1952  */
bld_dig_attrlist_iter(struct h_t * hp,struct attr_t * attrp)1953 static vpiHandle bld_dig_attrlist_iter(struct h_t *hp, struct attr_t *attrp)
1954 {
1955  register int32 ai;
1956  register struct attr_t *attrp2;
1957  int32 atnum;
1958  struct hrec_t *hrp, *hrp2;
1959  struct h_t *hp2;
1960  vpiHandle ihref;
1961  struct pviter_t *iterp;
1962 
1963  if (attrp == NULL) return(NULL);
1964  atnum = 0;
1965  for (attrp2 = attrp; attrp2 != NULL; attrp2 = attrp2->attrnxt) atnum++;
1966 
1967  hrp = hp->hrec;
1968  iterp = __alloc_iter(atnum, &ihref);
1969  for (ai = 0; ai < atnum; ai++)
1970   {
1971    hp2 = &(iterp->scanhtab[ai]);
1972    hp2->hin_itp = hp->hin_itp;
1973    hrp2 = hp2->hrec;
1974    hrp2->htyp = vpiAttribute;
1975    hrp2->htyp2 = hrp->htyp;
1976    hrp2->hi = ai;
1977    hrp2->hu.hanyp = hrp->hu.hanyp;
1978    hrp2->hin_tskp = hrp->hin_tskp;
1979   }
1980  return(ihref);
1981 }
1982 
1983 /*
1984  * ROUTINES TO BUILD STATEMENT CONTENTS ITERATOR
1985  */
1986 
1987 /*
1988  * build the case item iterator
1989  */
__bld_caseitems_iter(struct h_t * hp)1990 extern vpiHandle __bld_caseitems_iter(struct h_t *hp)
1991 {
1992  register int32 cii;
1993  register struct csitem_t *csip2;
1994  register struct hrec_t *hrp2;
1995  int32 numcis;
1996  vpiHandle ihref;
1997  struct csitem_t *dfltcsip;
1998  struct h_t *hp2;
1999  struct pviter_t *iterp;
2000  struct st_t *stp;
2001  struct csitem_t *csips;
2002  struct hrec_t *hrp;
2003 
2004  hrp = hp->hrec;
2005  if (hrp->htyp != vpiCase)
2006   {
2007    __vpi_err(1835, vpiError,
2008     "vpiCaseItem 1-to-many iterator requires vpiCase reference handle - %s illegal",
2009     __to_vpionam(__wrks1, hrp->htyp));
2010    return(NULL);
2011   }
2012  stp = hrp->hu.hstp;
2013  /* 08/27/99 - now case default always first on list - nil st if no dflt */
2014  dfltcsip = stp->st.scs.csitems;
2015 
2016  csips = dfltcsip->csinxt;
2017  for (numcis = 0, csip2 = csips; csip2 != NULL; csip2 = csip2->csinxt)
2018   numcis++;
2019  if (dfltcsip->csist != NULL) numcis++;
2020  if (numcis <= 0) return(NULL);
2021 
2022  iterp = __alloc_iter(numcis, &ihref);
2023  for (csip2 = csips, cii = 0; csip2 != NULL; csip2 = csip2->csinxt, cii++)
2024   {
2025    /* DBG remove --- */
2026    if (csip2->csist == NULL) __vpi_terr(__FILE__, __LINE__);
2027    /* --- */
2028    hp2 = &(iterp->scanhtab[cii]);
2029    hp2->hin_itp = hp->hin_itp;
2030 
2031    hrp2 = hp2->hrec;
2032    hrp2->htyp = vpiCaseItem;
2033    hrp2->hu.hcsip = csip2;
2034    hrp2->hin_tskp = hrp->hin_tskp;
2035   }
2036  /* notice cii at loop exit is next past end */
2037  if (dfltcsip->csist != NULL)
2038   {
2039    hp2 = &(iterp->scanhtab[cii]);
2040    hp2->hin_itp = hp->hin_itp;
2041 
2042    hrp2 = hp2->hrec;
2043    hrp2->htyp = vpiCaseItem;
2044    hrp2->hu.hcsip = dfltcsip;
2045    hrp2->hin_tskp = hrp->hin_tskp;
2046   }
2047  return(ihref);
2048 }
2049 
2050 /*
2051  * build the case item expression iterator from case item (including default)
2052  */
__bld_casi_exprs_iter(struct h_t * hp)2053 extern vpiHandle __bld_casi_exprs_iter(struct h_t *hp)
2054 {
2055  register int32 xi;
2056  register struct exprlst_t *xplst;
2057  int32 numxps;
2058  vpiHandle ihref;
2059  struct csitem_t *csip;
2060  struct h_t *hp2;
2061  struct pviter_t *iterp;
2062  struct hrec_t *hrp;
2063 
2064 
2065  hrp = hp->hrec;
2066  if (hrp->htyp != vpiCaseItem)
2067   {
2068    __vpi_err(1831, vpiError,
2069     "vpiExpr 1-to-many iterator only legal for vpiCaseItem - %s illegal",
2070     __to_vpionam(__wrks1, hrp->htyp));
2071    return(NULL);
2072   }
2073  csip = hrp->hu.hcsip;
2074  for (numxps = 0, xplst = csip->csixlst; xplst != NULL; xplst = xplst->xpnxt)
2075   numxps++;
2076  if (numxps <= 0) return(NULL);
2077  iterp = __alloc_iter(numxps, &ihref);
2078  for (xi = 0, xplst = csip->csixlst; xplst != NULL; xplst = xplst->xpnxt, xi++)
2079   {
2080    hp2 = &(iterp->scanhtab[xi]);
2081    mk2_exprclass_handle(hp2, xplst->xp, hp->hin_itp, hrp->hin_tskp);
2082   }
2083  return(ihref);
2084 }
2085 
2086 /*
2087  * build the iterator for operands of an operator
2088  * handle is an expression that must have operands
2089  *
2090  * for part select and bit (const or var) select vpiRange or vpiIndex
2091  * not vpiOperand iterator
2092  */
__bld_operands_iter(struct h_t * hp)2093 extern vpiHandle __bld_operands_iter(struct h_t *hp)
2094 {
2095  register int32 xi;
2096  register struct expr_t *xp, *catxp;
2097  int32 xtyp, otyp, numxps;
2098  vpiHandle ihref;
2099  struct expr_t *xp2;
2100  struct h_t *hp2;
2101  struct pviter_t *iterp;
2102  struct hrec_t *hrp;
2103 
2104  hrp = hp->hrec;
2105  if (hrp->htyp != vpiOperation)
2106   {
2107    strcpy(__wrks2, "*none*");
2108 bad_handle:
2109    __vpi_err(1831, vpiError,
2110     "vpiOperand 1-to-many iterator requires vpiOperation handle - %s (type %s) illegal",
2111     __to_vpionam(__wrks1, hrp->htyp), __wrks2);
2112    return(NULL);
2113   }
2114  xp = hrp->hu.hxp;
2115  xtyp = __exprtype_get(xp);
2116  if (xtyp != vpiOperation)
2117   { __to_vpionam(__wrks2, (word32) xtyp); goto bad_handle; }
2118 
2119  otyp = __expr_optype_get(xp);
2120 
2121  /* null op has no operands */
2122  if (otyp == vpiNullOp)
2123   {
2124    return(NULL);
2125   }
2126 
2127  /* concatenate and ?: are special cases (3-ary and n-ary) */
2128  if (otyp == vpiConcatOp)
2129   {
2130    for (numxps = 0, catxp = xp->ru.x; catxp != NULL; catxp = catxp->ru.x)
2131     numxps++;
2132 
2133    /* DBG remove --- */
2134    if (numxps <= 0) __vpi_terr(__FILE__, __LINE__);
2135    /* --- */
2136    iterp = __alloc_iter(numxps, &ihref);
2137    for (catxp = xp->ru.x, xi = 0; catxp != NULL; catxp = catxp->ru.x, xi++)
2138     {
2139      /* works because alloc of iter make connect from hp to hrec */
2140      hp2 = &(iterp->scanhtab[xi]);
2141      mk2_exprclass_handle(hp2, catxp->lu.x, hp->hin_itp, hrp->hin_tskp);
2142     }
2143    return(ihref);
2144   }
2145  if (otyp == vpiConditionOp)
2146   {
2147    iterp = __alloc_iter(3, &ihref);
2148    for (xi = 0; xi < 3; xi++)
2149     {
2150      hp2 = &(iterp->scanhtab[xi]);
2151      if (xi == 0) xp2 = xp->lu.x;
2152      else if (xi == 1) xp2 = xp->ru.x->lu.x;
2153      else xp2 = xp->ru.x->ru.x;
2154      mk2_exprclass_handle(hp2, xp2, hp->hin_itp, hrp->hin_tskp);
2155     }
2156    return(ihref);
2157   }
2158  /* notice ru operand nil implies unary */
2159  if (xp->ru.x == NULL)
2160   {
2161    iterp = __alloc_iter(1, &ihref);
2162    hp2 = &(iterp->scanhtab[0]);
2163    mk2_exprclass_handle(hp2, xp->lu.x, hp->hin_itp, hrp->hin_tskp);
2164    return(ihref);
2165   }
2166  /* normal binary operator */
2167  iterp = __alloc_iter(2, &ihref);
2168  for (xi = 0; xi < 2; xi++)
2169   {
2170    hp2 = &(iterp->scanhtab[xi]);
2171    if (xi == 0) xp2 = xp->lu.x; else xp2 = xp->ru.x;
2172    mk2_exprclass_handle(hp2, xp2, hp->hin_itp, hrp->hin_tskp);
2173   }
2174  return(ihref);
2175 }
2176 
2177 /*
2178  * build all callbacks iterator
2179  * for now only legal is all, FIXME - should support from objects
2180  */
__bld_allcbs_iter(struct h_t * hp)2181 extern vpiHandle __bld_allcbs_iter(struct h_t *hp)
2182 {
2183  register int32 cbi, numcbs;
2184  register struct cbrec_t *cbp;
2185  register struct hrec_t *hrp2;
2186  vpiHandle ihref;
2187  struct pviter_t *iterp;
2188  struct h_t *hp2;
2189 
2190  if (hp != NULL)
2191   {
2192    __vpi_err(1831, vpiError,
2193     "for now vpiCallback 1-to-many iterator requires NULL (all cbs) - %s illegal",
2194     __to_vpionam(__wrks1, hp->hrec->htyp));
2195     return(NULL);
2196   }
2197  if (__vpi_cbrec_hdr == NULL) return(NULL);
2198  for (numcbs = 0, cbp = __vpi_cbrec_hdr; cbp != NULL; cbp = cbp->cbnxt)
2199   numcbs++;
2200  if (numcbs <= 0) return(NULL);
2201 
2202  iterp = __alloc_iter(numcbs, &ihref);
2203  /* since register list new added to front, build iterator back to front */
2204  cbp = __vpi_cbrec_hdr;
2205  /* SJM - 06/14/99 - since put latest on front build in reverse order */
2206  for (cbi = numcbs - 1; cbp != NULL; cbp = cbp->cbnxt, cbi--)
2207   {
2208    hp2 = &(iterp->scanhtab[cbi]);
2209    hrp2 = hp2->hrec;
2210    hrp2->htyp = vpiCallback;
2211    hrp2->hu.hcbp = cbp;
2212    /* callback handles do not have itree loc (but obj might) */
2213   }
2214  return(ihref);
2215 }
2216 
2217 /*
2218  * ROUTINES TO BUILD PORT AND PORT BIT ITERATORS
2219  */
2220 
2221 /*
2222  * build vpi Port module port iterator from a net (any type) handle
2223  *
2224  * given a net, find all ports that connect to the net (usually one)
2225  * but jumpered ports legal in Verilog
2226  * search through all of load, drivers, and inout vertex edges
2227  *
2228  * module port connections are never xmr since no xmr forms for port wire
2229  */
bld_netmdport_iter(struct h_t * hp)2230 static vpiHandle bld_netmdport_iter(struct h_t *hp)
2231 {
2232  register int32 hi;
2233  int32 numprts;
2234  vpiHandle ihref;
2235  struct net_t *np;
2236  struct mod_t *mdp;
2237  struct pviter_t *iterp;
2238 
2239  np = hp->hrec->hu.hnp;
2240  mdp = hp->hin_itp->itip->imsym->el.emdp;
2241  if (mdp->mpnum == 0) return(NULL);
2242  numprts = bld_net_mdpins(np, mdp, hp->hin_itp);
2243  if (numprts <= 0) return(NULL);
2244 
2245  iterp = __alloc_iter(numprts, &ihref);
2246  memcpy(iterp->scanhtab, __ithtab, numprts*sizeof(struct h_t));
2247  memcpy(iterp->ihrectab, __ithrectab, numprts*sizeof(struct hrec_t));
2248  for (hi = 0; hi < numprts; hi++)
2249   {
2250    iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
2251   }
2252  return(ihref);
2253 }
2254 
2255 /*
2256  * build modport connecting iterators
2257  *
2258  * know all jumpered non tran channel ports will be marked if any are
2259  *
2260  * if multiple connections to same port do not include repeats
2261  * this does not run with anything on itstk instead uses itp
2262  *
2263  * here iterator is vpiPort so returns all port connections
2264  *
2265  * this is opposite of lowconn - from port connecting net up to port
2266  * here because not bit handle, return entire port
2267  *
2268  * to decompose and match expr. connections and ports, user must create
2269  * port iterator get highconn and lowconn connection and then write program
2270  * to match
2271  */
bld_net_mdpins(struct net_t * np,struct mod_t * mdp,struct itree_t * itp)2272 static int32 bld_net_mdpins(struct net_t *np, struct mod_t *mdp,
2273  struct itree_t *itp)
2274 {
2275  register struct net_pin_t *npp;
2276  register struct hrec_t *hrp2;
2277  int32 cnt;
2278  byte *prtconn;
2279  struct h_t *hp2;
2280  struct mod_pin_t *mpp;
2281 
2282  prtconn = (byte *) __my_malloc(mdp->mpnum);
2283  memset(prtconn, 0, mdp->mpnum);
2284  /* mod port loads are output ports - can connect to regs too */
2285  for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
2286   {
2287    /* PB mdports for drivers only */
2288    if (npp->npntyp == NP_PB_MDPRT)
2289     {
2290      /* SJM 09/20/02 - for per bit npp forms, ignore all but 1 npp */
2291      /* there will be one npp per bit but only one iterator forllowing LRM */
2292      /* and by not doing 2nd per bit indexing, looks like vectored npp */
2293      if (npp->pbi != 0) continue;
2294     }
2295    else if (npp->npntyp != NP_MDPRT) continue;
2296 
2297    /* DBG remove --- */
2298    if (npp->elnpp.emdp != mdp) __vpi_terr(__FILE__, __LINE__);
2299    /* --- */
2300    mpp = &(mdp->mpins[npp->obnum]);
2301    /* if no connection for this port include */
2302    if (prtconn[npp->obnum] == 0)
2303     {
2304      if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
2305      hp2 = &(__ithtab[cnt]);
2306      hrp2 = &(__ithrectab[cnt++]);
2307      __init_hrec(hrp2);
2308 
2309      hrp2->in_iter = TRUE;
2310      hrp2->htyp = vpiPort;
2311      hrp2->hu.hpi = npp->obnum;
2312      hp2->hin_itp = itp;
2313      /* only need to set cross link in newly added one */
2314      hp2->hrec = hrp2;
2315      prtconn[npp->obnum] = 1;
2316     }
2317    if (!mpp->mp_jmpered) break;
2318   }
2319  /* if reg done */
2320  if (np->ntyp >= NONWIRE_ST) goto done;
2321 
2322  /* mod port drivers are input ports - must be wire */
2323  for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
2324   {
2325    if (npp->npntyp == NP_PB_MDPRT)
2326     {
2327      /* SJM 09/20/02 - for per bit npp forms, ignore all but 1 npp */
2328      /* there will be one npp per bit but only one iterator forllowing LRM */
2329      /* and by not doing 2nd per bit indexing, looks like vectored npp */
2330      if (npp->pbi != 0) continue;
2331     }
2332    else if (npp->npntyp != NP_MDPRT) continue;
2333 
2334    /* DBG remove --- */
2335    if (npp->elnpp.emdp != mdp) __vpi_terr(__FILE__, __LINE__);
2336    /* --- */
2337    mpp = &(mdp->mpins[npp->obnum]);
2338    if (prtconn[npp->obnum] == 0)
2339     {
2340      if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
2341      hp2 = &(__ithtab[cnt]);
2342      hrp2 = &(__ithrectab[cnt++]);
2343      __init_hrec(hrp2);
2344 
2345      hrp2->in_iter = TRUE;
2346      hrp2->htyp = vpiPort;
2347      hrp2->hu.hpi = npp->obnum;
2348      hp2->hin_itp = itp;
2349      /* only need to set cross link in newly added one */
2350      hp2->hrec = hrp2;
2351      prtconn[npp->obnum] = 1;
2352     }
2353    if (!mpp->mp_jmpered) break;
2354   }
2355  /* finally inout ports if they exist (always bit by bit) */
2356  if (np->ntraux == NULL) goto done;
2357 
2358  /* SJM - 05/15/99 - after tran channels built - leave npps connected */
2359  /* as part of ntraux - use for PLI not simulation */
2360  /* bid and tran (gate?) npps move to traux for PLI processing */
2361  for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
2362   {
2363    if (npp->npntyp != NP_BIDMDPRT) continue;
2364 
2365    mpp = &(mdp->mpins[npp->obnum]);
2366    /* DBG remove --- */
2367    if (npp->elnpp.emdp != mdp) __vpi_terr(__FILE__, __LINE__);
2368    /* --- */
2369    mpp = &(mdp->mpins[npp->obnum]);
2370    if (prtconn[npp->obnum] == 0)
2371     {
2372      if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
2373      hp2 = &(__ithtab[cnt]);
2374      hrp2 = &(__ithrectab[cnt++]);
2375      __init_hrec(hrp2);
2376 
2377      hrp2->in_iter = TRUE;
2378      hrp2->htyp = vpiPort;
2379      hrp2->hu.hpi = npp->obnum;
2380      hp2->hin_itp = itp;
2381      /* only need to set cross link in newly added one */
2382      hp2->hrec = hrp2;
2383      prtconn[npp->obnum] = 1;
2384     }
2385   }
2386 done:
2387  __my_free((char *) prtconn, mdp->mpnum);
2388  return(cnt);
2389 }
2390 
2391 /*
2392  * build the port bit iterator for all bits connecting to the one net bit
2393  *
2394  * for normal non scalar only connections this is needed to get per bit
2395  * connections since different bits will have different connectivity
2396  * never get here for scalar
2397  *
2398  * LOOKATME - netbit here must be constant only (i.e. no eval)
2399  */
bld_netbitmdport_iter(struct h_t * hp)2400 static vpiHandle bld_netbitmdport_iter(struct h_t *hp)
2401 {
2402  register int32 hi;
2403  int32 bi, numprts;
2404  vpiHandle ihref;
2405  struct net_t *np;
2406  struct mod_t *mdp;
2407  struct itree_t *itp;
2408  struct pviter_t *iterp;
2409 
2410  if ((bi = cmp_drvld_bitndx(&np, hp, "vpiPort")) == -1) return(NULL);
2411 
2412  itp = hp->hin_itp;
2413  mdp = itp->itip->imsym->el.emdp;
2414  if (mdp->mpnum == 0) return(NULL);
2415  numprts = bld_netbit_mdpins(np, bi, mdp, itp);
2416  if (numprts <= 0) return(NULL);
2417 
2418  iterp = __alloc_iter(numprts, &ihref);
2419  memcpy(iterp->scanhtab, __ithtab, numprts*sizeof(struct h_t));
2420  memcpy(iterp->ihrectab, __ithrectab, numprts*sizeof(struct hrec_t));
2421  for (hi = 0; hi < numprts; hi++)
2422   {
2423    iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
2424   }
2425  return(ihref);
2426 }
2427 
2428 /*
2429  * compute index for bit object driver/load iterator
2430  *
2431  * ??? FIXME - think this is wrong needs to use current value
2432  * but then can't call during vpiEndOfCompile?
2433  */
cmp_drvld_bitndx(struct net_t ** nnp,struct h_t * hp,char * objnam)2434 static int32 cmp_drvld_bitndx(struct net_t **nnp, struct h_t *hp, char *objnam)
2435 {
2436  register int32 bi;
2437  register struct net_t *np;
2438  register struct hrec_t *hrp;
2439 
2440  *nnp = NULL;
2441  hrp = hp->hrec;
2442  if (!hrp->bith_ndx && !__expr_is_vpiconst(hrp->hu.hxp))
2443   {
2444    __vpi_err(1880, vpiError,
2445     "%s 1-to-many iterator from %s illegal - vpiNetBit/vpiRegBit non constant",
2446     objnam, __to_vpionam(__wrks1, hrp->htyp));
2447    return(-1);
2448   }
2449  if (hrp->bith_ndx) { np = hrp->hu.hnp; bi = hrp->hi; }
2450  else
2451   {
2452    /* DBG remove --- */
2453    if (hrp->hu.hxp->optyp != LSB) __vpi_terr(__FILE__, __LINE__);
2454    /* --- */
2455    /* know expr. is constant to get to here */
2456    np = hrp->hu.hxp->lu.sy->el.enp;
2457    __push_itstk(hp->hin_itp);
2458    bi = __comp_ndx(np, hrp->hu.hxp->ru.x);
2459    __pop_itstk();
2460    /* for x or out of range - iterator empty */
2461    if (bi == -1) return(-1);
2462   }
2463  *nnp = np;
2464  return(bi);
2465 }
2466 
2467 /*
2468  * build mod portbit connecting iterators
2469  *
2470  * notice since net in module npp bits indices and bi will both be h:0
2471  * here built iterator is vpiPortBit, i.e. bit matches
2472  *
2473  * this is opposite (iterator) of highconn
2474  *
2475  * here can not eliminate duplicates
2476  *
2477  * because this is bit, if port scalar returns vpiPort else vpiPortBit
2478  * if mod port is concat (rare) does not include and sets warning
2479  *
2480  * LOOKATME - all 3 cases have mostly same code - could make one func call
2481  */
bld_netbit_mdpins(struct net_t * np,int32 bi,struct mod_t * mdp,struct itree_t * itp)2482 static int32 bld_netbit_mdpins(struct net_t *np, int32 bi, struct mod_t *mdp,
2483  struct itree_t *itp)
2484 {
2485  register struct net_pin_t *npp;
2486  register struct hrec_t *hrp2;
2487  int32 ri1, ri2, cnt;
2488  struct mod_pin_t *mpp;
2489  struct h_t *hp2;
2490 
2491  /* md prt loads are output ports */
2492  for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
2493   {
2494    /* for per bit mod ports - match if this bit same as bi */
2495    if (npp->npntyp == NP_PB_MDPRT)
2496     {
2497      if (bi == npp->pbi)
2498       {
2499        ri1 = ri2 = bi;
2500        goto got_match;
2501       }
2502      else continue;
2503     }
2504 
2505    if (npp->npntyp != NP_MDPRT) continue;
2506 
2507    /* DBG remove --- */
2508    if (npp->elnpp.emdp != mdp) __vpi_terr(__FILE__, __LINE__);
2509    /* --- */
2510    __push_itstk(itp);
2511    __get_bidnpp_sect(np, npp, &ri1, &ri2);
2512    __pop_itstk();
2513    if (ri1 == -1 || bi == -1) goto got_match;
2514    if (bi > ri1 || bi < ri2) continue;
2515 
2516 got_match:
2517    mpp = &(mdp->mpins[npp->obnum]);
2518    if (mpp->mpref->optyp == LCB)
2519     {
2520      char s1[RECLEN];
2521 
2522      sprintf(s1, "%s[%d]", np->nsym->synam, __unnormalize_ndx(np, bi));
2523      __vpi_err(2025, vpiWarning,
2524       "vpiPort iterator %s bit handle for concatenate port - unable to determine bit so vpiPort used",
2525        s1);
2526     }
2527 
2528    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
2529    hp2 = &(__ithtab[cnt]);
2530    hrp2 = &(__ithrectab[cnt++]);
2531    __init_hrec(hrp2);
2532    hrp2->in_iter = TRUE;
2533 
2534    if (mpp->mpwide == 1 || mpp->mpref->optyp == LCB) hrp2->htyp = vpiPort;
2535    else
2536     {
2537      hrp2->htyp = vpiPortBit;
2538      /* if simple wire (ri1 == -1) bits match one to one - else offset from */
2539      /* right edge */
2540      /* FIXME - what if range 0:h? */
2541      if (ri1 == -1) hrp2->hi = bi; else hrp2->hi = bi - ri2;
2542     }
2543    hrp2->hu.hpi = npp->obnum;
2544    hp2->hin_itp = itp;
2545    /* only need to set cross link in newly added one */
2546    hp2->hrec = hrp2;
2547    /* LOOKATME - think some bit may be inout channel so need ports */
2548    if (!mpp->mp_jmpered) break;
2549   }
2550  /* will be no drivers and no tran channel for reg */
2551  if (np->ntyp >= NONWIRE_ST)
2552   {
2553    /* DBG remove --- */
2554    if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
2555    /* --- */
2556    goto done;
2557   }
2558 
2559  /* md prt drivers are input ports */
2560  for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
2561   {
2562    /* SJM 09/20/02 - need to access per bit contained port for PB form */
2563    /* for per bit mod ports - match if this bit same as bi */
2564    if (npp->npntyp == NP_PB_MDPRT)
2565     {
2566      if (bi == npp->pbi) goto got_match2;
2567      else continue;
2568     }
2569 
2570    if (npp->npntyp != NP_MDPRT) continue;
2571 
2572    /* DBG remove --- */
2573    if (npp->elnpp.emdp != mdp) __vpi_terr(__FILE__, __LINE__);
2574    /* --- */
2575    __push_itstk(itp);
2576    __get_bidnpp_sect(np, npp, &ri1, &ri2);
2577    __pop_itstk();
2578    if (ri1 == -1 || bi == -1) goto got_match2;
2579    if (bi > ri1 || bi < ri2) continue;
2580 
2581 got_match2:
2582    if (npp->npntyp == NP_MDPRT)
2583     {
2584      mpp = &(mdp->mpins[npp->obnum]);
2585      if (mpp->mpref->optyp == LCB)
2586       {
2587        char s1[RECLEN];
2588 
2589        sprintf(s1, "%s[%d]", np->nsym->synam, __unnormalize_ndx(np, bi));
2590        __vpi_err(2025, vpiWarning,
2591         "vpiPort iterator %s bit handle for concatenate port - unable to determine bit so vpiPort used",
2592          s1);
2593       }
2594     }
2595    else
2596     {
2597      mpp = &(mdp->mpins[npp->obnum]);
2598      mpp = &(mpp->pbmpps[npp->pbi]);
2599     }
2600    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
2601    hp2 = &(__ithtab[cnt]);
2602    hrp2 = &(__ithrectab[cnt++]);
2603    __init_hrec(hrp2);
2604    hrp2->in_iter = TRUE;
2605 
2606    if (npp->npntyp == NP_MDPRT)
2607     {
2608      if (mpp->mpwide == 1 || mpp->mpref->optyp == LCB) hrp2->htyp = vpiPort;
2609      else
2610       {
2611        hrp2->htyp = vpiPortBit;
2612        /* notice these are internal h:0 - fixed when index accessed */
2613        /* correct for port bit from non concatenate net bit */
2614        if (ri1 == -1) hrp2->hi = bi; else hrp2->hi = bi - ri2;
2615       }
2616     }
2617    else
2618     {
2619      /* SJM 09/20/02 - for PB input port MOD PORT, always scalared */
2620      hrp2->htyp = vpiPortBit;
2621      hrp2->hi = bi;
2622     }
2623    hp2->hin_itp = itp;
2624    /* only need to set cross link in newly added one */
2625    hp2->hrec = hrp2;
2626    hrp2->hu.hpi = npp->obnum;
2627   }
2628 done:
2629  return(cnt);
2630 }
2631 
2632 /*
2633  * ROUTINES BUILD PORT INSTANCE (ICONN) ITERATORS
2634  */
2635 
2636 /*
2637  * build vpi port instance (iconn) iterators
2638  *
2639  * here will commonly have many iconns (ports of in module instances)
2640  * for example if clock feeds lots of instances
2641  *
2642  * if net if any bits connect in iterator if bit only if right bit matches
2643  */
__bld_neticonn_iter(struct h_t * hp)2644 extern vpiHandle __bld_neticonn_iter(struct h_t *hp)
2645 {
2646  if (hp == NULL) return(__nil_iter_err(vpiPortInst));
2647  switch (hp->hrec->htyp) {
2648   case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
2649    /* iterator is usually 1 port net connects to (only more if jumpered) */
2650    /* this returns port handles even if selects */
2651    return(bld_neticonnport_iter(hp));
2652   case vpiNetBit: case vpiRegBit: case vpiVarSelect:
2653    /* iterator is usually 1 port bit bit connects to */
2654    /* this returns port bit handles for the one bit */
2655    return(bld_netbiticonnport_iter(hp));
2656   default:
2657    __vpi_err(1863, vpiError,
2658     "vpiPortInst 1-to-many iterator from %s illegal - for loconn instance ports",
2659     __to_vpionam(__wrks1, hp->hrec->htyp));
2660   }
2661  return(NULL);
2662 }
2663 
2664 /*
2665  * build the iterator for all ports connecting to inside module instances
2666  *
2667  * each will have different hin_itp and expect many
2668  */
bld_neticonnport_iter(struct h_t * hp)2669 static vpiHandle bld_neticonnport_iter(struct h_t *hp)
2670 {
2671  register int32 hi;
2672  int32 numprts;
2673  vpiHandle ihref;
2674  struct net_t *np;
2675  struct itree_t *itp;
2676  struct pviter_t *iterp;
2677 
2678  np = hp->hrec->hu.hnp;
2679  itp = hp->hin_itp;
2680  numprts = bld_net_iconns(np, itp);
2681  if (numprts <= 0) return(NULL);
2682 
2683  iterp = __alloc_iter(numprts, &ihref);
2684  memcpy(iterp->scanhtab, __ithtab, numprts*sizeof(struct h_t));
2685  memcpy(iterp->ihrectab, __ithrectab, numprts*sizeof(struct hrec_t));
2686  for (hi = 0; hi < numprts; hi++)
2687   {
2688    iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
2689   }
2690  return(ihref);
2691 }
2692 
2693 /*
2694  * build down instance connecting iconns iterators
2695  *
2696  * here any common bits cause all of inst-port handle to be added to iter
2697  * never duplicates since will be different port (inst. term) or different
2698  * instance
2699  *
2700  * but since tran channel per bit, some connections will probably
2701  * connect to same wire and port (i.e. needed to decompose part select or
2702  * wire to all the bits)
2703  *
2704  * algorithm is to count all so know will be at least big enough then
2705  * caller reallocates to shink when done
2706  *
2707  * notice nothing on itree stack here?
2708  * also no filtering of bit range and bit counts because return entire port
2709  *
2710  * SJM 09/20/02 - because this is vectored and only entire ports in
2711  * iterator filter to only one of iconn high conn concat works
2712  */
bld_net_iconns(struct net_t * np,struct itree_t * itp)2713 static int32 bld_net_iconns(struct net_t *np, struct itree_t *itp)
2714 {
2715  register struct net_pin_t *npp;
2716  register struct hrec_t *hrp2;
2717  int32 cnt;
2718  struct h_t *hp2;
2719  struct itree_t *itp2;
2720 
2721  /* iconn loads are input ports */
2722  for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
2723   {
2724    /* SJM 02/22/02 - works because rhs up expr not decomposed so all */
2725    /* loads are same - only difference is use part of port for action */
2726    if (npp->npntyp == NP_PB_ICONN)
2727     {
2728      /* SJM 09/20/02 - for per bit npp forms, ignore all but 1 npp */
2729      /* there will be one npp per bit but only one iterator forllowing LRM */
2730      if (npp->pbi != 0) continue;
2731     }
2732    else if (npp->npntyp != NP_ICONN) continue;
2733 
2734    /* filter out per inst. that is not this instance */
2735    if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
2736     continue;
2737 
2738    if (npp->npproctyp == NP_PROC_INMOD) itp2 = &(itp->in_its[npp->elnpp.eii]);
2739    else
2740     {
2741      /* SJM 04/17/03 - LOOKATME - think inst conn. down into illegal */
2742      /* but leaving does not hurt */
2743      __push_itstk(itp);
2744      if (!__move_to_npprefloc(npp))
2745       {
2746        __pop_itstk();
2747        continue;
2748       }
2749      itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
2750      __pop_itstk();
2751      __pop_itstk();
2752     }
2753 
2754    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
2755    hp2 = &(__ithtab[cnt]);
2756    hrp2 = &(__ithrectab[cnt++]);
2757    __init_hrec(hrp2);
2758    hrp2->in_iter = TRUE;
2759 
2760    hrp2->in_iter = TRUE;
2761    hrp2->htyp = vpiPort;
2762    hrp2->hu.hpi = npp->obnum;
2763    hp2->hin_itp = itp2;
2764    /* only need to set cross link in newly added one */
2765    hp2->hrec = hrp2;
2766   }
2767  /* will be no drivers and no tran channel for reg */
2768  if (np->ntyp >= NONWIRE_ST)
2769   {
2770    /* DBG remove --- */
2771    if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
2772    /* --- */
2773    goto done;
2774   }
2775 
2776  /* iconn drivers are output ports and only exist for wires */
2777  for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
2778   {
2779    /* PB iconns only for loads */
2780    /* DBG remove -- */
2781    if (npp->npntyp == NP_PB_ICONN) __vpi_terr(__FILE__, __LINE__);
2782    /* -- */
2783    if (npp->npntyp != NP_ICONN) continue;
2784 
2785    /* filter out per inst. that is not this instance */
2786    if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
2787     continue;
2788 
2789    if (npp->npproctyp == NP_PROC_INMOD) itp2 = &(itp->in_its[npp->elnpp.eii]);
2790    else
2791     {
2792      /* SJM 04/17/03 - LOOKATME - think inst conn. down into illegal */
2793      /* but leaving does not hurt */
2794      __push_itstk(itp);
2795      if (!__move_to_npprefloc(npp))
2796       {
2797        __pop_itstk();
2798        continue;
2799       }
2800      itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
2801      __pop_itstk();
2802      __pop_itstk();
2803     }
2804 
2805    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
2806    hp2 = &(__ithtab[cnt]);
2807    hrp2 = &(__ithrectab[cnt++]);
2808    __init_hrec(hrp2);
2809    hrp2->in_iter = TRUE;
2810 
2811    hrp2->in_iter = TRUE;
2812    hrp2->htyp = vpiPort;
2813    hrp2->hu.hpi = npp->obnum;
2814 
2815    /* vpi handle parent will get module/instance port in */
2816    hp2->hin_itp = itp2;
2817    /* only need to set cross link in newly added one */
2818    hp2->hrec = hrp2;
2819   }
2820 
2821  /* finally inout if they exist */
2822  if (np->ntraux == NULL) goto done;
2823 
2824  /* iconns in tran channels are only bid iconns */
2825  for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
2826   {
2827    if (npp->npntyp != NP_BIDICONN) continue;
2828 
2829    /* filter out per inst. that is not this instance */
2830    if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
2831     continue;
2832 
2833    if (npp->npproctyp == NP_PROC_INMOD) itp2 = &(itp->in_its[npp->elnpp.eii]);
2834    else
2835     {
2836      /* can be iconn from other instance for xmr */
2837      /* SJM 04/17/03 - LOOKATME - think inst conn. down into illegal */
2838      /* but leaving does not hurt */
2839      __push_itstk(itp);
2840      if (!__move_to_npprefloc(npp))
2841       {
2842        __pop_itstk();
2843        continue;
2844       }
2845      itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
2846      __pop_itstk();
2847      __pop_itstk();
2848     }
2849 
2850    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
2851    hp2 = &(__ithtab[cnt]);
2852    hrp2 = &(__ithrectab[cnt++]);
2853    __init_hrec(hrp2);
2854    hrp2->in_iter = TRUE;
2855    hrp2->htyp = vpiPort;
2856    hrp2->hu.hpi = npp->obnum;
2857    /* vpi handle parent will get module/instance port in */
2858    hp2->hin_itp = itp2;
2859    /* only need to set cross link in newly added one */
2860    hp2->hrec = hrp2;
2861   }
2862 done:
2863  return(cnt);
2864 }
2865 
2866 /*
2867  * return T if find tran channel inst-port that matches one already
2868  * in iterator
2869  */
same_vpi_handle(struct h_t * htab,int32 fr,int32 num,struct h_t * hp2,struct hrec_t * hrp2)2870 static int32 same_vpi_handle(struct h_t *htab, int32 fr, int32 num, struct h_t *hp2,
2871  struct hrec_t *hrp2)
2872 {
2873  register int32 hi;
2874  register struct h_t *hp;
2875  register struct hrec_t *hrp;
2876 
2877  for (hi = fr; hi < num; hi++)
2878   {
2879    hp = &(htab[hi]);
2880    hrp = hp->hrec;
2881 
2882    switch (hrp->htyp) {
2883     case vpiPort:
2884      if (hrp2->htyp != vpiPort) break;
2885      if (hp2->hin_itp != hp->hin_itp) break;
2886      if (hrp2->hu.hpi != hrp->hu.hpi) break;
2887      return(TRUE);
2888     case vpiContAssign:
2889      if (hrp2->htyp != vpiContAssign) break;
2890      if (hp2->hin_itp != hp->hin_itp) break;
2891      if (hrp2->htyp2 == vpiGate || hrp->htyp2 == vpiGate)
2892       {
2893        if (hrp2->htyp2 != vpiGate || hrp->htyp2 != vpiGate) break;
2894        if (hrp2->hu.hgp != hrp->hu.hgp) break;
2895       }
2896      else if (hrp2->hu.hcap != hrp->hu.hcap) break;
2897      return(TRUE);
2898     case vpiPrimTerm:
2899      /* terminal of gate */
2900      if (hrp2->htyp != vpiPrimTerm) break;
2901      if (hp2->hin_itp != hp->hin_itp) break;
2902      if (hrp2->hu.hgp != hrp->hu.hgp) break;
2903      if (hrp2->hi != hrp->hi) break;
2904      return(TRUE);
2905     case vpiModPathOut:
2906      if (hrp2->htyp != vpiModPathOut) break;
2907 chk_modpath:
2908      if (hp2->hin_itp != hp->hin_itp) break;
2909      if (hrp2->hu.hpthp != hrp->hu.hpthp) break;
2910      if (hrp2->hi != hrp->hi) break;
2911      return(TRUE);
2912     case vpiModPathIn:
2913      if (hrp2->htyp != vpiModPathIn) break;
2914      goto chk_modpath;
2915     case vpiForce:
2916      if (hrp2->htyp != vpiForce) break;
2917      if (hp2->hin_itp != hp->hin_itp) break;
2918      if (hrp2->hu.hstp != hrp->hu.hstp) break;
2919      return(TRUE);
2920     default: __vpi_terr(__FILE__, __LINE__);
2921    }
2922  }
2923  return(FALSE);
2924 }
2925 
2926 /*
2927  * build the iterator for all port bits connecting to inside module instances
2928  * given a vpi net or reg bit handle, build iterator of port bit handles
2929  *
2930  * if iconn contenate or operator expression - returns entire handle
2931  */
bld_netbiticonnport_iter(struct h_t * hp)2932 static vpiHandle bld_netbiticonnport_iter(struct h_t *hp)
2933 {
2934  register int32 hi;
2935  int32 bi, numprts;
2936  vpiHandle ihref;
2937  struct net_t *np;
2938  struct itree_t *itp;
2939  struct pviter_t *iterp;
2940 
2941  if ((bi = cmp_drvld_bitndx(&np, hp, "vpiPortInst")) == -1) return(NULL);
2942 
2943  itp = hp->hin_itp;
2944  numprts = bld_netbit_iconns(np, bi, itp);
2945  if (numprts <= 0) return(NULL);
2946 
2947  iterp = __alloc_iter(numprts, &ihref);
2948  memcpy(iterp->scanhtab, __ithtab, numprts*sizeof(struct h_t));
2949  memcpy(iterp->ihrectab, __ithrectab, numprts*sizeof(struct hrec_t));
2950  for (hi = 0; hi < numprts; hi++)
2951   {
2952    iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
2953   }
2954  return(ihref);
2955 }
2956 
2957 /*
2958  * build down instance connecting iconns iterators
2959  *
2960  * here any common bits cause all of inst-port handle to be added to iter
2961  * never duplicates since will be different port (inst. term) or different
2962  * instance
2963  *
2964  * but since tran channel per bit, some connections will probably
2965  * connect to same wire and port (i.e. needed to decompose part select or
2966  * wire to all the bits)
2967  *
2968  * algorithm is to count all so know will be at least big enough then
2969  * caller reallocates to shink when done
2970  *
2971  * notice nothing on itree stack here?
2972  */
bld_netbit_iconns(struct net_t * np,int32 bi,struct itree_t * itp)2973 static int32 bld_netbit_iconns(struct net_t *np, int32 bi, struct itree_t *itp)
2974 {
2975  register struct net_pin_t *npp;
2976  register struct hrec_t *hrp2;
2977  int32 ri1, ri2, cnt, nd_itpop, not_lhs;
2978  struct h_t *hp2;
2979  struct itree_t *itp2;
2980  struct mod_t *downmdp;
2981  struct mod_pin_t *mpp;
2982 
2983  __push_itstk(itp);
2984  /* iconn loads are input ports */
2985  for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
2986   {
2987    /* SJM 02/22/02 - works because rhs up expr not decomposed so all */
2988    /* loads are same - only difference is use part of port for action */
2989    if (npp->npntyp != NP_ICONN && npp->npntyp != NP_PB_ICONN) continue;
2990 
2991    /* filter out per inst. that is not this instance */
2992    if (npp->npproctyp == NP_PROC_FILT
2993     && npp->npaux->npu.filtitp != __inst_ptr) continue;
2994 
2995    /* can be iconn from other instance for xmr */
2996    nd_itpop = FALSE;
2997    if (npp->npproctyp != NP_PROC_INMOD)
2998     {
2999      /* SJM 04/17/03 - LOOKATME - think inst conn. down into illegal */
3000      /* but leaving does not hurt */
3001      if (!__move_to_npprefloc(npp)) continue;
3002      nd_itpop = TRUE;
3003     }
3004 
3005    /* this must run with right itree loc. */
3006    __get_bidnpp_sect(np, npp, &ri1, &ri2);
3007    if (ri1 == -1 || bi == -1) goto got_match;
3008    if (bi > ri1 || bi < ri2) goto nxt_npp;
3009 
3010 got_match:
3011    /* if iconn not lvalue (variable, bit or part select or mod pin concate */
3012    /* need warning and use entire vpiPort */
3013    itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
3014    downmdp = itp2->itip->imsym->el.emdp;
3015    if (npp->npntyp == NP_ICONN)
3016     {
3017      mpp = &(downmdp->mpins[npp->obnum]);
3018      if (!iconnbit_lvalue(mpp, npp, itp2)) not_lhs = TRUE;
3019      else not_lhs = FALSE;
3020 
3021      if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
3022      hp2 = &(__ithtab[cnt]);
3023      hrp2 = &(__ithrectab[cnt++]);
3024      __init_hrec(hrp2);
3025      hrp2->in_iter = TRUE;
3026      hrp2->hu.hpi = npp->obnum;
3027 
3028      if (mpp->mpwide == 1 || not_lhs) hrp2->htyp = vpiPort;
3029      else
3030       {
3031        hrp2->htyp = vpiPortBit;
3032        /* notice these are internal h:0 - fixed when index accessed */
3033        /* correct for port bit from non concatenate net bit */
3034        /* LOOKATME - is this right? */
3035        if (ri1 == -1) hrp2->hi = bi; else hrp2->hi = bi - ri2;
3036       }
3037     }
3038    else
3039     {
3040      /* SJM 09/20/02 - for per bit separated input iconn, need double ndxing */
3041      if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
3042      hp2 = &(__ithtab[cnt]);
3043      hrp2 = &(__ithrectab[cnt++]);
3044      __init_hrec(hrp2);
3045      hrp2->in_iter = TRUE;
3046      hrp2->hu.hpi = npp->obnum;
3047      hrp2->htyp = vpiPortBit;
3048      hrp2->hi = bi;
3049     }
3050    hp2->hin_itp = itp2;
3051    /* only need to set cross link in newly added one */
3052    hp2->hrec = hrp2;
3053 
3054 nxt_npp:
3055    if (nd_itpop) __pop_itstk();
3056   }
3057  /* will be no drivers and no tran channel for reg */
3058  if (np->ntyp >= NONWIRE_ST)
3059   {
3060    /* DBG remove --- */
3061    if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
3062    /* --- */
3063    goto done;
3064   }
3065  /* iconn drivers are output ports and only exist for wires */
3066  for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
3067   {
3068    /* SJM 09/20/02 - since this is output port iconn, never per bit */
3069    if (npp->npntyp != NP_ICONN) continue;
3070 
3071    /* filter out per inst. that is not this instance */
3072    if (npp->npproctyp == NP_PROC_FILT
3073     && npp->npaux->npu.filtitp != __inst_ptr) continue;
3074 
3075    /* can be iconn from other instance for xmr */
3076    nd_itpop = FALSE;
3077    if (npp->npproctyp != NP_PROC_INMOD)
3078     {
3079      /* SJM 04/17/03 - LOOKATME - think inst conn. down into illegal */
3080      /* but leaving does not hurt */
3081      if (!__move_to_npprefloc(npp)) continue;
3082      nd_itpop = TRUE;
3083     }
3084 
3085    /* this must run with right itree loc. */
3086    __get_bidnpp_sect(np, npp, &ri1, &ri2);
3087    if (ri1 == -1 || bi == -1) goto got_match2;
3088    if (bi > ri1 || bi < ri2) goto nxt2_npp;
3089 
3090 got_match2:
3091    /* if iconn not lvalue (variable, bit or part select or mod pin concate */
3092    /* need warning and use entire vpiPort */
3093    itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
3094    downmdp = itp2->itip->imsym->el.emdp;
3095    mpp = &(downmdp->mpins[npp->obnum]);
3096    if (!iconnbit_lvalue(mpp, npp, itp2)) not_lhs = TRUE;
3097    else not_lhs = FALSE;
3098 
3099    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
3100    hp2 = &(__ithtab[cnt]);
3101    hrp2 = &(__ithrectab[cnt++]);
3102    __init_hrec(hrp2);
3103    hrp2->in_iter = TRUE;
3104    hrp2->htyp = vpiPort;
3105    hrp2->hu.hpi = npp->obnum;
3106 
3107    if (mpp->mpwide == 1 || not_lhs) hrp2->htyp = vpiPort;
3108    else
3109     {
3110      hrp2->htyp = vpiPortBit;
3111      /* notice these are internal h:0 - fixed when index accessed */
3112      /* correct for port bit from non concatenate net bit */
3113      if (ri1 == -1) hrp2->hi = bi; else hrp2->hi = bi - ri2;
3114     }
3115    hp2->hin_itp = itp2;
3116    /* only need to set cross link in newly added one */
3117    hp2->hrec = hrp2;
3118 
3119 nxt2_npp:
3120    if (nd_itpop) __pop_itstk();
3121   }
3122  /* finally inout if they exist */
3123  if (np->ntraux == NULL) goto done;
3124 
3125  /* iconn drivers are output ports and only exist for wires */
3126  for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
3127   {
3128    if (npp->npntyp != NP_BIDICONN) continue;
3129 
3130    /* filter out per inst. that is not this instance */
3131    if (npp->npproctyp == NP_PROC_FILT
3132     && npp->npaux->npu.filtitp != __inst_ptr) continue;
3133 
3134    /* can be iconn from other instance for xmr */
3135    nd_itpop = FALSE;
3136    if (npp->npproctyp != NP_PROC_INMOD)
3137     {
3138      /* SJM 04/17/03 - LOOKATME - think inst conn. down into illegal */
3139      /* but leaving does not hurt */
3140      if (!__move_to_npprefloc(npp)) continue;
3141      nd_itpop = TRUE;
3142     }
3143 
3144    /* this must run with right itree loc. */
3145    __get_bidnpp_sect(np, npp, &ri1, &ri2);
3146    if (ri1 == -1 || bi == -1) goto got_match3;
3147    if (bi > ri1 || bi < ri2) goto nxt3_npp;
3148 
3149 got_match3:
3150    /* if iconn not lvalue (variable, bit or part select or mod pin concate */
3151    /* need warning and use entire vpiPort */
3152    itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
3153    downmdp = itp2->itip->imsym->el.emdp;
3154    mpp = &(downmdp->mpins[npp->obnum]);
3155    if (!iconnbit_lvalue(mpp, npp, itp2)) not_lhs = TRUE;
3156    else not_lhs = FALSE;
3157 
3158    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
3159    hp2 = &(__ithtab[cnt]);
3160    hrp2 = &(__ithrectab[cnt++]);
3161    __init_hrec(hrp2);
3162    hrp2->in_iter = TRUE;
3163    hrp2->htyp = vpiPort;
3164    hrp2->hu.hpi = npp->obnum;
3165 
3166    if (mpp->mpwide == 1 || not_lhs) hrp2->htyp = vpiPort;
3167    else
3168     {
3169      hrp2->htyp = vpiPortBit;
3170      /* notice these are internal h:0 - fixed when index accessed */
3171      /* correct for port bit from non concatenate net bit */
3172      if (ri1 == -1) hrp2->hi = bi; else hrp2->hi = bi - ri2;
3173     }
3174    hp2->hin_itp = itp2;
3175    /* only need to set cross link in newly added one */
3176    hp2->hrec = hrp2;
3177 
3178 nxt3_npp:
3179    if (nd_itpop) __pop_itstk();
3180   }
3181 
3182 done:
3183  __pop_itstk();
3184  return(cnt);
3185 }
3186 
3187 /*
3188  * return T if good port and iconn simple (non concat) lvalue
3189  */
iconnbit_lvalue(struct mod_pin_t * mpp,struct net_pin_t * npp,struct itree_t * itp2)3190 static int32 iconnbit_lvalue(struct mod_pin_t *mpp, struct net_pin_t *npp,
3191  struct itree_t *itp2)
3192 {
3193  struct expr_t *xp;
3194 
3195  if (mpp->mpref->optyp == LCB) return(FALSE);
3196  xp = itp2->itip->ipins[npp->obnum];
3197  if (xp->optyp == ID || xp->optyp == GLBREF || xp->optyp == LSB ||
3198   xp->optyp == PARTSEL) return(TRUE);
3199  return(FALSE);
3200 }
3201 
3202 /*
3203  * ROUTINES TO BUILD LOCAL LOAD ITERATORS
3204  */
3205 
3206 /*
3207  * build an iterator of wire or reg (or bit) local loads
3208  *
3209  * list differs but otherwise code is same
3210  * inout ports and trans are both loads and drivers
3211  *
3212  * this is local loads including ports and works for vectors
3213  * local loads give user exact control over connectivity tracing
3214  */
__bld_loc_lds_iterator(struct h_t * hp,int32 otype)3215 extern vpiHandle __bld_loc_lds_iterator(struct h_t *hp, int32 otype)
3216 {
3217  if (hp == NULL) return(__nil_iter_err(otype));
3218 
3219  /* routine for each thing that load can be of */
3220  switch (hp->hrec->htyp) {
3221   case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
3222    return(net_lds_iter(hp));
3223   case vpiNetBit: case vpiRegBit: case vpiVarSelect:
3224    return(bit_lds_iter(hp));
3225   default:
3226    __vpi_err(1874, vpiError,
3227     "vpiLocalLoad 1-to-many iterator from %s illegal - for net/reg/variable loads",
3228     __to_vpionam(__wrks1, hp->hrec->htyp));
3229   }
3230  return(NULL);
3231 }
3232 
3233 /*
3234  * build entire wire net load iterator - in list if any bits
3235  *
3236  * caller must know type of iterator that is scanned since ld and driver
3237  * same except for list used
3238  */
net_lds_iter(struct h_t * hp)3239 static vpiHandle net_lds_iter(struct h_t *hp)
3240 {
3241  register int32 hi;
3242  int32 num;
3243  vpiHandle ihref;
3244  struct net_t *np;
3245  struct itree_t *itp;
3246  struct pviter_t *iterp;
3247 
3248  np = hp->hrec->hu.hnp;
3249  itp = hp->hin_itp;
3250  if ((num = bld_net_lds(np, itp)) <= 0) return(NULL);
3251 
3252  iterp = __alloc_iter(num, &ihref);
3253  memcpy(iterp->scanhtab, __ithtab, num*sizeof(struct h_t));
3254  memcpy(iterp->ihrectab, __ithrectab, num*sizeof(struct hrec_t));
3255  for (hi = 0; hi < num; hi++)
3256   {
3257    iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
3258   }
3259  return(ihref);
3260 }
3261 
3262 /*
3263  * build loads on a net or reg (match on any common bits)
3264  *
3265  * but since tran channel per bit, some connections will probably
3266  * connect to same wire and port (i.e. needed to decompose part select or
3267  * wire to all the bits)
3268  *
3269  * algorithm is to count all so know will be at least big enough then
3270  * caller reallocates to shink when done
3271  *
3272  * notice nothing on itree stack here?
3273  * also no need to filter bit range and bit counts
3274  */
bld_net_lds(struct net_t * np,struct itree_t * itp)3275 static int32 bld_net_lds(struct net_t *np, struct itree_t *itp)
3276 {
3277  register struct net_pin_t *npp;
3278  register struct hrec_t *hrp2;
3279  int32 cnt, nd_itpop;
3280  struct h_t tmph, *hp2;
3281  struct hrec_t tmphrec;
3282 
3283  __push_itstk(itp);
3284  /* for hard inout/tran channel hard loads, found here */
3285  for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
3286   {
3287    /* SJM 07/12/01 - until add v2k delay devices, omit mipd chg load */
3288    if (npp->npntyp == NP_MIPD_NCHG) continue;
3289    if (npp->npntyp == NP_PB_ICONN && npp->pbi != 0) continue;
3290 
3291    /* filter out per inst. that is not this instance */
3292    if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
3293     continue;
3294    /* maybe move to right ref. itree loc. */
3295    nd_itpop = FALSE;
3296    if (npp->npproctyp != NP_PROC_INMOD)
3297     {
3298      /* SJM 04/17/03 - must match each inst in xmr path */
3299      /* but leaving does not hurt */
3300      if (!__move_to_npprefloc(npp)) continue;
3301      nd_itpop = TRUE;
3302     }
3303    __init_hrec(&tmphrec);
3304    tmphrec.in_iter = TRUE;
3305    tmph.hrec = &tmphrec;
3306    if (!fill_ld_handle(&tmph, &tmphrec, npp)) goto nxt_npp;
3307 
3308    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
3309    hp2 = &(__ithtab[cnt]);
3310    hrp2 = &(__ithrectab[cnt++]);
3311 
3312    memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
3313    hp2->hin_itp = tmph.hin_itp;
3314    /* only need to set cross link in newly added one */
3315    hp2->hrec = hrp2;
3316 
3317 nxt_npp:
3318    if (nd_itpop) __pop_itstk();
3319   }
3320  /* will be no drivers and no tran channel for reg */
3321  if (np->ntyp >= NONWIRE_ST)
3322   {
3323    /* DBG remove --- */
3324    if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
3325    /* --- */
3326    goto done;
3327   }
3328  /* tran channel npps - go in both ld and driver iterators */
3329  if (np->ntraux == NULL) goto done;
3330 
3331  /* SJM 05/15/99 - although not using npp's for inouts they are kept */
3332  /* around because they are needed for PLI load/driver iterators */
3333  for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
3334   {
3335    /* filter out per inst. that is not this instance */
3336    if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
3337     continue;
3338 
3339    /* maybe move to right ref. itree loc. */
3340    nd_itpop = FALSE;
3341    if (npp->npproctyp != NP_PROC_INMOD)
3342     {
3343      /* SJM 04/17/03 - must match each inst in xmr path */
3344      if (!__move_to_npprefloc(npp)) continue;
3345      nd_itpop = TRUE;
3346     }
3347    __init_hrec(&tmphrec);
3348    tmphrec.in_iter = TRUE;
3349    if (!fill_ld_handle(&tmph, &tmphrec, npp)) goto nxt2_npp;
3350    tmph.hrec = &tmphrec;
3351 
3352    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
3353    hp2 = &(__ithtab[cnt]);
3354    hrp2 = &(__ithrectab[cnt++]);
3355 
3356    memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
3357    hp2->hin_itp = tmph.hin_itp;
3358    /* only need to set cross link in newly added one */
3359    hp2->hrec = hrp2;
3360 
3361 nxt2_npp:
3362    if (nd_itpop) __pop_itstk();
3363   }
3364 done:
3365  __pop_itstk();
3366  return(cnt);
3367 }
3368 
3369 /*
3370  * fill a load handle - if non handle element, return nil
3371  *
3372  * caller must have initialized fields in handle
3373  * this must be called from ref. (stacked itree loc) for xmr
3374  */
fill_ld_handle(struct h_t * hp,struct hrec_t * hrp,struct net_pin_t * npp)3375 static int32 fill_ld_handle(struct h_t *hp, struct hrec_t *hrp,
3376  struct net_pin_t *npp)
3377 {
3378  struct itree_t *itp2;
3379  struct gate_t *gp;
3380 
3381  hp->hin_itp = __inst_ptr;
3382  switch ((byte) npp->npntyp) {
3383   case NP_ICONN: case NP_BIDICONN: case NP_PB_ICONN:
3384    /* load iconn is input port */
3385    hrp->htyp = vpiPort;
3386    hrp->hu.hpi = npp->obnum;
3387    itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
3388    hp->hin_itp = itp2;
3389    break;
3390   case NP_MDPRT: case NP_BIDMDPRT: case NP_PB_MDPRT:
3391    /* load mdprt is output port */
3392    hrp->htyp = vpiPort;
3393    hrp->hu.hpi = npp->obnum;
3394    break;
3395   case NP_CONTA:
3396    hrp->htyp = vpiContAssign;
3397    hrp->hu.hcap = npp->elnpp.ecap;
3398    break;
3399   case NP_GATE: case NP_TRANIF: case NP_TRAN:
3400    gp = npp->elnpp.egp;
3401    if (gp->gmsym->el.eprimp->gateid == G_ASSIGN)
3402     {
3403      hrp->htyp = vpiContAssign;
3404      hrp->htyp2 = vpiGate;
3405      hrp->hu.hgp = gp;
3406     }
3407    else
3408     {
3409      gp = npp->elnpp.egp;
3410      hrp->htyp = vpiPrimTerm;
3411      hrp->hu.hgp = gp;
3412      hrp->hi = npp->obnum;
3413     }
3414    break;
3415   default: return(FALSE);
3416  }
3417  return(TRUE);
3418 }
3419 
3420 /*
3421  * build the iterator for all port bits connecting to inside module instances
3422  * given a vpi net or reg bit handle, build iterator of port bit handles
3423  *
3424  * builds in ithtab and then allocates iterator and copies into it
3425  */
bit_lds_iter(struct h_t * hp)3426 static vpiHandle bit_lds_iter(struct h_t *hp)
3427 {
3428  register int32 hi;
3429  int32 bi, num;
3430  vpiHandle ihref;
3431  struct net_t *np;
3432  struct itree_t *itp;
3433  struct pviter_t *iterp;
3434 
3435  if ((bi = cmp_drvld_bitndx(&np, hp, "vpiLoad/vpiLocalLoad")) == -1)
3436   return(NULL);
3437 
3438  itp = hp->hin_itp;
3439  num = bld_bit_lds(np, bi, itp, FALSE);
3440  if (num <= 0) return(NULL);
3441 
3442  iterp = __alloc_iter(num, &ihref);
3443  memcpy(iterp->scanhtab, __ithtab, num*sizeof(struct h_t));
3444  memcpy(iterp->ihrectab, __ithrectab, num*sizeof(struct hrec_t));
3445  for (hi = 0; hi < num; hi++)
3446   {
3447    iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
3448   }
3449  return(ihref);
3450 }
3451 
3452 /*
3453  * build net bit loads or drivers iterator
3454  *
3455  * fills ithtab that then gets copied from later
3456  *
3457  * since per bit never a need to remove duplicates
3458  * passed itp is instance of load npp
3459  * notice this works for scalar where bi must be -1
3460  */
bld_bit_lds(struct net_t * np,int32 bi,struct itree_t * itp,int32 no_ports)3461 static int32 bld_bit_lds(struct net_t *np, int32 bi, struct itree_t *itp,
3462  int32 no_ports)
3463 {
3464  register struct net_pin_t *npp;
3465  register struct hrec_t *hrp2;
3466  int32 ri1, ri2, cnt, nd_itpop;
3467  struct h_t tmph, *hp2;
3468  struct hrec_t tmphrec;
3469 
3470  __push_itstk(itp);
3471  /* iconn loads are input ports */
3472  for (cnt = 0, npp = np->nlds; npp != NULL; npp = npp->npnxt)
3473   {
3474    /* SJM 07/12/01 - until add v2k delay devices, omit mipd chg load */
3475    if (npp->npntyp == NP_MIPD_NCHG) continue;
3476 
3477    /* filter out per inst. that is not this instance */
3478    if (npp->npproctyp == NP_PROC_FILT
3479     && npp->npaux->npu.filtitp != __inst_ptr) continue;
3480 
3481    /* can be iconn from other instance for xmr */
3482    nd_itpop = FALSE;
3483    if (npp->npproctyp != NP_PROC_INMOD)
3484     {
3485      /* SJM 04/17/03 - must match each inst in xmr path */
3486      if (!__move_to_npprefloc(npp)) continue;
3487      nd_itpop = TRUE;
3488     }
3489 
3490    /* this must run with right itree loc. */
3491    __get_bidnpp_sect(np, npp, &ri1, &ri2);
3492    if (ri1 == -1 || bi == -1) goto got_match;
3493    if (bi > ri1 || bi < ri2) goto nxt_npp;
3494 
3495 got_match:
3496    if (no_ports)
3497     {
3498      /* remove port npp's */
3499      switch ((byte) npp->npntyp) {
3500       case NP_ICONN: case NP_BIDICONN: case NP_MDPRT: case NP_BIDMDPRT:
3501       case NP_PB_ICONN: case NP_PB_MDPRT:
3502        goto nxt_npp;
3503       default: break;
3504      }
3505     }
3506 
3507    __init_hrec(&tmphrec);
3508    tmphrec.in_iter = TRUE;
3509    tmph.hrec = &tmphrec;
3510 
3511    if (!fill_bit_ld_handle(&tmph, &tmphrec, bi, ri1, ri2, npp)) goto nxt_npp;
3512 
3513    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
3514    hp2 = &(__ithtab[cnt]);
3515    hrp2 = &(__ithrectab[cnt++]);
3516 
3517    memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
3518 
3519    hp2->hin_itp = tmph.hin_itp;
3520    /* only need to set cross link in newly added one */
3521    hp2->hrec = hrp2;
3522 
3523 nxt_npp:
3524    if (nd_itpop) __pop_itstk();
3525   }
3526  /* will be no drivers and no tran channel for reg */
3527  if (np->ntyp >= NONWIRE_ST)
3528   {
3529    /* DBG remove --- */
3530    if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
3531    /* --- */
3532    goto done;
3533   }
3534  /* tran channel connections if they exist */
3535  if (np->ntraux == NULL) goto done;
3536 
3537  /* iconn tran channel connections are all loads */
3538  for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
3539   {
3540    /* filter out per inst. that is not this instance */
3541    if (npp->npproctyp == NP_PROC_FILT
3542     && npp->npaux->npu.filtitp != __inst_ptr) continue;
3543 
3544    /* can be iconn from other instance for xmr */
3545    nd_itpop = FALSE;
3546    if (npp->npproctyp != NP_PROC_INMOD)
3547     {
3548      /* SJM 04/17/03 - must match each inst in xmr path */
3549      if (!__move_to_npprefloc(npp)) continue;
3550      nd_itpop = TRUE;
3551     }
3552 
3553    /* this must run with right itree loc. */
3554    __get_bidnpp_sect(np, npp, &ri1, &ri2);
3555    if (ri1 == -1 || bi == -1) goto got2_match;
3556    if (bi > ri1 || bi < ri2) goto nxt2_npp;
3557 
3558 got2_match:
3559    if (no_ports)
3560     {
3561      /* remove port npp's */
3562      switch ((byte) npp->npntyp) {
3563       case NP_ICONN: case NP_BIDICONN: case NP_MDPRT: case NP_BIDMDPRT:
3564       case NP_PB_ICONN: case NP_PB_MDPRT:
3565        goto nxt2_npp;
3566       default: break;
3567      }
3568     }
3569    __init_hrec(&tmphrec);
3570    tmphrec.in_iter = TRUE;
3571    tmph.hrec = &tmphrec;
3572 
3573    if (!fill_bit_ld_handle(&tmph, &tmphrec, bi, ri1, ri2, npp)) goto nxt_npp;
3574 
3575    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
3576    hp2 = &(__ithtab[cnt]);
3577    hrp2 = &(__ithrectab[cnt++]);
3578 
3579    memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
3580 
3581    hp2->hin_itp = tmph.hin_itp;
3582    /* only need to set cross link in newly added one */
3583    hp2->hrec = hrp2;
3584 
3585 nxt2_npp:
3586    if (nd_itpop) __pop_itstk();
3587   }
3588 done:
3589  __pop_itstk();
3590  return(cnt);
3591 }
3592 
3593 /*
3594  * fill a load handle - if non handle element, return nil
3595  *
3596  * caller must have initialized fields in handle
3597  * this must be called from ref. (stacked itree loc) for xmr
3598  *
3599  * looking for load of net np bit bi (if scalar not called)
3600  */
fill_bit_ld_handle(struct h_t * hp,struct hrec_t * hrp,int32 bi,int32 ri1,int32 ri2,struct net_pin_t * npp)3601 static int32 fill_bit_ld_handle(struct h_t *hp, struct hrec_t *hrp, int32 bi,
3602  int32 ri1, int32 ri2, struct net_pin_t *npp)
3603 {
3604  int32 not_lhs;
3605  struct itree_t *itp2;
3606  struct mod_t *downmdp;
3607  struct mod_pin_t *mpp;
3608  struct gate_t *gp;
3609 
3610  hp->hin_itp = __inst_ptr;
3611  switch ((byte) npp->npntyp) {
3612   case NP_ICONN: case NP_BIDICONN:
3613    /* load iconn is input port */
3614    itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
3615    downmdp = itp2->itip->imsym->el.emdp;
3616    mpp = &(downmdp->mpins[npp->obnum]);
3617    if (!iconnbit_lvalue(mpp, npp, itp2)) not_lhs = TRUE;
3618    else not_lhs = FALSE;
3619    if (mpp->mpwide == 1 || not_lhs) hrp->htyp = vpiPort;
3620    else
3621     {
3622      hrp->htyp = vpiPortBit;
3623      /* notice these are internal h:0 - fixed when index accessed */
3624      if (ri1 == -1) hrp->hi = bi; else hrp->hi = bi - ri2;
3625     }
3626    hrp->hu.hpi = npp->obnum;
3627    hp->hin_itp = itp2;
3628    break;
3629   case NP_PB_ICONN:
3630    /* load iconn is concat high conn one bit of PB separated input port */
3631    itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
3632    downmdp = itp2->itip->imsym->el.emdp;
3633    mpp = &(downmdp->mpins[npp->obnum]);
3634    mpp = &(mpp->pbmpps[npp->pbi]);
3635    hrp->htyp = vpiPortBit;
3636    hrp->hi = bi;
3637    hrp->hu.hpi = npp->obnum;
3638    hp->hin_itp = itp2;
3639    break;
3640   case NP_MDPRT: case NP_BIDMDPRT:
3641    /* load mod port is output port */
3642    mpp = &(__inst_mod->mpins[npp->obnum]);
3643    if (mpp->mpref->optyp == LCB || mpp->mpwide == 1) hrp->htyp = vpiPort;
3644    else
3645     {
3646      hrp->htyp = vpiPortBit;
3647      /* notice these are internal h:0 - fixed when index accessed */
3648      /* correct for port bit from non concatenate net bit */
3649      if (ri1 == -1) hrp->hi = bi; else hrp->hi = bi - ri2;
3650     }
3651    hrp->hu.hpi = npp->obnum;
3652    break;
3653   case NP_PB_MDPRT:
3654    /* load mod port is output port - this is one bit from PB decompose */
3655    /* but still for vpi_ do not use decomposed mpp */
3656    mpp = &(__inst_mod->mpins[npp->obnum]);
3657    /* SJM 11/15/02 - LOOKATME ??? - why is this filter needed */
3658    if (npp->npntyp == NP_PB_MDPRT && npp->pbi != 0) return(FALSE);
3659    hrp->htyp = vpiPortBit;
3660    /* notice these are internal h:0 - fixed when index accessed */
3661    /* correct for port bit from non concatenate net bit */
3662    if (ri1 == -1) hrp->hi = bi; else hrp->hi = bi - ri2;
3663    hrp->hu.hpi = npp->obnum;
3664    break;
3665   case NP_CONTA:
3666    hrp->htyp = vpiContAssign;
3667    hrp->hu.hcap = npp->elnpp.ecap;
3668    break;
3669   case NP_GATE: case NP_TRANIF: case NP_TRAN:
3670    gp = npp->elnpp.egp;
3671    /* must correct for 1 bit conta */
3672    if (gp->gmsym->el.eprimp->gateid == G_ASSIGN)
3673     {
3674      hrp->htyp = vpiContAssign;
3675      hrp->htyp2 = vpiGate;
3676      hrp->hu.hgp = npp->elnpp.egp;
3677      break;
3678     }
3679    hrp->htyp = vpiPrimTerm;
3680    hrp->hu.hgp = gp;
3681    hrp->hi = npp->obnum;
3682    break;
3683   default: return(FALSE);
3684  }
3685  return(TRUE);
3686 }
3687 
3688 /*
3689  * ROUTINES TO BUILD XL STYLE LOAD ITERATORS (SCALAR OR BIT ONLY)
3690  */
3691 
3692 /*
3693  * build an iterator of wire or reg bit XL style collapsed loads
3694  *
3695  * inout ports and trans are both loads and drivers
3696  *
3697  * no ports here - cross and include actual loads from other side
3698  * algorithm sort of (mostly?) duplicates XL collapsing
3699  * only makes sense for 1 bit objects
3700  *
3701  * uese local loads but cross ports
3702  */
__bld_lds_iterator(struct h_t * hp,int32 otype)3703 extern vpiHandle __bld_lds_iterator(struct h_t *hp, int32 otype)
3704 {
3705  struct hrec_t *hrp;
3706 
3707  if (hp == NULL) return(__nil_iter_err(otype));
3708 
3709  hrp = hp->hrec;
3710  /* routine for each thing that load can be of */
3711  switch (hrp->htyp) {
3712   case vpiNet: case vpiReg:
3713    if (hrp->hu.hnp->nwid != 1) goto bad_obj;
3714    return(bit_xl_ldsdrvs_iter(hp, TRUE));
3715   case vpiNetBit: case vpiRegBit: case vpiVarSelect:
3716    return(bit_xl_ldsdrvs_iter(hp, TRUE));
3717   default:
3718 bad_obj:
3719    __vpi_err(1874, vpiError,
3720     "vpiLoad 1-to-many iterator from %s illegal - for one bit net or reg loads only",
3721     __to_vpionam(__wrks1, hrp->htyp));
3722   }
3723  return(NULL);
3724 }
3725 
3726 /*
3727  * build bit XL collapsed style net loads iterator
3728  *
3729  * caller must know type of iterator that is scanned since ld and driver
3730  * same except for list used
3731  *
3732  * differs from acc next load "iterators" because returns contas and
3733  * does not distinguish cells
3734  */
bit_xl_ldsdrvs_iter(struct h_t * hp,int32 do_loads)3735 static vpiHandle bit_xl_ldsdrvs_iter(struct h_t *hp, int32 do_loads)
3736 {
3737  register int32 vti, hi;
3738  int32 bi, vtxnum, num, xlnum, new2siz;
3739  vpiHandle ihref;
3740  struct hrec_t *hrp;
3741  struct itree_t *itp;
3742  struct net_t *np;
3743  struct xldlvtx_t *xldlvp;
3744  struct pviter_t *iterp;
3745 
3746  itp = hp->hin_itp;
3747  hrp = hp->hrec;
3748  /* know if not bit object, then scalar net or reg */
3749  if (hrp->htyp == vpiReg || hrp->htyp == vpiNet)
3750   {
3751    np = hrp->hu.hnp;
3752    bi = -1;
3753   }
3754  else
3755   {
3756    if ((bi = cmp_drvld_bitndx(&np, hp, "vpiLoad")) == -1) return(NULL);
3757   }
3758  /* know there will always be one */
3759  /* 4th arg. T means loads */
3760  vtxnum = __bld_xl_drvld_vtxtab(np, bi, itp, do_loads);
3761 
3762  for (vti = 0, xlnum = 0; vti < vtxnum; vti++)
3763   {
3764    xldlvp = __xldlvtxind[vti];
3765    /* DBG remove -- */
3766    if (xldlvp == NULL) __vpi_terr(__FILE__, __LINE__);
3767    /* --- */
3768 
3769    /* fill ith tab with only non port loads or drivers */
3770    if (do_loads)
3771     {
3772      num = bld_bit_lds(xldlvp->dlnp, xldlvp->dlbi, xldlvp->dlitp, TRUE);
3773     }
3774    else
3775     {
3776      num = bld_bit_drvs(xldlvp->dlnp, xldlvp->dlbi, xldlvp->dlitp, TRUE);
3777     }
3778 
3779    /* copy onto end of 2nd ith tab */
3780    if (num > 0)
3781     {
3782      new2siz = xlnum + num;
3783      if (new2siz >= __ithtsiz2) __grow_htab2(num);
3784 
3785      memcpy(&(__ithtab2[xlnum]), __ithtab, num*sizeof(struct h_t));
3786      memcpy(&(__ithrectab2[xlnum]), __ithrectab, num*sizeof(struct hrec_t));
3787      for (hi = xlnum; hi < num + xlnum; hi++)
3788       { __ithtab2[hi].hrec = &(__ithrectab2[hi]); }
3789      xlnum += num;
3790     }
3791    __my_free((char *) xldlvp, sizeof(struct xldlvtx_t));
3792    __xldlvtxind[vti] = NULL;
3793   }
3794  __num_xldlvtxs = 0;
3795 
3796  /* iterator may be empty */
3797  if(xlnum <= 0) return(NULL);
3798 
3799  /* final step copy from 2nd ith tab into iterator */
3800  iterp = __alloc_iter(xlnum, &ihref);
3801  memcpy(iterp->scanhtab, __ithtab2, xlnum*sizeof(struct h_t));
3802  memcpy(iterp->ihrectab, __ithrectab2, xlnum*sizeof(struct hrec_t));
3803  for (hi = 0; hi < xlnum; hi++)
3804   {
3805    iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
3806   }
3807  /* xl style ld/drvr vertex table to empty */
3808  return(ihref);
3809 }
3810 
3811 /*
3812  * ROUTINES TO BUILD LOCAL DRIVER ITERATOR
3813  */
3814 
3815 /*
3816  * build an iterator of local wire drivers
3817  *
3818  * regs have only qausi-continuous vpiForce and vpiRelease drivers
3819  *
3820  * includes user added vpi drivers
3821  *
3822  * inout ports and trans are both loads and drivers
3823  * user must traverse all of channel to get hard drivers of inout
3824  */
__bld_loc_drvs_iterator(struct h_t * hp,int32 otype)3825 extern vpiHandle __bld_loc_drvs_iterator(struct h_t *hp, int32 otype)
3826 {
3827  if (hp == NULL) return(__nil_iter_err(otype));
3828 
3829  switch (hp->hrec->htyp) {
3830   case vpiNet:
3831    return(net_drvs_iter(hp));
3832   case vpiNetBit:
3833    return(bit_drvs_iter(hp));
3834 
3835   case vpiReg: case vpiIntegerVar: case vpiTimeVar:
3836   case vpiRegBit: case vpiVarSelect:
3837    /* quasi-procedural force and assign are only drivers of regs */
3838    /* also never per bit */
3839    return(reg_drvs_iter(hp));
3840   default:
3841    __vpi_err(1877, vpiError,
3842     "vpiDriver 1-to-many iterator from %s illegal - only variables have drivers",
3843     __to_vpionam(__wrks1, hp->hrec->htyp));
3844   }
3845  return(NULL);
3846 }
3847 
3848 /*
3849  * build entire wire net drivers iterator - in list if any bits
3850  *
3851  * normal drivers plus pull and per bit force
3852  */
net_drvs_iter(struct h_t * hp)3853 static vpiHandle net_drvs_iter(struct h_t *hp)
3854 {
3855  register int32 hi;
3856  int32 num;
3857  vpiHandle ihref;
3858  struct net_t *np;
3859  struct itree_t *itp;
3860  struct pviter_t *iterp;
3861 
3862  np = hp->hrec->hu.hnp;
3863  itp = hp->hin_itp;
3864  num = bld_net_drvs(np, itp);
3865  if (num <= 0) return(NULL);
3866 
3867  iterp = __alloc_iter(num, &ihref);
3868  memcpy(iterp->scanhtab, __ithtab, num*sizeof(struct h_t));
3869  memcpy(iterp->ihrectab, __ithrectab, num*sizeof(struct hrec_t));
3870  for (hi = 0; hi < num; hi++)
3871   {
3872    iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
3873   }
3874  return(ihref);
3875 }
3876 
3877 /*
3878  * build drivers on a net
3879  *
3880  * entire net drivers are not net bit
3881  * nothing on itree stack here
3882  */
bld_net_drvs(struct net_t * np,struct itree_t * itp)3883 static int32 bld_net_drvs(struct net_t *np, struct itree_t *itp)
3884 {
3885  register int32 bi;
3886  register struct net_pin_t *npp;
3887  int32 cnt, cnt2, nd_itpop;
3888  struct h_t tmph, *hp2;
3889  struct hrec_t tmphrec, *hrp2;
3890  struct qcval_t *frc_qcp;
3891 
3892  __push_itstk(itp);
3893  for (cnt = 0, npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
3894   {
3895    /* SJM 09/20/02 - for per bit input port drivers only use first */
3896    if (npp->npntyp == NP_PB_MDPRT && npp->pbi != 0) continue;
3897 
3898    /* filter out per inst. that is not this instance */
3899    if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
3900     continue;
3901    /* maybe move to right ref. itree loc. */
3902    nd_itpop = FALSE;
3903    if (npp->npproctyp != NP_PROC_INMOD)
3904     {
3905      /* SJM 04/17/03 - must match each inst in xmr path */
3906      if (!__move_to_npprefloc(npp)) continue;
3907      nd_itpop = TRUE;
3908     }
3909    __init_hrec(&tmphrec);
3910    tmphrec.in_iter = TRUE;
3911    tmph.hrec = &tmphrec;
3912 
3913    if (!fill_drv_handle(&tmph, &tmphrec, npp)) goto nxt_npp;
3914 
3915    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
3916    hp2 = &(__ithtab[cnt]);
3917    hrp2 = &(__ithrectab[cnt++]);
3918 
3919    memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
3920    hp2->hin_itp = tmph.hin_itp;
3921    /* only need to set cross link in newly added one */
3922    hp2->hrec = hrp2;
3923 
3924 nxt_npp:
3925    if (nd_itpop) __pop_itstk();
3926   }
3927  cnt2 = cnt;
3928  /* will be no drivers and no tran channel for reg */
3929  if (np->ntyp >= NONWIRE_ST)
3930   {
3931    /* DBG remove --- */
3932    if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
3933    /* --- */
3934    goto do_force;
3935   }
3936  /* tran channel npps - go in both ld and driver iterators */
3937  if (np->ntraux == NULL) goto do_force;
3938 
3939  /* notice any tran channel tran/inout port is driver and load */
3940  for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
3941   {
3942    /* filter out per inst. that is not this instance */
3943    if (npp->npproctyp == NP_PROC_FILT && npp->npaux->npu.filtitp != itp)
3944     continue;
3945    /* maybe move to right ref. itree loc. */
3946    nd_itpop = FALSE;
3947    if (npp->npproctyp != NP_PROC_INMOD)
3948     {
3949      /* SJM 04/17/03 - must match each inst in xmr path */
3950      if (!__move_to_npprefloc(npp)) continue;
3951      nd_itpop = TRUE;
3952     }
3953 
3954    __init_hrec(&tmphrec);
3955    tmphrec.in_iter = TRUE;
3956    tmph.hrec = &tmphrec;
3957 
3958    if (!fill_drv_handle(&tmph, &tmphrec, npp)) goto nxt2_npp;
3959 
3960    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
3961    hp2 = &(__ithtab[cnt]);
3962    hrp2 = &(__ithrectab[cnt++]);
3963 
3964    memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
3965    hp2->hin_itp = tmph.hin_itp;
3966    /* only need to set cross link in newly added one */
3967    hp2->hrec = hrp2;
3968 
3969 nxt2_npp:
3970    if (nd_itpop) __pop_itstk();
3971   }
3972  cnt2 = cnt;
3973 
3974 do_force:
3975  /* if not in src or added by PLI, can't be active */
3976  if (!np->frc_assgn_allocated) goto done;
3977 
3978  /* for scalar bit 0 right */
3979  /* ?? LOOKATME - this was low to high */
3980  frc_qcp = &(np->nu2.qcval[__inum*np->nwid + np->nwid - 1]);
3981  /* 11/22/02 AIV removed equal in for break bi >= */
3982  for (bi = np->nwid - 1; bi > 0; bi--, frc_qcp--)
3983   {
3984 
3985    /* 11/22/02 AIV must check for null case */
3986    if(frc_qcp == NULL) break;
3987    if (frc_qcp->qc_active)
3988     {
3989      /* FIXME - vpi_ driver not found as driver - vpi_ must keep track */
3990      /* if vpi_ force, do not return as driver */
3991      if (frc_qcp->qcstp == NULL) continue;
3992 
3993      __init_hrec(&tmphrec);
3994      tmphrec.in_iter = TRUE;
3995      tmph.hrec = &tmphrec;
3996 
3997      tmphrec.htyp = vpiForce;
3998      tmphrec.hu.hstp = frc_qcp->qcstp;
3999      tmph.hin_itp = __inst_ptr;
4000 
4001      if (cnt != 0 && same_vpi_handle(__ithtab, cnt2, cnt, &tmph, &tmphrec))
4002       continue;
4003 
4004      if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
4005      hp2 = &(__ithtab[cnt]);
4006      hrp2 = &(__ithrectab[cnt++]);
4007      memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
4008      hp2->hin_itp = tmph.hin_itp;
4009      /* only need to set cross link in newly added one */
4010      hp2->hrec = hrp2;
4011     }
4012   }
4013 
4014 done:
4015  __pop_itstk();
4016  return(cnt);
4017 }
4018 
4019 /*
4020  * fill a driver handle (hp) - if non handle element, return nil
4021  * notice same rules for loads and drivers (iterator type determines)
4022  *
4023  * caller must have initialized fields (for iterator type)
4024  * this must be called from ref. (stacked itree loc) for xmr
4025  */
fill_drv_handle(struct h_t * hp,struct hrec_t * hrp,struct net_pin_t * npp)4026 static int32 fill_drv_handle(struct h_t *hp, struct hrec_t *hrp,
4027  struct net_pin_t *npp)
4028 {
4029  struct itree_t *itp2;
4030  struct gate_t *gp;
4031 
4032  hp->hin_itp = __inst_ptr;
4033  switch ((byte) npp->npntyp) {
4034   case NP_ICONN: case NP_BIDICONN:
4035    /* SJM 09/20/02 - PB ICONN form only possible for loads */
4036    /* iconn driver is output port */
4037    hrp->htyp = vpiPort;
4038    hrp->hu.hpi = npp->obnum;
4039    itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
4040    hp->hin_itp = itp2;
4041    break;
4042   case NP_MDPRT: case NP_BIDMDPRT: case NP_PB_MDPRT:
4043    /* iconn driver is input port */
4044    hrp->htyp = vpiPort;
4045    hrp->hu.hpi = npp->obnum;
4046    break;
4047   case NP_CONTA:
4048    hrp->htyp = vpiContAssign;
4049    hrp->hu.hcap = npp->elnpp.ecap;
4050    break;
4051   case NP_GATE: case NP_TRANIF: case NP_TRAN:
4052    gp = npp->elnpp.egp;
4053    if (gp->gmsym->el.eprimp->gateid == G_ASSIGN)
4054     {
4055      hrp->htyp = vpiContAssign;
4056      hrp->htyp2 = vpiGate;
4057      hrp->hu.hgp = gp;
4058     }
4059    else
4060     {
4061      hrp->htyp = vpiPrimTerm;
4062      hrp->hu.hgp = gp;
4063      hrp->hi = npp->obnum;
4064     }
4065    break;
4066   case NP_VPIPUTV:
4067    /* include entire wire or any bit's driver here */
4068    if (npp->npaux != NULL && npp->npaux->nbi1 != -1)
4069     {
4070      hrp->htyp = vpiNetBitDriver;
4071      hrp->hi = npp->npaux->nbi1;
4072     }
4073    else hrp->htyp = vpiNetDriver;
4074    hrp->hu.hnpp = npp;
4075    break;
4076   case NP_PULL:
4077    gp = npp->elnpp.egp;
4078    hrp->htyp = vpiPrimTerm;
4079    hrp->hu.hgp = gp;
4080    hrp->hi = npp->obnum;
4081    break;
4082   default: return(FALSE);
4083  }
4084  return(TRUE);
4085 }
4086 
4087 /*
4088  * build the iterator for all port bits connecting to inside module instances
4089  * given a vpi net or reg bit handle, build iterator of port bit handles
4090  */
bit_drvs_iter(struct h_t * hp)4091 static vpiHandle bit_drvs_iter(struct h_t *hp)
4092 {
4093  register int32 hi;
4094  int32 bi, num;
4095  vpiHandle ihref;
4096  struct net_t *np;
4097  struct itree_t *itp;
4098  struct pviter_t *iterp;
4099 
4100  if ((bi = cmp_drvld_bitndx(&np, hp, "vpiDriver/vpiLocalDriver")) == -1)
4101   return(NULL);
4102 
4103  itp = hp->hin_itp;
4104  num = bld_bit_drvs(np, bi, itp, FALSE);
4105  if (num <= 0) return(NULL);
4106 
4107  iterp = __alloc_iter(num, &ihref);
4108  memcpy(iterp->scanhtab, __ithtab, num*sizeof(struct h_t));
4109  memcpy(iterp->ihrectab, __ithrectab, num*sizeof(struct hrec_t));
4110  for (hi = 0; hi < num; hi++)
4111   {
4112    iterp->scanhtab[hi].hrec = &(iterp->ihrectab[hi]);
4113   }
4114  return(ihref);
4115 }
4116 
4117 /*
4118  * build net bit drivers iterator
4119  *
4120  * nothing on itree stack here?
4121  * since per bit never a need to remove duplicates
4122  */
bld_bit_drvs(struct net_t * np,int32 bi,struct itree_t * itp,int32 no_ports)4123 static int32 bld_bit_drvs(struct net_t *np, int32 bi, struct itree_t *itp,
4124  int32 no_ports)
4125 {
4126  register struct net_pin_t *npp;
4127  int32 ri1, ri2, cnt, nd_itpop;
4128  struct h_t tmph, *hp2;
4129  struct hrec_t tmphrec, *hrp2;
4130  struct qcval_t *frc_qcp;
4131 
4132  __push_itstk(itp);
4133  /* iconn drivers are output ports */
4134  for (cnt = 0, npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
4135   {
4136    /* filter out per inst. that is not this instance */
4137    if (npp->npproctyp == NP_PROC_FILT
4138     && npp->npaux->npu.filtitp != __inst_ptr) continue;
4139 
4140    /* can be iconn from other instance for xmr */
4141    nd_itpop = FALSE;
4142    if (npp->npproctyp != NP_PROC_INMOD)
4143     {
4144      /* SJM 04/17/03 - must match each inst in xmr path */
4145      if (!__move_to_npprefloc(npp)) continue;
4146      nd_itpop = TRUE;
4147     }
4148 
4149    /* this must run with right itree loc. */
4150    __get_bidnpp_sect(np, npp, &ri1, &ri2);
4151    /* for scalar bi will be -1 here */
4152    if (ri1 == -1 || bi == -1) goto got_match;
4153    if (bi > ri1 || bi < ri2) goto nxt_npp;
4154 
4155 got_match:
4156    if (no_ports)
4157     {
4158      /* remove port npp's */
4159      switch ((byte) npp->npntyp) {
4160       case NP_ICONN: case NP_BIDICONN: case NP_MDPRT: case NP_BIDMDPRT:
4161       case NP_PB_MDPRT: case NP_PB_ICONN:
4162        goto nxt_npp;
4163       default: break;
4164      }
4165     }
4166    __init_hrec(&tmphrec);
4167    tmphrec.in_iter = TRUE;
4168    tmph.hrec = &tmphrec;
4169 
4170    if (!fill_bit_drv_handle(&tmph, &tmphrec, bi, ri1, ri2, npp)) goto nxt_npp;
4171 
4172    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
4173    hp2 = &(__ithtab[cnt]);
4174    hrp2 = &(__ithrectab[cnt++]);
4175 
4176    memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
4177    hp2->hin_itp = tmph.hin_itp;
4178    /* only need to set cross link in newly added one */
4179    hp2->hrec = hrp2;
4180 
4181 nxt_npp:
4182    if (nd_itpop) __pop_itstk();
4183   }
4184  /* will be no drivers and no tran channel for reg */
4185  if (np->ntyp >= NONWIRE_ST)
4186   {
4187    /* DBG remove --- */
4188    if (np->ndrvs != NULL || np->ntraux != NULL) __vpi_terr(__FILE__, __LINE__);
4189    /* --- */
4190    goto do_force;
4191   }
4192  /* tran channel connections if they exist */
4193  if (np->ntraux == NULL) goto do_force;
4194 
4195  /* iconn drivers are output ports */
4196  for (npp = np->ntraux->tran_npps; npp != NULL; npp = npp->npnxt)
4197   {
4198    /* filter out per inst. that is not this instance */
4199    if (npp->npproctyp == NP_PROC_FILT
4200     && npp->npaux->npu.filtitp != __inst_ptr) continue;
4201 
4202    /* can be iconn from other instance for xmr */
4203    nd_itpop = FALSE;
4204    if (npp->npproctyp != NP_PROC_INMOD)
4205     {
4206      /* SJM 04/17/03 - must match each inst in xmr path */
4207      if (!__move_to_npprefloc(npp)) continue;
4208      nd_itpop = TRUE;
4209     }
4210 
4211    /* this must run with right itree loc. */
4212    __get_bidnpp_sect(np, npp, &ri1, &ri2);
4213    /* for scalar bi will be -1 here */
4214    if (ri1 == -1 || bi == -1) goto got2_match;
4215    if (bi > ri1 || bi < ri2) goto nxt2_npp;
4216 
4217 got2_match:
4218    if (no_ports)
4219     {
4220      /* remove port npp's */
4221      switch ((byte) npp->npntyp) {
4222       case NP_ICONN: case NP_BIDICONN: case NP_MDPRT: case NP_BIDMDPRT:
4223       case NP_PB_ICONN: case NP_PB_MDPRT:
4224        goto nxt2_npp;
4225       default: break;
4226      }
4227     }
4228 
4229    __init_hrec(&tmphrec);
4230    tmphrec.in_iter = TRUE;
4231    tmph.hrec = &tmphrec;
4232 
4233    if (!fill_bit_drv_handle(&tmph, &tmphrec, bi, ri1, ri2, npp)) goto nxt_npp;
4234 
4235    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
4236    hp2 = &(__ithtab[cnt]);
4237    hrp2 = &(__ithrectab[cnt++]);
4238 
4239    memcpy(hrp2, &tmphrec, sizeof(struct hrec_t));
4240    hp2->hin_itp = tmph.hin_itp;
4241    /* only need to set cross link in newly added one */
4242    hp2->hrec = hrp2;
4243 
4244 nxt2_npp:
4245    if (nd_itpop) __pop_itstk();
4246   }
4247 
4248 do_force:
4249  if (!np->frc_assgn_allocated) goto done;
4250  /* this is 1 bit form */
4251  frc_qcp = &(np->nu2.qcval[__inum*np->nwid + ((bi == -1) ? 0 : bi)]);
4252  if (frc_qcp->qc_active)
4253   {
4254    /* FIXME - vpi_ driver not found as driver - vpi_ must keep track */
4255    /* if vpi_ force, do not return as driver */
4256    if (frc_qcp->qcstp == NULL) goto done;
4257 
4258    /* there is an active force - maybe just constant */
4259    if (cnt >= __ithtsiz) __grow_htab(cnt - __ithtsiz + 1);
4260    hp2 = &(__ithtab[cnt]);
4261    hrp2 = &(__ithrectab[cnt++]);
4262    __init_hrec(hrp2);
4263 
4264    hrp2->in_iter = TRUE;
4265    hrp2->htyp = vpiForce;
4266    hrp2->hu.hstp = frc_qcp->qcstp;
4267    hp2->hin_itp = __inst_ptr;
4268    /* only need to set cross link in newly added one */
4269    hp2->hrec = hrp2;
4270   }
4271 done:
4272  __pop_itstk();
4273  return(cnt);
4274 }
4275 
4276 /*
4277  * fill a bit driver handle - if non handle element, return nil
4278  *
4279  * caller must have initialized fields in handle
4280  * this must be called from ref. (stacked itree loc) for xmr
4281  *
4282  * looking for driver of net np bit bi (if scalar not called)
4283  *
4284  * LOOKATME - except for pull, same as fill bit ld handle - right?
4285  */
fill_bit_drv_handle(struct h_t * hp,struct hrec_t * hrp,int32 bi,int32 ri1,int32 ri2,struct net_pin_t * npp)4286 static int32 fill_bit_drv_handle(struct h_t *hp, struct hrec_t *hrp, int32 bi,
4287  int32 ri1, int32 ri2, struct net_pin_t *npp)
4288 {
4289  int32 not_lhs;
4290  struct itree_t *itp2;
4291  struct mod_t *downmdp;
4292  struct mod_pin_t *mpp;
4293  struct gate_t *gp;
4294 
4295  hp->hin_itp = __inst_ptr;
4296  switch ((byte) npp->npntyp) {
4297   case NP_ICONN: case NP_BIDICONN:
4298    /* driver iconn is output port */
4299    itp2 = &(__inst_ptr->in_its[npp->elnpp.eii]);
4300    downmdp = itp2->itip->imsym->el.emdp;
4301    mpp = &(downmdp->mpins[npp->obnum]);
4302    if (!iconnbit_lvalue(mpp, npp, itp2)) not_lhs = TRUE;
4303    else not_lhs = FALSE;
4304    if (mpp->mpwide == 1 || not_lhs) hrp->htyp = vpiPort;
4305    else
4306     {
4307      hrp->htyp = vpiPortBit;
4308      /* notice these are internal h:0 - fixed when index accessed */
4309      /* correct for port bit from non concatenate net bit */
4310      if (ri1 == -1) hrp->hi = bi; else hrp->hi = bi - ri2;
4311     }
4312    hrp->hu.hpi = npp->obnum;
4313    hp->hin_itp = itp2;
4314    break;
4315   case NP_MDPRT: case NP_BIDMDPRT:
4316    /* driver mod port is input port */
4317    mpp = &(__inst_mod->mpins[npp->obnum]);
4318    if (mpp->mpref->optyp == LCB || mpp->mpwide == 1) hrp->htyp = vpiPort;
4319    else
4320     {
4321      hrp->htyp = vpiPortBit;
4322      /* notice these are internal h:0 - fixed when index accessed */
4323      /* correct for port bit from non concatenate net bit */
4324      if (ri1 == -1) hrp->hi = bi; else hrp->hi = bi - ri2;
4325     }
4326    hrp->hu.hpi = npp->obnum;
4327    break;
4328   case NP_PB_MDPRT:
4329    /* driver is bit of separated into per bits mod input port */
4330    hrp->htyp = vpiPortBit;
4331    hrp->hu.hpi = npp->obnum;
4332    if (ri1 == -1) hrp->hi = bi; else hrp->hi = bi - ri2;
4333    break;
4334   case NP_CONTA:
4335    hrp->htyp = vpiContAssign;
4336    hrp->hu.hcap = npp->elnpp.ecap;
4337    break;
4338   case NP_GATE: case NP_TRANIF: case NP_TRAN:
4339    gp = npp->elnpp.egp;
4340    /* must correct for 1 bit conta */
4341    if (gp->gmsym->el.eprimp->gateid == G_ASSIGN)
4342     {
4343      hrp->htyp = vpiContAssign;
4344      hrp->htyp2 = vpiGate;
4345      hrp->hu.hgp = npp->elnpp.egp;
4346      break;
4347     }
4348    hrp->htyp = vpiPrimTerm;
4349    hrp->hu.hgp = gp;
4350    hrp->hi = npp->obnum;
4351    break;
4352   case NP_VPIPUTV:
4353    /* include entire wire (know overlaps) or matching bit's driver here */
4354    if (npp->npaux != NULL && npp->npaux->nbi1 != -1)
4355     {
4356      if (npp->npaux->nbi1 != bi) break;
4357      hrp->htyp = vpiNetBitDriver;
4358      hrp->hi = npp->npaux->nbi1;
4359     }
4360    else hrp->htyp = vpiNetDriver;
4361    hrp->hu.hnpp = npp;
4362    break;
4363   case NP_PULL:
4364    gp = npp->elnpp.egp;
4365    hrp->htyp = vpiPrimTerm;
4366    hrp->hu.hgp = gp;
4367    hrp->hi = npp->obnum;
4368    break;
4369   default: return(FALSE);
4370  }
4371  return(TRUE);
4372 }
4373 
4374 /*
4375  * build iterator for drivers of a reg (or variable)
4376  *
4377  * only possible drivers are quasi continuous force or assign
4378  * notice only one can be active (i.e. either no iter or size 1)
4379  *
4380  * d.s for reg qcval is 2 qcval's per inst. - one for entire reg force and
4381  * one for qc assign
4382  */
reg_drvs_iter(struct h_t * hp)4383 static vpiHandle reg_drvs_iter(struct h_t *hp)
4384 {
4385  register struct hrec_t *hrp2;
4386  vpiHandle ihref;
4387  struct net_t *np;
4388  struct itree_t *itp;
4389  struct pviter_t *iterp;
4390  struct h_t *hp2;
4391  struct qcval_t *assgn_qcp, *frc_qcp;
4392  struct hrec_t *hrp;
4393 
4394  hrp = hp->hrec;
4395  np = hrp->hu.hnp;
4396  itp = hp->hin_itp;
4397 
4398  /* not in src or added by PLI, can't be active */
4399  if (!np->frc_assgn_allocated) return(NULL);
4400 
4401  frc_qcp = &(np->nu2.qcval[2*itp->itinum]);
4402  if (frc_qcp->qc_active)
4403   {
4404    /* FIXME - vpi_ driver not found as driver - vpi_ must keep track */
4405    /* if vpi_ force know will not be reg qc assign */
4406    if (frc_qcp->qcstp == NULL) return(NULL);
4407 
4408    /* there is an active force - maybe just constant */
4409    iterp = __alloc_iter(1, &ihref);
4410    hp2 = &(iterp->scanhtab[0]);
4411    hrp2 = hp2->hrec;
4412 
4413    hrp2->htyp = vpiForce;
4414    hrp2->hu.hstp = frc_qcp->qcstp;
4415    hp2->hin_itp = itp;
4416    return(ihref);
4417   }
4418 
4419  assgn_qcp = &(np->nu2.qcval[2*itp->itinum + 1]);
4420  if (!assgn_qcp->qc_active) return(NULL);
4421  iterp = __alloc_iter(1, &ihref);
4422  hp2 = &(iterp->scanhtab[0]);
4423  hrp2 = hp2->hrec;
4424 
4425  hrp2->htyp = vpiAssignStmt;
4426  hrp2->hu.hstp = assgn_qcp->qcstp;
4427  hp2->hin_itp = itp;
4428  return(ihref);
4429 }
4430 
4431 /*
4432  * ROUTINES TO BUILD XL STYLE DRIVER ITERATOR (SCALAR OR BIT ONLY)
4433  */
4434 
4435 /*
4436  * build an iterator of wire or reg bit XL style collapsed drivers
4437  *
4438  * inout ports and trans are both loads and drivers
4439  *
4440  * no ports here - cross and include actual loads from other side
4441  * algorithm sort of (mostly?) duplicates XL collapsing
4442  * only makes sense for 1 bit objects
4443  */
__bld_drvs_iterator(struct h_t * hp,int32 otype)4444 extern vpiHandle __bld_drvs_iterator(struct h_t *hp, int32 otype)
4445 {
4446  if (hp == NULL) return(__nil_iter_err(otype));
4447 
4448  /* routine for each thing that load can be of */
4449  switch (hp->hrec->htyp) {
4450   case vpiNet: case vpiReg:
4451    if (hp->hrec->hu.hnp->nwid != 1) goto bad_obj;
4452    return(bit_xl_ldsdrvs_iter(hp, FALSE));
4453   case vpiNetBit:
4454    return(bit_xl_ldsdrvs_iter(hp, FALSE));
4455 
4456   /* quasi-procedural force and assign are only drivers of regs */
4457   /* also really never per bit and no cross module iconn/port */
4458   case vpiRegBit: case vpiVarSelect:
4459    return(reg_drvs_iter(hp));
4460 
4461   default:
4462 bad_obj:
4463    __vpi_err(1874, vpiError,
4464     "vpiLoad 1-to-many iterator from %s illegal - for one bit net or reg loads only",
4465     __to_vpionam(__wrks1, hp->hrec->htyp));
4466   }
4467  return(NULL);
4468 }
4469 
4470 /*
4471  * ITERATOR SCAN ROUTINES
4472  */
4473 
4474 /*
4475  * given a handle returned by vpi iterator, get next object
4476  * and move to one past
4477  *
4478  * easy since table of right object type handles already built
4479  * LOOKATME - for empty iterator is this supposed to return nil (think yes)
4480  */
vpi_scan(vpiHandle iterator)4481 extern vpiHandle vpi_scan(vpiHandle iterator)
4482 {
4483  register struct pviter_t *iterp;
4484  register struct h_t *ihp, *hp;
4485 
4486  /* assume no error */
4487  __last_eip = NULL;
4488  if (__run_state == SS_COMP) { __still_comp_err("vpi_scan"); return(NULL); }
4489  ihp = (struct h_t *) iterator;
4490  if (ihp == NULL) return(NULL);
4491  if (!__validate_handle("vpi_scan (iterator)", ihp)) return(NULL);
4492  if (ihp->hrec->htyp != vpiIterator)
4493   {
4494    __vpi_err(1864, vpiError,
4495     "vpi_scan passed handle of type %s - must be vpiIterator",
4496     __to_vpionam(__wrks1, ihp->hrec->htyp));
4497    return(NULL);
4498   }
4499  /* for last, return and move past end - then next call return nil and free */
4500  iterp = ihp->hrec->hu.hiterp;
4501  if (iterp->nxthi == -1)
4502   {
4503    __vpi_err(1862, vpiError,
4504     "vpi_scan iterator handle invalid because scan already finished or error");
4505    return(NULL);
4506   }
4507  if (iterp->nxthi >= iterp->numhs)
4508   {
4509    iterp->nxthi = -1;
4510    __free_iterator(iterator);
4511    return(NULL);
4512   }
4513  hp = &(iterp->scanhtab[iterp->nxthi]);
4514  /* here can not free since corrupt handle */
4515  if (!__validate_handle("vpi_scan (component)", hp))
4516   {
4517    iterp->nxthi = -1;
4518    return(NULL);
4519   }
4520  (iterp->nxthi)++;
4521  return((vpiHandle) hp);
4522 }
4523 
4524 /*
4525  * ROUTINES FOR OBTAINING HANDLES
4526  */
4527 
4528 /*
4529  * get handle by name - use symbol table of scope (task or itree loc)
4530  *
4531  * LRM does not allow vpiFullName for ports
4532  */
vpi_handle_by_name(char * name,vpiHandle scope)4533 extern vpiHandle vpi_handle_by_name(char *name, vpiHandle scope)
4534 {
4535  int32 sav_ecnt;
4536  vpiHandle href;
4537  struct h_t *hp;
4538  struct symtab_t *sytp;
4539  struct itree_t *itp;
4540  struct hrec_t *hrp;
4541 
4542  sav_ecnt = __pv_err_cnt;
4543  __last_eip = NULL;
4544  if (__run_state == SS_COMP)
4545   { __still_comp_err("vpi_handle_by_name"); return(NULL); }
4546  if (scope == NULL)
4547   {
4548    href = cnvt_name_to_handle(name, (struct symtab_t *) NULL,
4549     (struct itree_t *) NULL);
4550    goto done;
4551   }
4552 
4553  hp = (struct h_t *) scope;
4554  if (!__validate_handle("vpi_handle_by_name", hp)) return(NULL);
4555  hrp = hp->hrec;
4556  itp = hp->hin_itp;
4557  switch (hrp->htyp) {
4558   case vpiModule:
4559    sytp = itp->itip->imsym->el.emdp->msymtab;
4560    break;
4561   case vpiTask: case vpiFunction:
4562    sytp = hrp->hu.htskp->tsksymtab;
4563    break;
4564   case vpiNamedBegin: case vpiNamedFork:
4565    sytp = hrp->hu.htskp->tsksymtab;
4566    break;
4567   default:
4568    __vpi_err(1868, vpiError,
4569     "vpi_handle_by_name scope object must be scope handle - %s illegal",
4570    __to_vpionam(__wrks1, hrp->htyp));
4571   return(NULL);
4572  }
4573  href = cnvt_name_to_handle(name, sytp, itp);
4574 
4575 done:
4576  if (sav_ecnt < __pv_err_cnt)
4577   {
4578    __vpi_err(1878, vpiError,
4579     "vpi_handle_by_name failed - name %s illegal", name);
4580   }
4581  return(href);
4582 }
4583 
4584 /*
4585  * convert a name to a handle
4586  *
4587  * sytp is scope to start in - if nil, then reference is rooted
4588  * if sytp nil so must be scopitp
4589  *
4590  * on error, this returns nil
4591  * FIXME - figure out whether last gnc was set to last or to last non net
4592  *         if so this routine is wrong because it uses last
4593  * LOOKATME - this routine fails on arr of insts (comp. with numeric ind)
4594  *            but so far that is correct unless LRM changes - if g/i array
4595  *            passed, not seen here
4596  */
cnvt_name_to_handle(char * nam,struct symtab_t * sytp,struct itree_t * scopitp)4597 static vpiHandle cnvt_name_to_handle(char *nam, struct symtab_t *sytp,
4598  struct itree_t *scopitp)
4599 {
4600  int32 ii, has_dot;
4601  struct itree_t *itp;
4602  struct expr_t *glbndp, *gcmp_ndp;
4603  struct sy_t *syp, *hsyp;
4604  struct mod_t *mdp;
4605  struct inst_t *ip;
4606  char *chp;
4607  byte *bp1, *bp2;
4608 
4609  /* case 1 - xmr name */
4610  has_dot = __name_vpi_hasdot(nam);
4611  if (has_dot)
4612   {
4613    itp = NULL;
4614    if ((glbndp = __glbnam_to_expr(nam)) == NULL) return(NULL);
4615    gcmp_ndp = glbndp->ru.x;
4616    if (sytp == NULL)
4617     {
4618      chp = __to_glbcmp_nam(gcmp_ndp);
4619      if ((ii = __ip_indsrch(chp)) == -1)
4620       {
4621 ret_nil:
4622        if (glbndp != NULL) __free_xtree(glbndp);
4623        return(NULL);
4624       }
4625      itp = __it_roots[ii];
4626      sytp = itp->itip->imsym->el.emdp->msymtab;
4627      gcmp_ndp = gcmp_ndp->ru.x;
4628     }
4629    else itp = scopitp;
4630 
4631    for (; gcmp_ndp != NULL;)
4632     {
4633      chp = __to_glbcmp_nam(gcmp_ndp);
4634      /* look up first in context then in specify section */
4635      if ((syp = __get_nongia_sym(chp, sytp)) == NULL)
4636       {
4637        if (gcmp_ndp->ru.x != NULL) goto ret_nil;
4638        /* this is last component */
4639        hsyp = sytp->sypofsyt;
4640        if (hsyp->sytyp != SYM_M) goto ret_nil;
4641 
4642        mdp = itp->itip->imsym->el.emdp;
4643        /* first try specify section if it exists */
4644        if (mdp->mspfy != NULL)
4645         {
4646          if ((syp = __get_sym(chp, mdp->mspfy->spfsyms)) != NULL)
4647           {
4648            if (glbndp != NULL) __free_xtree(glbndp);
4649            return(bld_symhandle(nam, syp, sytp, itp));
4650           }
4651         }
4652        goto ret_nil;
4653       }
4654      /* non scope symbol found in scope */
4655      if (!__is_scope_sym(syp))
4656       {
4657        /* if non scope symbol but not end of path - mismatch */
4658        if (gcmp_ndp->ru.x != NULL) goto ret_nil;
4659        if (glbndp != NULL) __free_xtree(glbndp);
4660        /* end of path build whatever it is */
4661        return(bld_symhandle(nam, syp, sytp, itp));
4662       }
4663      /* if last symbol, build the scope handle - this is inst. type ref */
4664      if (gcmp_ndp->ru.x == NULL)
4665       {
4666        if (glbndp != NULL) __free_xtree(glbndp);
4667        return(bld_symhandle(nam, syp, sytp, itp));
4668       }
4669      /* scope symbol - maybe descend */
4670      if (syp->sytyp == SYM_I)
4671       {
4672        /* syp in itp */
4673        ip = syp->el.eip;
4674        mdp = itp->itip->imsym->el.emdp;
4675        bp1 = (byte *) ip;
4676        bp2 = (byte *) mdp->minsts;
4677        ii = (bp1 - bp2)/sizeof(struct inst_t);
4678        itp = &(itp->in_its[ii]);
4679        sytp = itp->itip->imsym->el.emdp->msymtab;
4680       }
4681      else sytp = syp->el.etskp->tsksymtab;
4682      if ((gcmp_ndp = gcmp_ndp->ru.x) == NULL) break;
4683     }
4684    __vpi_terr(__FILE__, __LINE__);
4685    if (glbndp != NULL) __free_xtree(glbndp);
4686    return(NULL);
4687   }
4688 
4689  /* case 2: simple name */
4690  itp = scopitp;
4691  /* top level module name */
4692  if (sytp == NULL)
4693   {
4694    /* LOOKATME - could add getting user defined systf here by name */
4695    /* but LRM says only things with vpiFullName properties can be accessed */
4696    if ((ii = __ip_indsrch(nam)) == -1)
4697     {
4698      return(NULL);
4699     }
4700    itp = __it_roots[ii];
4701    return(__mk_handle(vpiModule, (void *) itp->itip->imsym->el.emdp, itp,
4702     (struct task_t *) NULL));
4703   }
4704  hsyp = sytp->sypofsyt;
4705  /* case 1b simple name in some scope */
4706  if ((syp = __get_nongia_sym(nam, sytp)) == NULL)
4707   {
4708    if (hsyp->sytyp != SYM_M) return(NULL);
4709 
4710    mdp = hsyp->el.emdp;
4711    /* try specify section if it exists */
4712    if (mdp->mspfy != NULL)
4713     {
4714      if ((syp = __get_sym(nam, mdp->mspfy->spfsyms)) != NULL)
4715       return(bld_symhandle(nam, syp, sytp, itp));
4716     }
4717    return(NULL);
4718   }
4719  /* simple name found in scope */
4720  return(bld_symhandle(nam, syp, sytp, itp));
4721 }
4722 
4723 /*
4724  * build a handle from a symbol
4725  *
4726  * nam here just for error messages
4727  */
bld_symhandle(char * nam,struct sy_t * syp,struct symtab_t * sytp,struct itree_t * itp)4728 static vpiHandle bld_symhandle(char *nam, struct sy_t *syp,
4729  struct symtab_t *sytp, struct itree_t *itp)
4730 {
4731  int32 ii, ttyp;
4732  word32 otyp;
4733  vpiHandle href;
4734  struct sy_t *in_tsyp;
4735  struct task_t *intskp, *tskp;
4736  struct mod_t *mdp;
4737  struct inst_t *ip;
4738  struct itree_t *down_itp;
4739  struct gate_t *gp;
4740  struct net_t *np;
4741  struct h_t *hp;
4742  byte *bp1, *bp2;
4743 
4744  in_tsyp = sytp->sypofsyt;
4745  if (in_tsyp->sytyp == SYM_M) intskp = NULL; else intskp = in_tsyp->el.etskp;
4746 
4747  switch ((byte) syp->sytyp) {
4748    case SYM_I:
4749     if (intskp != NULL) __vpi_terr(__FILE__, __LINE__);
4750     mdp = itp->itip->imsym->el.emdp;
4751     ip = syp->el.eip;
4752     bp1 = (byte *) ip;
4753     bp2 = (byte *) mdp->minsts;
4754     ii = (bp1 - bp2)/sizeof(struct inst_t);
4755     down_itp = &(itp->in_its[ii]);
4756     href = __mk_handle(vpiModule, (void *) down_itp->itip->imsym->el.emdp,
4757      down_itp, (struct task_t *) NULL);
4758     break;
4759    case SYM_TSK: case SYM_F: case SYM_LB:
4760     tskp = syp->el.etskp;
4761     ttyp = __to_vpi_tasktyp(tskp->tsktyp);
4762     href = __mk_handle(ttyp, (void *) tskp, itp, intskp);
4763     break;
4764    case SYM_PRIM:
4765     if (intskp != NULL) __vpi_terr(__FILE__, __LINE__);
4766     gp = syp->el.egp;
4767     if (gp->gmsym->el.eprimp->gateid == G_ASSIGN)
4768      {
4769       href = __mk_handle(vpiContAssign, (void *) gp, itp, NULL);
4770       hp = (struct h_t *) href;
4771       hp->hrec->htyp2 = vpiGate;
4772       break;
4773      }
4774     href = __mk_handle(__gate_to_vpiprimtyp(gp), (void *) gp, itp, NULL);
4775     break;
4776    case SYM_N:
4777     np = syp->el.enp;
4778     if (np->n_isaparam)
4779      {
4780       /* case 1: specparam */
4781       if (np->nu.ct->p_specparam)
4782        {
4783         href = __mk_handle(vpiSpecParam, (void *) np, itp, NULL);
4784        }
4785       else
4786        {
4787         /* case 2: parameter */
4788         /* if local imported param - always returns global "real" copy */
4789         /* now just fall thru to make param handle */
4790         href = __mk_handle(vpiParameter, (void *) np, itp, NULL);
4791        }
4792       break;
4793      }
4794     /* case 3: variable (wire/net) and never select */
4795     /* 01/25/00 SJM - for imported global net this is just normal net */
4796     otyp = __ntyp_to_vpivarhtyp(np);
4797     href = __mk_handle(otyp, (void *) np, itp, intskp);
4798     break;
4799    /* these are Cver extensions for added delay setting system tasks */
4800    case SYM_CA:
4801     href = __mk_handle(vpiContAssign, (void *) syp->el.ecap, itp, NULL);
4802     break;
4803    case SYM_TCHK:
4804     href = __mk_handle(vpiTchk, (void *) syp->el.etcp, itp, NULL);
4805     break;
4806    case SYM_PTH:
4807     href = __mk_handle(vpiTchk, (void *) syp->el.epthp, itp, NULL);
4808     break;
4809    case SYM_UDP:
4810     __vpi_err(1856, vpiError,
4811      "vpi_handle_by_name of udp definition %s object not supported",
4812      nam);
4813     return(NULL);
4814    /* never should see SYM_M - if top level this not called */
4815    /* preprocess (SYM_DEF) and system task (SYM_SF) never seen here */
4816    default: __vpi_terr(__FILE__, __LINE__); return(NULL);
4817   }
4818  return(href);
4819 }
4820 
4821 /*
4822  * return T if has dot (xmr type path)
4823  *
4824  * tricky because last name in xmr path can be escaped
4825  */
__name_vpi_hasdot(char * nam)4826 extern int32 __name_vpi_hasdot(char *nam)
4827 {
4828  register char *chp;
4829 
4830  for (chp = nam; *chp != '\0'; chp++)
4831   {
4832    if (*chp == '.') return(TRUE);
4833    if (*chp == '\\')
4834     {
4835      for (chp++;; chp++)
4836       {
4837        if (*chp == ' ') goto nxt_comp;
4838        if (*chp == '\0') break;
4839       }
4840      return(FALSE);
4841     }
4842 nxt_comp:;
4843   }
4844  return(FALSE);
4845 }
4846 
4847 /*
4848  * get a bit handle from its index
4849  *
4850  * error and return NULL for non indexable handle
4851  * this is passed user [i1:i2] range index instead of normalized internal
4852  */
vpi_handle_by_index(vpiHandle object,int32 indx)4853 extern vpiHandle vpi_handle_by_index(vpiHandle object, int32 indx)
4854 {
4855  int32 biti, ri1, ri2, wid;
4856  word32 ityp;
4857  word32 av, bv;
4858  vpiHandle href;
4859  struct h_t *hp, *hp2;
4860  struct net_t *np;
4861  struct mod_t *mdp;
4862  struct mod_pin_t *mpp;
4863  struct xstk_t *xsp;
4864  struct hrec_t *hrp, *hrp2;
4865 
4866  __last_eip = NULL;
4867  if (__run_state == SS_COMP)
4868   { __still_comp_err("vpi_handle_by_index"); return(NULL); }
4869  hp = (struct h_t *) object;
4870  if (!__validate_handle("vpi_handle_by_index", hp)) return(NULL);
4871  hrp = hp->hrec;
4872 
4873  ri1 = ri2 = 0;
4874  switch (hrp->htyp) {
4875   case vpiMemory:
4876    /* convert index to internal range */
4877    np = hrp->hu.hnp;
4878    if (!np->n_isarr) __vpi_terr(__FILE__, __LINE__);
4879    __getarr_range(np, &ri1, &ri2, &wid);
4880    biti = normalize_ndx_(indx, ri1, ri2);
4881    if (biti < 0 || biti >= wid)
4882     {
4883 bad_ndx:
4884      __vpi_err(1828, vpiError,
4885       "vpi_handle_by_index index %d of %s out of range [%d:%d]", indx,
4886       __to_vpionam(__wrks1, hrp->htyp), ri1, ri2);
4887      return(NULL);
4888     }
4889    ityp = vpiMemoryWord;
4890    href = __mk_handle(ityp, (void *) np, hp->hin_itp, NULL);
4891    hp2 = (struct h_t *) href;
4892    hrp2 = hp2->hrec;
4893    hrp2->hi = biti;
4894    hrp2->bith_ndx = TRUE;
4895    break;
4896   case vpiMemoryWord:
4897    /* LOOKATME - should this be vpiRegBit object? */
4898    /* this evaluates expr. to array and bit or for bith form just get ndx */
4899    biti = __get_vpinet_index(&np, hp);
4900 
4901    /* DBG remove --- */
4902    if (!np->n_isarr) __vpi_terr(__FILE__, __LINE__);
4903    /* --- */
4904    if (!np->n_isavec) goto no_ndx;
4905    /* load the array */
4906    __getarr_range(np, &ri1, &ri2, &wid);
4907    push_xstk_(xsp, np->nwid);
4908    __ld_arr_val(xsp->ap, xsp->bp, np->nva, wid, np->nwid, biti);
4909    /* determine (normalize) bit */
4910    __getwir_range(np, &ri1, &ri2);
4911    biti = normalize_ndx_(indx, ri1, ri2);
4912    if (biti < 0 || biti >= np->nwid) { __pop_xstk(); goto bad_ndx; }
4913    av = rhsbsel_(xsp->ap, biti);
4914    bv = rhsbsel_(xsp->bp, biti);
4915    __pop_xstk();
4916    href = __mk_handle(vpiConstant, (void *) NULL, hp->hin_itp,
4917     hp->hrec->hin_tskp);
4918    hp2 = (struct h_t *) href;
4919    hrp2 = hp2->hrec;
4920    hrp2->hu.hxp = __bld_rng_numxpr(av, bv, 1);
4921    hrp2->free_xpr = TRUE;
4922    break;
4923   case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
4924    np = hrp->hu.hnp;
4925    if (!np->n_isavec)
4926     {
4927 no_ndx:
4928      __vpi_err(2027, vpiWarning,
4929       "vpi_handle_by_index of non indexable object %s - index of scalar illegal",
4930       __to_vpionam(__wrks1, hrp->htyp));
4931      return(NULL);
4932     }
4933    __getwir_range(np, &ri1, &ri2);
4934    biti = normalize_ndx_(indx, ri1, ri2);
4935    if (biti < 0 || biti >= np->nwid) goto bad_ndx;
4936    ityp = __to_vpinetbithtyp(np->ntyp);
4937    href = __mk_handle(ityp, (void *) np, hp->hin_itp, NULL);
4938    hp2 = (struct h_t *) href;
4939    hrp2 = hp2->hrec;
4940    hrp2->hi = biti;
4941    hrp2->bith_ndx = TRUE;
4942    break;
4943   case vpiPort:
4944    /* port ranges always wid-1:0 since not declared (can be 0) */
4945    mdp = hp->hin_itp->itip->imsym->el.emdp;
4946    mpp = &(mdp->mpins[hrp->hu.hpi]);
4947    if (mpp->mpwide == 1) goto no_ndx;
4948    ri1 = mpp->mpwide - 1;
4949    ri2 = 0;
4950    if (indx < 0 || indx > ri1) goto bad_ndx;
4951    href = __mk_handle(vpiPortBit, (void *) hrp->hu.hpi, hp->hin_itp, NULL);
4952    hp2 = (struct h_t *) href;
4953    hrp2 = hp2->hrec;
4954    hrp2->hi = indx;
4955    break;
4956   default:
4957    __vpi_err(1846, vpiError,
4958     "vpi_handle_index failed because %s has no contained indexable object",
4959     __to_vpionam(__wrks1, hrp->htyp));
4960    return(NULL);
4961  }
4962  return(href);
4963 }
4964 
4965 /*
4966  * new handle by index that requires new 2001 multi-dimensional vectors
4967  * and is only way to access them by indexing
4968  *
4969  * WRITME - add multi-dimensional vector support
4970  */
vpi_handle_by_multi_index(vpiHandle obj,PLI_INT32 num_index,PLI_INT32 * index_array)4971 extern vpiHandle vpi_handle_by_multi_index(vpiHandle obj, PLI_INT32 num_index,
4972  PLI_INT32 *index_array)
4973 {
4974  __vpi_err(1801, vpiError,
4975   "new P1364 2001 vpi_handle_by_multi_index unsupported because multi-dimensional arrays not supported");
4976  return(NULL);
4977 }
4978 
4979 /*
4980  * ROUTINES TO GET PROPERTIES
4981  */
4982 
4983 /*
4984  * get property type property for object object if it exists
4985  */
vpi_get(PLI_INT32 property,vpiHandle object)4986 extern int32 vpi_get(PLI_INT32 property, vpiHandle object)
4987 {
4988  PLI_INT32 pval;
4989  int32 casetyp;
4990  struct h_t *hp;
4991  struct hrec_t *hrp;
4992 
4993  __last_eip = NULL;
4994  if (__run_state == SS_COMP)
4995   {
4996    __still_comp_err("vpi_get");
4997    return(vpiUndefined);
4998   }
4999  if (!validate_property("vpi_get", property)) return(0);
5000  /* special case return smallest time precision (not units) in design */
5001  if (object == NULL)
5002   {
5003    /* design wide these are same - could be timeformat unit */
5004    /* LOOKATME - acc_ equivalent returns timeformat precision here */
5005    if (property == vpiTimePrecision)
5006     { pval = -((int32) __des_timeprec); return(pval); }
5007    else if (property == vpiTimeUnit)
5008     { pval = -((int32) __des_timeprec); return(pval); }
5009    __vpi_err(1865, vpiError,
5010     "property %s illegal for vpi_get with NULL object - only for timescale",
5011     __to_vpipnam(__wrks1, property));
5012    return(vpiUndefined);
5013   }
5014  hp = (struct h_t *) object;
5015  if (!__validate_handle("vpi_get", hp)) return(vpiUndefined);
5016  hrp = hp->hrec;
5017 
5018  /* vpiType special meta property for handle object */
5019  if (property == vpiType) return(hrp->htyp);
5020 
5021  switch (hrp->htyp) {
5022   /* notice - not in LRM but iterators have size property */
5023   case vpiIterator:
5024    if (property != vpiSize)
5025     { notpropof_err(hrp->htyp, property); return(vpiUndefined); }
5026    return(hrp->hu.hiterp->numhs);
5027   case vpiModule:
5028    pval = modprop_vpiget(hp, property);
5029    break;
5030   case vpiNet: case vpiNetBit:
5031    pval = netprop_vpiget(hp, property);
5032    break;
5033   case vpiReg: case vpiRegBit: case vpiIntegerVar: case vpiTimeVar:
5034   case vpiRealVar: case vpiVarSelect: case vpiNamedEvent:
5035    pval = regprop_vpiget(hp, property);
5036    break;
5037   case vpiMemory:
5038    pval = arrprop_vpiget(hp, property);
5039    break;
5040   case vpiMemoryWord:
5041    pval = arrwrdprop_vpiget(hp, property);
5042    break;
5043   case vpiParameter: case vpiSpecParam:
5044    pval = paramprop_vpiget(hp, property);
5045    break;
5046   case vpiPort: case vpiPortBit:
5047    pval = portprop_vpiget(hp, property);
5048    break;
5049   case vpiGate: case vpiUdp: case vpiSwitch:
5050    pval = gateprop_vpiget(hp, property);
5051    break;
5052   case vpiPrimTerm:
5053    pval = __primtermprop_vpiget(hp, property);
5054    break;
5055   case vpiContAssign:
5056    pval = contaprop_vpiget(hp, property);
5057    break;
5058   case vpiFuncCall: case vpiSysFuncCall:
5059    pval = fcallprop_vpiget(hp, property);
5060    break;
5061   case vpiTaskCall: case vpiSysTaskCall:
5062    pval = tcallprop_vpiget(hp, property);
5063    break;
5064   /* this is function definition not call */
5065   case vpiFunction:
5066    pval = funcdefprop_vpiget(hp, property);
5067    break;
5068   case vpiTchk:
5069    pval = tchkprop_vpiget(hp, property);
5070    break;
5071   case vpiTchkTerm:
5072    pval = tchktermprop_vpiget(hp, property);
5073    break;
5074   case vpiModPath:
5075    pval = pthprop_vpiget(hp, property);
5076    break;
5077   case vpiPathTerm:
5078    pval = pthtermprop_vpiget(hp, property);
5079    break;
5080   case vpiSchedBitEvent:
5081    if (property != vpiScheduled)
5082     { notpropof_err(hrp->htyp, property); return(vpiUndefined); }
5083    /* for vector wire driver form only T if all bits done */
5084    if (hrp->evnt_done) return(FALSE);
5085    return(TRUE);
5086   case vpiSchedEvent:
5087    if (property != vpiScheduled)
5088     { notpropof_err(hrp->htyp, property); return(vpiUndefined); }
5089    /* for non table form bit determines if done or canceled */
5090    if (hrp->evnt_done) return(FALSE);
5091    /* table vectored driver form - must re-check for */
5092    if (hrp->bith_ndx)
5093     {
5094      register int32 bi;
5095      struct net_t *np;
5096      i_tev_ndx *evtabi, tevpi;
5097 
5098      np = hrp->hu.hevrec->evnp;
5099      evtabi = hrp->hu.hevrec->evndxtab;
5100      /* ?? LOOKATME - this was low to high */
5101      for (bi = np->nwid - 1; bi >= 0; bi--)
5102       {
5103        tevpi = evtabi[bi];
5104        if (tevpi != -1 && !(__tevtab[tevpi].te_cancel)) return(FALSE);
5105       }
5106     }
5107    return(TRUE);
5108 
5109   /* all statements and processes - not processes (init/always) */
5110   case vpiAssignStmt: case vpiBegin: case vpiDeassign:
5111   case vpiDelayControl: case vpiEventControl: case vpiDisable:
5112   case vpiEventStmt: case vpiFor: case vpiForce: case vpiForever:
5113   case vpiFork: case vpiIf: case vpiIfElse: case vpiNullStmt:
5114   case vpiRelease: case vpiRepeat: case vpiWait: case vpiWhile:
5115 try_line_prop:
5116    if (property != vpiLineNo)
5117     { notpropof_err(hrp->htyp, property); return(vpiUndefined); }
5118    pval = hrp->hu.hstp->stlin_cnt;
5119    break;
5120   /* named blocks are tasks although "in line" */
5121   case vpiNamedBegin: case vpiNamedFork:
5122    if (property != vpiLineNo)
5123     { notpropof_err(hrp->htyp, property); return(vpiUndefined); }
5124    pval = hrp->hu.htskp->tsksyp->sylin_cnt;
5125    break;
5126   case vpiDefParam:
5127    if (property != vpiLineNo)
5128     { notpropof_err(vpiDefParam, property); return(vpiUndefined); }
5129    pval = (int32) hrp->hu.hdfp->dfplin_cnt;
5130    break;
5131   case vpiParamAssign:
5132    if (property != vpiLineNo)
5133     { notpropof_err(vpiParamAssign, property); return(vpiUndefined); }
5134    pval = (int32) hrp->hu.hnp->nsym->sylin_cnt;
5135    break;
5136   case vpiAssignment:
5137    if (property == vpiBlocking)
5138     {
5139      if (hrp->hu.hstp->rl_stmttyp == S_NBPROCA) pval = TRUE;
5140      else pval = FALSE;
5141      break;
5142     }
5143    goto try_line_prop;
5144   case vpiCase:
5145    if (property == vpiCaseType)
5146     {
5147      casetyp = hrp->hu.hstp->st.scs.castyp;
5148      if (casetyp == CASEZ) pval = vpiCaseZ;
5149      else if (casetyp == CASEX) pval = vpiCaseX;
5150      else pval = vpiCaseExact;
5151      break;
5152     }
5153    goto try_line_prop;
5154   /* all elements of expr. class that are not variables or selects of vars */
5155   case vpiConstant: case vpiPartSelect: case vpiOperation:
5156    pval = exprclass_prop_vpiget(hp, property);
5157    break;
5158   case vpiIODecl:
5159    pval = iodecl_prop_vpiget(hp, property);
5160    break;
5161   case vpiUdpDefn:
5162    pval = udpdefnprop_vpiget(hp, property);
5163    break;
5164   case vpiTableEntry:
5165    pval = udptabentryprop_vpiget(hp, property);
5166    break;
5167   case vpiAttribute:
5168    pval = dig_attrprop_vpiget(hp, property);
5169    break;
5170   case vpiCallback:
5171    /* property for enable (active or on) call back is vpiActive, i.e. on */
5172    if (property != vpiActive)
5173     { notpropof_err(hrp->htyp, property); return(vpiUndefined); }
5174    if (hrp->hu.hcbp->cb_user_off) return(FALSE);
5175    return(TRUE);
5176 
5177   default:
5178    notpropof_err(hrp->htyp, property);
5179    return(vpiUndefined);
5180   }
5181  return(pval);
5182 }
5183 
5184 /*
5185  * validate property
5186  * returns F on error
5187  */
validate_property(char * rnam,int32 proptyp)5188 static int32 validate_property(char *rnam, int32 proptyp)
5189 {
5190  if (__to_vpipnam(__wrks1, proptyp) == NULL || proptyp == vpiUndefined)
5191   {
5192    __vpi_err(1819, vpiError,
5193     "%s: property %d illegal or out of range", rnam, proptyp);
5194    return(FALSE);
5195   }
5196  return(TRUE);
5197 }
5198 
5199 /*
5200  * get int32 property values for module (inst. itree loc.)
5201  */
modprop_vpiget(struct h_t * hp,int32 prop)5202 static int32 modprop_vpiget(struct h_t *hp, int32 prop)
5203 {
5204  int32 pval;
5205  struct mod_t *mdp;
5206 
5207  mdp = hp->hrec->hu.hmdp;
5208  switch (prop) {
5209   case vpiCellInstance:
5210    if (mdp->m_iscell) return(TRUE);
5211    return(FALSE);
5212   /* delay modes not supported by Cver */
5213   case vpiDefDelayMode: return(vpiDelayModeNone);
5214   case vpiLineNo: return(hp->hin_itp->itip->isym->sylin_cnt);
5215   case vpiDefLineNo: return(mdp->msym->sylin_cnt);
5216   case vpiProtected: return(FALSE);
5217   case vpiTimeUnit:
5218    if (!mdp->mno_unitcnv) pval = -((int32) mdp->mtime_units);
5219    /* if no time scale both precision and units the same */
5220    else pval = -((int32) __des_timeprec);
5221    return(pval);
5222   case vpiTimePrecision:
5223    if (!mdp->mno_unitcnv)
5224     pval = -((int32) (mdp->mtime_units + mdp->mtime_prec));
5225    else pval = -((int32) __des_timeprec);
5226    return(pval);
5227   case vpiDefNetType: return(__to_vpi_netproptyp(mdp->mod_dfltntyp));
5228   case vpiUnconnDrive:
5229    if (mdp->mod_uncdrv == TOK_NONE) return(vpiHighZ);
5230    if (mdp->mod_uncdrv == PULL0) return(vpiPull0);
5231    if (mdp->mod_uncdrv == PULL1) return(vpiPull1);
5232    __vpi_terr(__FILE__, __LINE__);
5233    return(0);
5234   case vpiTopModule:
5235    if (mdp->minstnum == 0) return(TRUE);
5236    return(FALSE);
5237   /* LOOKATME - what should this be? */
5238   case vpiDefDecayTime: return(0);
5239   default: notpropof_err(hp->hrec->htyp, prop); break;
5240  }
5241  return(vpiUndefined);
5242 }
5243 
5244 /*
5245  * emit not property of handle err
5246  *
5247  * know hp non nil or will not get here
5248  */
notpropof_err(word32 typh,int32 prop)5249 static void notpropof_err(word32 typh, int32 prop)
5250 {
5251  __vpi_err(1867, vpiError,
5252   "property %s not defined for vpi_get of %s",
5253   __to_vpipnam(__wrks1, prop), __to_vpionam(__wrks2, typh));
5254 }
5255 
5256 /*
5257  * get the vpi handle object type for a variable (net_t)
5258  */
__ntyp_to_vpivarhtyp(struct net_t * np)5259 extern word32 __ntyp_to_vpivarhtyp(struct net_t *np)
5260 {
5261  word32 otyp;
5262 
5263  if (np->n_isaparam) otyp = vpiParameter;
5264  else if (np->ntyp < NONWIRE_ST) otyp = vpiNet;
5265  else if (np->n_isarr) otyp = vpiMemory;
5266  else otyp = to_vpi_reghtyp(np->ntyp);
5267  return(otyp);
5268 }
5269 
5270 /*
5271  * routine to convert from internal Cver net (but known to be reg)
5272  * type to vpi_ var object type
5273  *
5274  * SJM 08/11/97 - separated so old one type mapping from ntyp routine
5275  *                now 3 depending on vpi_ output needed
5276  */
to_vpi_reghtyp(word32 ntyp)5277 static word32 to_vpi_reghtyp(word32 ntyp)
5278 {
5279  switch (ntyp) {
5280   case N_REG: return(vpiReg);
5281   case N_INT: return(vpiIntegerVar);
5282   case N_TIME: return(vpiTimeVar);
5283   case N_REAL: return(vpiRealVar);
5284   default: __vpi_terr(__FILE__, __LINE__);
5285  }
5286  return(0);
5287 }
5288 
5289 /*
5290  * convert a Cver side net type to vpi_ var bit select type
5291  */
__to_vpinetbithtyp(word32 ntyp)5292 extern word32 __to_vpinetbithtyp(word32 ntyp)
5293 {
5294  if (ntyp < NONWIRE_ST) return(vpiNetBit);
5295  switch (ntyp) {
5296   case N_REG: return(vpiRegBit);
5297   case N_INT: case N_TIME: case N_REAL: return(vpiVarSelect);
5298   default: __vpi_terr(__FILE__, __LINE__);
5299  }
5300  return(0);
5301 }
5302 
5303 /*
5304  * routine to convert from internal Cver wire type to vpi property value
5305  * also converts internal net types to variable (reg,int32, ...) object types
5306  */
__to_vpi_netproptyp(word32 ntyp)5307 extern int32 __to_vpi_netproptyp(word32 ntyp)
5308 {
5309  switch (ntyp) {
5310   case N_WIRE: return(vpiWire);
5311   case N_WA: return(vpiWand);
5312   case N_WO: return(vpiWor);
5313   case N_TRI: return(vpiTri);
5314   case N_TRI0: return(vpiTri0);
5315   case N_TRI1: return(vpiTri1);
5316   case N_TRIREG: return(vpiTriReg);
5317   case N_TRIAND: return(vpiTriAnd);
5318   case N_TRIOR: return(vpiTriOr);
5319   case N_SUPPLY0: return(vpiSupply0);
5320   case N_SUPPLY1: return(vpiSupply1);
5321   case N_REG: return(vpiReg);
5322   case N_INT: return(vpiIntegerVar);
5323   case N_TIME: return(vpiTimeVar);
5324   case N_REAL: return(vpiRealVar);
5325   case N_EVENT: return(vpiNamedEvent);
5326   default: __vpi_terr(__FILE__, __LINE__);
5327  }
5328  return(vpiUndefined);
5329 }
5330 
5331 /*
5332  * routine to convert from vpi handle type known to be variable to
5333  * to internal ntyp
5334  *
5335  * never called with bit of (vpiNetBit or vpiRegBit)
5336  */
__from_vpi_vartyp(word32 pval)5337 extern word32 __from_vpi_vartyp(word32 pval)
5338 {
5339  switch ((byte) pval) {
5340   case vpiWire: return(N_WIRE);
5341   case vpiWand: return(N_WA);
5342   case vpiWor: return(N_WO);
5343   case vpiTri: return(N_TRI);
5344   case vpiTri0: return(N_TRI0);
5345   case vpiTri1: return(N_TRI1);
5346   case vpiTriReg: return(N_TRIREG);
5347   case vpiTriAnd: return(N_TRIAND);
5348   case vpiTriOr: return(N_TRIOR);
5349   case vpiSupply0: return(N_SUPPLY0);
5350   case vpiSupply1: return(N_SUPPLY1);
5351   case vpiReg: return(N_REG);
5352   case vpiIntegerVar: return(N_INT);
5353   case vpiTimeVar: return(N_TIME);
5354   case vpiRealVar: return(N_REAL);
5355   case vpiNamedEvent: return(N_EVENT);
5356   default: __vpi_terr(__FILE__, __LINE__);
5357  }
5358  return(0);
5359 }
5360 
5361 /*
5362  * get int32 property values of net for net or net bit (ignore bit)
5363  */
netprop_vpiget(struct h_t * hp,int32 prop)5364 static int32 netprop_vpiget(struct h_t *hp, int32 prop)
5365 {
5366  int32 biti;
5367  struct net_t *np;
5368  struct hrec_t *hrp;
5369 
5370  hrp = hp->hrec;
5371  if (hrp->htyp == vpiNetBit)
5372   {
5373    if (hrp->bith_ndx) np = hrp->hu.hnp;
5374    else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
5375   }
5376  else np = hrp->hu.hnp;
5377 
5378  switch (prop) {
5379   case vpiExpanded: return(TRUE);
5380   case vpiImplicitDecl:
5381    if (np->nsym->sy_impldecl) return(TRUE);
5382    return(FALSE);
5383   case vpiLineNo: return(np->nsym->sylin_cnt);
5384   /* vpiNetDeclAssign undeclared in Cver */
5385 
5386   /* get net type property (i.e vpiWand) not net expr. part obj htyp */
5387   /* know net or net bit or will not get here */
5388   case vpiNetType: return(__to_vpi_netproptyp(np->ntyp));
5389   case vpiScalar:
5390    if (np->n_isavec) return(FALSE);
5391    return(TRUE);
5392   /* always false in Cver since the default */
5393   case vpiExplicitScalared: return(FALSE);
5394   case vpiSigned:
5395    /* SJM 09/28/06 - for 2001/5 net type objects have signed prop */
5396    if (np->n_signed) return(TRUE);
5397    return(FALSE);
5398    break;
5399   case vpiSize:
5400    if (hrp->htyp == vpiNetBit) return(1);
5401    return(np->nwid);
5402   /* no net strengths in Cver (or Verilog?) just charge */
5403   /* if no charge strength returns 0 */
5404   case vpiChargeStrength:
5405    if (np->n_capsiz == CAP_NONE) return(0);
5406    if (np->n_capsiz == CAP_SMALL) return(vpiSmallCharge);
5407    if (np->n_capsiz == CAP_MED) return(vpiMediumCharge);
5408    if (np->n_capsiz == CAP_LARGE) return(vpiLargeCharge);
5409    __vpi_terr(__FILE__, __LINE__);
5410    break;
5411   case vpiVector:
5412    if (np->n_isavec) return(TRUE);
5413    return(FALSE);
5414   case vpiConstantSelect:
5415    if (hrp->htyp != vpiNetBit) goto bad_prop;
5416    if (hrp->bith_ndx) return(TRUE);
5417    if (__expr_is_vpiconst(hrp->hu.hxp->ru.x))
5418     {
5419      __push_itstk(hp->hin_itp);
5420      /* if constant already normalized to h:0, else this will normalize */
5421      /* variable index */
5422      biti = __comp_ndx(np, hrp->hu.hxp->ru.x);
5423      __pop_itstk();
5424      if (biti == -1) return(FALSE);
5425      return(TRUE);
5426     }
5427    return(FALSE);
5428 
5429   default:
5430 bad_prop:
5431     notpropof_err(hrp->htyp, prop); break;
5432  }
5433  return(vpiUndefined);
5434 }
5435 
5436 
5437 /*
5438  * get int32 property values for reg or reg bit (includes int32 and time)
5439  * all properties same
5440  */
regprop_vpiget(struct h_t * hp,int32 prop)5441 static int32 regprop_vpiget(struct h_t *hp, int32 prop)
5442 {
5443  int32 biti, is_bit;
5444  struct net_t *np;
5445  struct hrec_t *hrp;
5446 
5447  hrp = hp->hrec;
5448  is_bit = FALSE;
5449  if (hrp->htyp == vpiRegBit || hrp->htyp == vpiVarSelect)
5450   {
5451    if (hrp->bith_ndx) np = hrp->hu.hnp;
5452    else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
5453    is_bit = TRUE;
5454   }
5455  else np = hrp->hu.hnp;
5456 
5457  switch (prop) {
5458   case vpiLineNo: return(np->nsym->sylin_cnt);
5459   case vpiScalar:
5460    if (np->n_isavec) return(FALSE);
5461    return(TRUE);
5462   case vpiSigned:
5463    /* SJM 09/28/06 - for 2001/5 net type objects have signed prop */
5464    if (np->n_signed) return(TRUE);
5465    return(FALSE);
5466   case vpiSize:
5467    if (is_bit) return(1);
5468    return(np->nwid);
5469   case vpiVector:
5470    if (np->n_isavec && !is_bit) return(TRUE);
5471    return(FALSE);
5472   case vpiConstantSelect:
5473    if (hrp->htyp != vpiRegBit && hrp->htyp != vpiVarSelect) goto bad_prop;
5474    if (hrp->bith_ndx) return(TRUE);
5475    if (__expr_is_vpiconst(hrp->hu.hxp->ru.x))
5476     {
5477      __push_itstk(hp->hin_itp);
5478      /* if constant already normalized to h:0, else this will normalize */
5479      /* variable index */
5480      biti = __comp_ndx(np, hrp->hu.hxp->ru.x);
5481      __pop_itstk();
5482      if (biti == -1) return(FALSE);
5483      return(TRUE);
5484     }
5485    return(FALSE);
5486   default:
5487 bad_prop:
5488    notpropof_err(hrp->htyp, prop); break;
5489  }
5490  return(vpiUndefined);
5491 }
5492 
5493 /*
5494  * get int32 property values for array (know hp is array handle)
5495  */
arrprop_vpiget(struct h_t * hp,int32 prop)5496 static int32 arrprop_vpiget(struct h_t *hp, int32 prop)
5497 {
5498  struct net_t *np;
5499 
5500  np = hp->hrec->hu.hnp;
5501  switch (prop) {
5502   case vpiLineNo: return(np->nsym->sylin_cnt);
5503   case vpiSize: return(__get_arrwide(np));
5504   default: notpropof_err(hp->hrec->htyp, prop); break;
5505  }
5506  return(vpiUndefined);
5507 }
5508 
5509 /*
5510  * get int32 property values for word32 of array
5511  */
arrwrdprop_vpiget(struct h_t * hp,int32 prop)5512 static int32 arrwrdprop_vpiget(struct h_t *hp, int32 prop)
5513 {
5514  int32 biti;
5515  struct net_t *np;
5516  struct hrec_t *hrp;
5517 
5518  hrp = hp->hrec;
5519  if (hrp->bith_ndx) np = hrp->hu.hnp;
5520  else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
5521 
5522  switch (prop) {
5523   case vpiLineNo: return(np->nsym->sylin_cnt);
5524   case vpiSize: return(np->nwid);
5525   case vpiConstantSelect:
5526    if (hrp->bith_ndx) return(TRUE);
5527    /* DBG remove --- */
5528    if (__expr_is_vpiconst(hrp->hu.hxp->ru.x))
5529     {
5530      __push_itstk(hp->hin_itp);
5531      /* if constant already normalized to h:0, else this will normalize */
5532      /* variable index */
5533      biti = __comp_ndx(np, hrp->hu.hxp->ru.x);
5534      __pop_itstk();
5535      if (biti == -1) return(FALSE);
5536      return(TRUE);
5537     }
5538    return(FALSE);
5539 
5540   default: notpropof_err(hrp->htyp, prop); break;
5541  }
5542  return(vpiUndefined);
5543 }
5544 
5545 /*
5546  * get int32 property values for param
5547  */
paramprop_vpiget(struct h_t * hp,int32 prop)5548 static int32 paramprop_vpiget(struct h_t *hp, int32 prop)
5549 {
5550  struct net_t *np;
5551 
5552  np = hp->hrec->hu.hnp;
5553  switch (prop) {
5554   /* this will always be constant because evaluated to constant */
5555   /* may have been expr in source but by here always a number */
5556   case vpiConstType: return(get_param_constyp(np));
5557   case vpiLineNo: return(np->nsym->sylin_cnt);
5558   case vpiSize: return(np->nwid);
5559   case vpiLocalParam:
5560    if (np->nu.ct->p_locparam) return(TRUE);
5561    return(FALSE);
5562   case vpiSigned:
5563    /* SJM 09/28/06 - for 2001/5 net type objects have signed prop */
5564    if (hp->hrec->htyp == vpiParameter)
5565     {
5566      if (np->n_signed) return(TRUE);
5567      return(FALSE);
5568     }
5569   /* SJM 09/28/06 - fall thru if specparam since no has sign property */
5570   default: notpropof_err(hp->hrec->htyp, prop); break;
5571  }
5572  return(vpiUndefined);
5573 }
5574 
5575 /*
5576  * get param constant type property
5577  */
get_param_constyp(struct net_t * np)5578 static int32 get_param_constyp(struct net_t *np)
5579 {
5580  int32 ctyp;
5581 
5582  ctyp = 0;
5583  if (np->ntyp == N_REAL) return(vpiRealConst);
5584  if (np->nu.ct->pstring) return(vpiStringConst);
5585 
5586  switch (np->nu.ct->pbase) {
5587   case BBIN: ctyp = vpiBinaryConst; break;
5588   case BOCT: ctyp = vpiOctConst; break;
5589   case BDEC: ctyp = vpiDecConst; break;
5590   case BHEX: ctyp = vpiHexConst; break;
5591   default: __vpi_terr(__FILE__, __LINE__);
5592  }
5593  return(ctyp);
5594 }
5595 
5596 /*
5597  * get int32 property values for port and port bit
5598  */
portprop_vpiget(struct h_t * hp,int32 prop)5599 static int32 portprop_vpiget(struct h_t *hp, int32 prop)
5600 {
5601  struct mod_t *mdp;
5602  struct mod_pin_t *mpp;
5603  struct hrec_t *hrp;
5604 
5605  hrp = hp->hrec;
5606  mdp = hp->hin_itp->itip->imsym->el.emdp;
5607  mpp = &(mdp->mpins[hrp->hu.hpi]);
5608  switch (prop) {
5609   case vpiConnByName:
5610    if (mpp->mp_explicit) return(TRUE);
5611    return(FALSE);
5612   case vpiDirection:
5613    if (mpp->mptyp == IO_IN) return(vpiInput);
5614    if (mpp->mptyp == IO_OUT) return(vpiOutput);
5615    if (mpp->mptyp == IO_BID) return(vpiInout);
5616    __vpi_terr(__FILE__, __LINE__);
5617    break;
5618   case vpiExplicitName:
5619    if (mpp->mpsnam == NULL) return(FALSE);
5620    return(TRUE);
5621   case vpiPortIndex: return(hrp->hu.hpi);
5622   case vpiLineNo: return(mpp->mplin_cnt);
5623   case vpiScalar: return(mpp->mpwide == 1);
5624   case vpiSize:
5625    if (hrp->htyp == vpiPortBit) return(1);
5626    return(mpp->mpwide);
5627   case vpiVector:
5628    if (hrp->htyp == vpiPortBit) return(FALSE);
5629    return(mpp->mpwide != 1);
5630   default: notpropof_err(hrp->htyp, prop); break;
5631  }
5632  return(vpiUndefined);
5633 }
5634 
5635 /*
5636  * get int32 property values for primitives
5637  */
gateprop_vpiget(struct h_t * hp,int32 prop)5638 static int32 gateprop_vpiget(struct h_t *hp, int32 prop)
5639 {
5640  word32 sval;
5641  struct gate_t *gp;
5642  struct hrec_t *hrp;
5643 
5644  hrp = hp->hrec;
5645  gp = hrp->hu.hgp;
5646  switch (prop) {
5647   case vpiLineNo: return(gp->gsym->sylin_cnt);
5648   case vpiPrimType: return(__to_vpi_primtyp(gp));
5649   /* LRM defines this as number of inputs */
5650   case vpiSize:
5651    /* switch all terminasl are inputs (counting inouts) */
5652    if (hrp->htyp == vpiSwitch) return(gp->gpnum);
5653    /* for udp get from udp definition */
5654    if (hrp->htyp == vpiUdp) return(gp->gmsym->el.eudpp->numins);
5655    /* all other have one output (cmos is 3 inputs and one output */
5656    /* pullup/pulldown not seen here */
5657    return(gp->gpnum - 1);
5658   /* LOOKATME - what if no gate strength - no way to detect */
5659   case vpiStrength0:
5660    /* 0 is high 3 bits */
5661    sval = (gp->g_stval >> 3) & 0x7;
5662    return((int32) __map_tovpi_stren(sval));
5663   case vpiStrength1:
5664    /* 1 is low 3 bits */
5665    sval = gp->g_stval & 0x7;
5666    return((int32) __map_tovpi_stren(sval));
5667   default: notpropof_err(hrp->htyp, prop); break;
5668  }
5669  return(vpiUndefined);
5670 }
5671 
5672 /*
5673  * routine to convert from internal Cver gate type to vpi primitive class
5674  *
5675  * i.e. type of udp or particular type of gate (not vpi gate rather vpi Buf)
5676  */
__to_vpi_primtyp(struct gate_t * gp)5677 extern int32 __to_vpi_primtyp(struct gate_t *gp)
5678 {
5679  struct primtab_t *ptp;
5680  struct udp_t *udpp;
5681 
5682  if (gp->g_class == GC_UDP)
5683   {
5684    udpp = gp->gmsym->el.eudpp;
5685    if (udpp->utyp == U_COMB) return(vpiCombPrim);
5686    return(vpiSeqPrim);
5687   }
5688  ptp = gp->gmsym->el.eprimp;
5689  switch ((byte) ptp->gateid) {
5690   case G_BITREDAND: return(vpiAndPrim);
5691   case G_NAND: return(vpiNandPrim);
5692   case G_NOR: return(vpiNorPrim);
5693   case G_BITREDOR: return(vpiOrPrim);
5694   case G_BITREDXOR: return(vpiXorPrim);
5695   case G_REDXNOR: return(vpiXnorPrim);
5696   case G_BUF: return(vpiBufPrim);
5697   case G_NOT: return(vpiNotPrim);
5698   case G_BUFIF0: return(vpiBufif0Prim);
5699   case G_BUFIF1: return(vpiBufif1Prim);
5700   case G_NOTIF0: return(vpiNotif0Prim);
5701   case G_NOTIF1: return(vpiNotif1Prim);
5702   case G_NMOS: return(vpiNmosPrim);
5703   case G_RNMOS: return(vpiRnmosPrim);
5704   case G_PMOS: return(vpiPmosPrim);
5705   case G_RPMOS: return(vpiRpmosPrim);
5706   case G_CMOS: return(vpiCmosPrim);
5707   case G_RCMOS: return(vpiRcmosPrim);
5708   case G_TRAN: return(vpiTranPrim);
5709   case G_RTRAN: return(vpiRtranPrim);
5710   case G_TRANIF0: return(vpiTranif0Prim);
5711   case G_RTRANIF0: return(vpiRtranif0Prim);
5712   case G_TRANIF1: return(vpiTranif1Prim);
5713   case G_RTRANIF1: return(vpiRtranif1Prim);
5714   default: __vpi_terr(__FILE__, __LINE__);
5715  }
5716  return(vpiUndefined);
5717 }
5718 
5719 /*
5720  * get int32 property values for primitive (gate) terminals
5721  */
__primtermprop_vpiget(struct h_t * hp,int32 prop)5722 extern int32 __primtermprop_vpiget(struct h_t *hp, int32 prop)
5723 {
5724  struct gate_t *gp;
5725  struct hrec_t *hrp;
5726 
5727  hrp = hp->hrec;
5728  gp = hrp->hu.hgp;
5729  switch (prop) {
5730   case vpiDirection:
5731    /* tran switch first 2 terminals always bid - third for tranif input */
5732    if (gp->g_class == GC_TRAN || gp->g_class == GC_TRANIF)
5733     {
5734      if (hrp->hi == 2) return(vpiInput);
5735      return(vpiInout);
5736     }
5737    /* first (0th) terminal always output */
5738    if (hrp->hi == 0) return(vpiOutput);
5739    /* rest always input - not supporting >1 outpu buf/not gates */
5740    return(vpiInput);
5741 
5742   case vpiTermIndex: return(hrp->hi);
5743   case vpiLineNo: return(gp->gsym->sylin_cnt);
5744   default: notpropof_err(hrp->htyp, prop); break;
5745  }
5746  return(vpiUndefined);
5747 }
5748 
5749 /*
5750  * get property values for task call
5751  *
5752  * LOOKAT - interpreted LRM to allow vpUserDefn for user system tasks
5753  * <not clear from even new Verilog 98 LRM page>
5754  */
tcallprop_vpiget(struct h_t * hp,int32 prop)5755 static int32 tcallprop_vpiget(struct h_t *hp, int32 prop)
5756 {
5757  struct tskcall_t *tkcp;
5758  struct systsk_t *stbp;
5759  struct hrec_t *hrp;
5760 
5761  hrp = hp->hrec;
5762  switch (prop) {
5763   case vpiLineNo: return(hrp->hu.hstp->stlin_cnt);
5764   case vpiUserDefn:
5765    /* non system task is always user defined */
5766    if (hrp->htyp == vpiTaskCall) return(TRUE);
5767    tkcp = &(hrp->hu.hstp->st.stkc);
5768    stbp = tkcp->tsksyx->lu.sy->el.esytbp;
5769    if (stbp->stsknum > BASE_VERIUSERTFS) return(TRUE);
5770    return(FALSE);
5771   default: notpropof_err(hrp->htyp, prop);
5772  }
5773  return(vpiUndefined);
5774 }
5775 
5776 /*
5777  * get property values of function definition (task def. has only str props)
5778  *
5779  * this is only for user function definitions (vpiFunction) - use
5780  * vpi get systtf_info for system functions
5781  */
funcdefprop_vpiget(struct h_t * hp,int32 prop)5782 static int32 funcdefprop_vpiget(struct h_t *hp, int32 prop)
5783 {
5784  int32 pval;
5785  struct net_t *np;
5786  struct task_t *tskp;
5787 
5788  tskp = hp->hrec->hu.htskp;
5789  pval = 0;
5790  switch (prop) {
5791   case vpiLineNo:
5792    pval = tskp->tsksyp->sylin_cnt;
5793    break;
5794   case vpiFuncType:
5795    /* first pin for func. is the return value */
5796    np = tskp->tskpins->tpsy->el.enp;
5797    if (np->ntyp == N_INT) { pval = vpiIntFunc; break; }
5798    if (np->ntyp == N_REAL) { pval = vpiRealFunc; break; }
5799    if (np->ntyp == N_TIME) { pval = vpiTimeFunc; break; }
5800    pval = vpiSizedFunc;
5801    break;
5802   case vpiSize:
5803    /* first pin for func. is the return value */
5804    np = tskp->tskpins->tpsy->el.enp;
5805    pval = np->nwid;
5806    break;
5807   case vpiSigned:
5808    /* SJM 09/28/06 - for 2001/5 net type objects have signed prop */
5809    np = tskp->tskpins->tpsy->el.enp;
5810    if (np->n_signed) pval = TRUE; else pval = FALSE;
5811    break;
5812   default:
5813    notpropof_err(hp->hrec->htyp, prop);
5814    return(vpiUndefined);
5815  }
5816  return(pval);
5817 }
5818 
5819 /*
5820  * get property values (int32) for cont assign
5821  */
contaprop_vpiget(struct h_t * hp,int32 prop)5822 static int32 contaprop_vpiget(struct h_t *hp, int32 prop)
5823 {
5824  word32 sval;
5825  struct conta_t *cap;
5826  struct gate_t *gp;
5827  struct hrec_t *hrp;
5828 
5829  hrp = hp->hrec;
5830  if (hrp->htyp2 == vpiGate)
5831   {
5832    gp = hrp->hu.hgp;
5833    switch (prop) {
5834     case vpiLineNo: return(gp->gsym->sylin_cnt);
5835     case vpiNetDeclAssign:
5836      /* in Cver always assuming not part of net since not preserved */
5837      /* FIXME - should record */
5838      return(FALSE);
5839     case vpiStrength0:
5840      /* 0 is high 3 bits */
5841      sval = (gp->g_stval >> 3) & 0x7;
5842      return((int32) __map_tovpi_stren(sval));
5843     case vpiStrength1:
5844      /* 1 is low 3 bits */
5845      sval = gp->g_stval & 0x7;
5846      return((int32) __map_tovpi_stren(sval));
5847     default: notpropof_err(hrp->htyp, prop); break;
5848    }
5849    return(vpiUndefined);
5850   }
5851  cap = hrp->hu.hcap;
5852  switch (prop) {
5853   case vpiLineNo: return(cap->casym->sylin_cnt);
5854   /* vpiNetDeclAssign undeclared in Cver */
5855   case vpiStrength0:
5856    /* 0 is high 3 bits */
5857    sval = (cap->ca_stval >> 3) & 0x7;
5858    return((int32) __map_tovpi_stren(sval));
5859   case vpiStrength1:
5860    /* 1 is low 3 bits */
5861    sval = cap->ca_stval & 0x7;
5862    return((int32) __map_tovpi_stren(sval));
5863   default: notpropof_err(hrp->htyp, prop); break;
5864  }
5865  return(vpiUndefined);
5866 }
5867 
5868 /*
5869  * get property values for function call (user or system)
5870  *
5871  * name for vpiSysFunc and vpiFunc subtype property changed to vpiFuncType and
5872  * now applies to both user and system functions: values now are
5873  * vpiIntFunc, vpiRealFunc, vpiTimeFunc, vpiSizedFunc
5874  *
5875  * contrary to new Veirlog 98 LRM system func calls do not have line location
5876  * so emitting warning and return 0
5877  */
fcallprop_vpiget(struct h_t * hp,int32 prop)5878 static int32 fcallprop_vpiget(struct h_t *hp, int32 prop)
5879 {
5880  int32 pval;
5881  struct sy_t *fsyp;
5882  struct sysfunc_t *sfbp;
5883  struct task_t *tskp;
5884  struct net_t *np;
5885  struct hrec_t *hrp;
5886 
5887  hrp = hp->hrec;
5888  pval = 0;
5889  /* case 1: user function call */
5890  if (hrp->htyp == vpiFuncCall)
5891   {
5892    fsyp = hrp->hu.hxp->lu.x->lu.sy;
5893    switch (prop) {
5894     case vpiSize:
5895      /* FIXME - what should size of real be - for now making it 0 */
5896      if (hrp->hu.hxp->is_real) { pval = 0; break; }
5897      pval = hrp->hu.hxp->szu.xclen;
5898      break;
5899     case vpiLineNo:
5900      /* for compatibility making location 0 with inform */
5901      __vpi_err(2112, vpiNotice,
5902       "vpiLineNo property not saved for vpiFuncCall object - 0 returned");
5903      pval = 0;
5904      break;
5905     case vpiFuncType:
5906      tskp = fsyp->el.etskp;
5907      /* DBG remove --- */
5908      if (tskp->tskpins == NULL || tskp->tskpins->tpsy == NULL)
5909       __vpi_terr(__FILE__, __LINE__);
5910      /* --- */
5911      np = tskp->tskpins->tpsy->el.enp;
5912      if (np->ntyp == N_INT) { pval = vpiIntFunc; break; }
5913      if (np->ntyp == N_REAL) { pval = vpiRealFunc; break; }
5914      if (np->ntyp == N_TIME) { pval = vpiTimeFunc; break; }
5915      pval = vpiSizedFunc;
5916      break;
5917     default:
5918 no_prop:
5919      notpropof_err(hrp->htyp, prop);
5920      return(vpiUndefined);
5921    }
5922    return(pval);
5923   }
5924  /* DBG remove --- */
5925  if (hrp->htyp != vpiSysFuncCall) __vpi_terr(__FILE__, __LINE__);
5926  /* --- */
5927 
5928  /* case 2: sysfunc of some type call */
5929  fsyp = hrp->hu.hxp->lu.x->lu.sy;
5930  sfbp = fsyp->el.esyftbp;
5931  switch (prop) {
5932   case vpiUserDefn:
5933    if (sfbp->syfnum > BASE_VERIUSERTFS) pval = TRUE;
5934    else pval = FALSE;
5935    break;
5936   case vpiSize:
5937    /* FIXME - what should size of real be - for now making it 0 */
5938    if (sfbp->retntyp == N_REAL) { pval = 0; break; }
5939    pval = hrp->hu.hxp->szu.xclen;
5940    break;
5941 
5942   /* as of Verilog 98, both normal and system functions have ret. type */
5943   case vpiFuncType:
5944    if (sfbp->retntyp == N_INT) { pval = vpiIntFunc; break; }
5945    if (sfbp->retntyp == N_REAL) { pval = vpiRealFunc; break; }
5946    if (sfbp->retntyp == N_TIME) { pval = vpiTimeFunc; break; }
5947    pval = vpiSizedFunc;
5948    break;
5949   case vpiLineNo:
5950    __vpi_err(2112, vpiNotice,
5951     "vpiLineNo property not saved for vpiSysFuncCall object - 0 returned");
5952    return(0);
5953   default: goto no_prop;
5954  }
5955  return(pval);
5956 }
5957 
5958 /*
5959  * get property values for tchk
5960  */
tchkprop_vpiget(struct h_t * hp,int32 prop)5961 static int32 tchkprop_vpiget(struct h_t *hp, int32 prop)
5962 {
5963  int32 pval;
5964  struct tchk_t *tcp;
5965 
5966  tcp = hp->hrec->hu.htcp;
5967  switch (prop) {
5968   case vpiLineNo: pval = tcp->tcsym->sylin_cnt; break;
5969   case vpiTchkType:
5970    pval = to_vpi_tchktyp(tcp->tchktyp);
5971    break;
5972   default: notpropof_err(hp->hrec->htyp, prop); pval = vpiUndefined;
5973  }
5974  return(pval);
5975 }
5976 
5977 /*
5978  * routine to convert from internal Cver tchk type to vpi_ constant
5979  *
5980  * notice hold of setup hold separate tchk but will never see
5981  */
to_vpi_tchktyp(word32 tctyp)5982 static int32 to_vpi_tchktyp(word32 tctyp)
5983 {
5984  switch ((byte) tctyp) {
5985   case TCHK_SETUP: return(vpiSetup);
5986   case TCHK_HOLD: return(vpiHold);
5987   case TCHK_WIDTH: return(vpiWidth);
5988   case TCHK_PERIOD: return(vpiPeriod);
5989   case TCHK_SKEW: return(vpiSkew);
5990   case TCHK_RECOVERY: return(vpiRecovery);
5991   case TCHK_NOCHANGE: return(vpiNoChange);
5992   case TCHK_SETUPHOLD: return(vpiSetupHold);
5993   /* SJM 12/15/03 - new 2001 timing checks - recognized but not supported */
5994   case TCHK_FULLSKEW: return(vpiFullskew);
5995   case TCHK_RECREM: return(vpiRecrem);
5996   case TCHK_REMOVAL: return(vpiRemoval);
5997   case TCHK_TIMESKEW: return(vpiTimeskew);
5998   default: __vpi_terr(__FILE__, __LINE__);
5999  }
6000  return(vpiUndefined);
6001 }
6002 
6003 /*
6004  * get property values for function call
6005  * LOOKATME - think reversed 1st and 2nd term for setup already moved?
6006  */
tchktermprop_vpiget(struct h_t * hp,int32 prop)6007 static int32 tchktermprop_vpiget(struct h_t *hp, int32 prop)
6008 {
6009  int32 pval;
6010  struct tchk_t *tcp;
6011 
6012  tcp = hp->hrec->hu.htcp;
6013  switch (prop) {
6014   case vpiLineNo: pval = tcp->tcsym->sylin_cnt; break;
6015   case vpiEdge:
6016    if (hp->hrec->htyp2 == vpiTchkRefTerm)
6017     pval = to_vpi_edgeval(tcp->startedge);
6018    else if (hp->hrec->htyp2 == vpiTchkDataTerm)
6019     pval = to_vpi_edgeval(tcp->chkedge);
6020    else { __vpi_terr(__FILE__, __LINE__); return(vpiUndefined); }
6021    break;
6022   default: notpropof_err(hp->hrec->htyp, prop); pval = vpiUndefined;
6023  }
6024  return(pval);
6025 }
6026 
6027 /*
6028  * routine to convert from internal Cver edge to Vpi edge
6029  * they are identical execept no any edge in Cver (same filtering algorithm)
6030  *
6031  * LOOKATME: could just remove this identity mapping since same
6032  */
to_vpi_edgeval(word32 edg)6033 static int32 to_vpi_edgeval(word32 edg)
6034 {
6035  switch ((byte) edg) {
6036   case NOEDGE: return(vpiNoEdge);
6037   case EDGE01: return(vpiEdge01);
6038   case EDGE10: return(vpiEdge10);
6039   case EDGE0X: return(vpiEdge0x);
6040   case EDGEX1: return(vpiEdgex1);
6041   case EDGE1X: return(vpiEdge1x);
6042   case EDGEX0: return(vpiEdgex0);
6043   case E_POSEDGE: return(vpiPosEdge);
6044   case E_NEGEDGE: return(vpiNegEdge);
6045   default: __vpi_terr(__FILE__, __LINE__);
6046  }
6047  return(vpiUndefined);
6048 }
6049 
6050 /*
6051  * get property values for function call
6052  */
pthprop_vpiget(struct h_t * hp,int32 prop)6053 static int32 pthprop_vpiget(struct h_t *hp, int32 prop)
6054 {
6055  int32 pval;
6056  struct spcpth_t *pthp;
6057 
6058  pthp = hp->hrec->hu.hpthp;
6059  switch (prop) {
6060   case vpiLineNo: pval = pthp->pthsym->sylin_cnt; break;
6061   case vpiPathType:
6062    if (pthp->pthtyp == PTH_PAR) pval = vpiPathParallel;
6063    else if (pthp->pthtyp == PTH_FULL) pval = vpiPathFull;
6064    else { __vpi_terr(__FILE__, __LINE__); pval = vpiUndefined; }
6065    break;
6066   case vpiPolarity:
6067    if (pthp->pthpolar == POLAR_PLUS) pval = vpiPositive;
6068    else if (pthp->pthpolar == POLAR_MINUS) pval = vpiNegative;
6069    else if (pthp->pthpolar == POLAR_NONE) pval = vpiUnknown;
6070    else { __vpi_terr(__FILE__, __LINE__); pval = vpiUndefined; }
6071    break;
6072   case vpiDataPolarity:
6073    if (pthp->dsrc_polar == POLAR_PLUS) pval = vpiPositive;
6074    else if (pthp->dsrc_polar == POLAR_MINUS) pval = vpiNegative;
6075    else if (pthp->dsrc_polar == POLAR_NONE) pval = vpiUnknown;
6076    else { __vpi_terr(__FILE__, __LINE__); pval = vpiUndefined; }
6077    break;
6078   case vpiModPathHasIfNone:
6079    if (pthp->pth_ifnone) pval = TRUE; else pval = FALSE;
6080    break;
6081   default: notpropof_err(hp->hrec->htyp, prop); pval = vpiUndefined;
6082  }
6083  return(pval);
6084 }
6085 
6086 /*
6087  * get property values for function call
6088  * handle is hu pthp, hi - index, htyp2 is list from
6089  */
pthtermprop_vpiget(struct h_t * hp,int32 prop)6090 static int32 pthtermprop_vpiget(struct h_t *hp, int32 prop)
6091 {
6092  struct spcpth_t *pthp;
6093  int32 pval;
6094 
6095  pthp = hp->hrec->hu.hpthp;
6096  switch (prop) {
6097   case vpiLineNo: pval = pthp->pthsym->sylin_cnt; break;
6098   case vpiDirection: pval = (int32) hp->hrec->htyp2; break;
6099   case vpiEdge:
6100    /* only path in has edge */
6101    if (hp->hrec->htyp2 != vpiModPathIn) goto no_prop;
6102    pval = to_vpi_edgeval(pthp->pthedge);
6103    break;
6104   default:
6105 no_prop:
6106    notpropof_err(hp->hrec->htyp, prop);
6107    pval = vpiUndefined;
6108  }
6109  return(pval);
6110 }
6111 
6112 /*
6113  * get an expr property (know hp is vpiExpr to get here)
6114  *
6115  * uses changed semantics because of added vpiExpr object
6116  */
exprclass_prop_vpiget(struct h_t * hp,int32 prop)6117 static int32 exprclass_prop_vpiget(struct h_t *hp, int32 prop)
6118 {
6119  int32 pval;
6120  struct expr_t *xp;
6121 
6122  xp = hp->hrec->hu.hxp;
6123  pval = vpiUndefined;
6124  switch (hp->hrec->htyp) {
6125   case vpiOperation:
6126    if (prop == vpiOpType) pval = __expr_optype_get(xp);
6127    else if (prop == vpiSize) pval = xp->szu.xclen;
6128    else goto not_prop;
6129    break;
6130   case vpiConstant:
6131    if (prop == vpiConstType)
6132     {
6133      return(get_vpi_const_typ(xp));
6134     }
6135    else if (prop == vpiSize) pval = xp->szu.xclen;
6136    else goto not_prop;
6137    break;
6138   /* misc. with no special properties */
6139   case vpiFuncCall: case vpiSysFuncCall:
6140    if (prop == vpiSize) pval = xp->szu.xclen;
6141    else goto not_prop;
6142    break;
6143   case vpiPartSelect:
6144    if (prop == vpiSize) pval = xp->szu.xclen;
6145    else if (prop == vpiConstantSelect) pval = TRUE;
6146    else goto not_prop;
6147    break;
6148   default: goto not_prop;
6149  }
6150  return(pval);
6151 
6152 not_prop:
6153  notpropof_err(hp->hrec->htyp, prop);
6154  return(vpiUndefined);
6155 }
6156 
6157 /*
6158  * get constant type property from expression
6159  */
get_vpi_const_typ(struct expr_t * xp)6160 static int32 get_vpi_const_typ(struct expr_t *xp)
6161 {
6162  if (xp->is_real) return(vpiRealConst);
6163  if (xp->is_string) return(vpiStringConst);
6164  if (xp->ibase == BBIN) return(vpiBinaryConst);
6165  if (xp->ibase == BOCT) return(vpiOctConst);
6166  if (xp->ibase == BDEC) return(vpiDecConst);
6167  if (xp->ibase == BHEX) return(vpiHexConst);
6168  __vpi_terr(__FILE__, __LINE__);
6169  return(vpiUndefined);
6170 }
6171 
6172 /*
6173  * given an internal (ndp) expr node, return vpi_ expression htyp
6174  *
6175  * this gets type, no itree information needed
6176  */
__exprtype_get(struct expr_t * ndp)6177 extern int32 __exprtype_get(struct expr_t *ndp)
6178 {
6179  struct net_t *np;
6180  struct sy_t *syp;
6181 
6182  /* in this case, must put value on tos */
6183  switch ((byte) ndp->optyp) {
6184   case NUMBER: case REALNUM: case ISNUMBER: case ISREALNUM:
6185    return(vpiConstant);
6186   case GLBREF: case ID:
6187    np = ndp->lu.sy->el.enp;
6188    return(__ntyp_to_vpivarhtyp(np));
6189   case LSB:
6190    /* this must just return select from a variable (net/reg/var) */
6191    return(vpiVarSelect);
6192   case PARTSEL: return(vpiPartSelect);
6193   case FCALL:
6194    syp = ndp->lu.x->lu.sy;
6195    if (syp->sytyp == SYM_SF) return(vpiSysFuncCall);
6196    return(vpiFuncCall);
6197  }
6198  /* LOOKATME - currently no way to check - only other possibility is op */
6199  return(vpiOperation);
6200 }
6201 
6202 /*
6203  * for a binary or unary or ?: expression return the top node operator type
6204  */
__expr_optype_get(struct expr_t * xp)6205 extern int32 __expr_optype_get(struct expr_t *xp)
6206 {
6207  switch ((byte) xp->optyp) {
6208   /* unary ops */
6209   case BITNOT: return(vpiBitNegOp);
6210   case REALNOT: case NOT: return(vpiNotOp);
6211   /* both binary and unary in Cver */
6212   case REALMINUS: case MINUS:
6213    if (xp->ru.x == NULL) return(vpiMinusOp);
6214    return(vpiSubOp);
6215   case PLUS: case REALPLUS:
6216    if (xp->ru.x == NULL) return(vpiPlusOp);
6217    return(vpiAddOp);
6218   /* LOOKATME - vpiUnaryNorOp does not exist in Cver - decomposed */
6219   case BITREDOR:
6220    if (xp->ru.x == NULL) return(vpiUnaryOrOp);
6221    return(vpiBitOrOp);
6222   case BITREDXOR:
6223    if (xp->ru.x == NULL) return(vpiUnaryXorOp);
6224    return(vpiBitXorOp);
6225   case REDXNOR:
6226    if (xp->ru.x == NULL) return(vpiUnaryXNorOp);
6227    return(vpiBitXNorOp);
6228   /* vpiUnaryNandOp does not exist in Cver - decomposed */
6229   case BITREDAND:
6230    if (xp->ru.x == NULL) return(vpiUnaryAndOp);
6231    return(vpiBitAndOp);
6232 
6233   /* binary only ops */
6234   case TIMES: case REALTIMES: return(vpiMultOp);
6235   case DIV: case REALDIV: return(vpiDivOp);
6236   case MOD: return(vpiModOp);
6237   case REALRELGT: case RELGT: return(vpiGtOp);
6238   case RELGE: case REALRELGE: return(vpiGeOp);
6239   case RELLT: case REALRELLT: return(vpiLtOp);
6240   case RELLE: case REALRELLE: return(vpiLeOp);
6241   case RELCEQ: return(vpiCaseEqOp);
6242   case RELCNEQ: return(vpiCaseNeqOp);
6243   case RELEQ: case REALRELEQ: return(vpiEqOp);
6244   case RELNEQ: case REALRELNEQ: return(vpiNeqOp);
6245   case BOOLAND: case REALBOOLAND: return(vpiLogAndOp);
6246   case BOOLOR: case REALBOOLOR: return(vpiLogOrOp);
6247   case SHIFTL: return(vpiLShiftOp);
6248   case ASHIFTL: return(vpiArithLShiftOp);
6249   case SHIFTR: return(vpiRShiftOp);
6250   case ASHIFTR: return(vpiArithRShiftOp);
6251   case QUEST: case REALREALQUEST: case REALREGQUEST: case REGREALQCOL:
6252     return(vpiConditionOp);
6253   /* SJM 06/01/04 - ### ??? LOOKATME - vpi_ can't distinguish 2 ev or types */
6254   case OPEVOR: case OPEVCOMMAOR: return(vpiEventOrOp);
6255   case OPPOSEDGE: return(vpiPosedgeOp);
6256   case OPNEGEDGE: return(vpiNegedgeOp);
6257   case LCB: return(vpiConcatOp);
6258   case CATREP: return(vpiMultiConcatOp);
6259   case OPEMPTY: return(vpiNullOp);
6260   default: __vpi_terr(__FILE__, __LINE__);
6261  }
6262  return(vpiUndefined);
6263 }
6264 
6265 /*
6266  * get properties of an iodecl object
6267  *
6268  * udp io decl indicated by htyp2 type of vpiUdpDefn
6269  * if any bits of net are in port, entire net is a port (hu hnp field set)
6270  */
iodecl_prop_vpiget(struct h_t * hp,int32 prop)6271 static int32 iodecl_prop_vpiget(struct h_t *hp, int32 prop)
6272 {
6273  int32 pval;
6274  struct net_t *np;
6275  struct hrec_t *hrp;
6276 
6277  hrp = hp->hrec;
6278  if (hrp->htyp2 == vpiUdpDefn) return(udpiodecl_get(hp, prop));
6279  pval = vpiUndefined;
6280  np = hrp->hu.hnp;
6281  switch (prop) {
6282   case vpiDirection:
6283    if (np->ntyp == IO_IN) pval = vpiInput;
6284    else if (np->ntyp == IO_OUT) pval = vpiOutput;
6285    else if (np->ntyp == IO_BID) pval = vpiInout;
6286    else __vpi_terr(__FILE__, __LINE__);
6287    break;
6288   case vpiLineNo:
6289    pval = np->nsym->sylin_cnt;
6290    break;
6291   case vpiSize:
6292    pval = np->nwid;
6293    break;
6294   case vpiScalar:
6295    if (!np->n_isavec) pval = TRUE; else pval = FALSE;
6296    break;
6297   case vpiSigned:
6298    /* SJM 09/28/06 - for 2001/5 net type objects have signed prop */
6299    if (np->n_signed) pval = TRUE; else pval = FALSE;
6300    break;
6301   case vpiVector:
6302    if (np->n_isavec) pval = TRUE; else pval = FALSE;
6303    break;
6304   default: notpropof_err(hrp->htyp, prop);
6305  }
6306  return(pval);
6307 }
6308 
6309 /*
6310  * get properties for a udp io decl object (mod pin - not nets)
6311  */
udpiodecl_get(struct h_t * hp,int32 prop)6312 static int32 udpiodecl_get(struct h_t *hp, int32 prop)
6313 {
6314  int32 pval;
6315  struct mod_t *mdp;
6316  struct mod_pin_t *mpp;
6317 
6318  mdp = hp->hin_itp->itip->imsym->el.emdp;
6319  mpp = &(mdp->mpins[hp->hrec->hu.hpi]);
6320  pval = vpiUndefined;
6321  switch (prop) {
6322   case vpiDirection:
6323    if (mpp->mptyp == IO_IN) pval = vpiInput;
6324    else if (mpp->mptyp == IO_OUT) pval = vpiOutput;
6325    else __vpi_terr(__FILE__, __LINE__);
6326    break;
6327   case vpiLineNo:
6328    pval = mpp->mplin_cnt;
6329    break;
6330   case vpiSize:
6331    pval = 1;
6332    break;
6333   case vpiScalar:
6334    pval = TRUE;
6335    break;
6336   case vpiVector:
6337    pval = FALSE;
6338    break;
6339   default: notpropof_err(hp->hrec->htyp, prop);
6340  }
6341  return(pval);
6342 }
6343 
6344 /*
6345  * get a upd definition property
6346  */
udpdefnprop_vpiget(struct h_t * hp,int32 prop)6347 static int32 udpdefnprop_vpiget(struct h_t *hp, int32 prop)
6348 {
6349  int32 pval;
6350  struct udp_t *udpp;
6351 
6352  pval = vpiUndefined;
6353  udpp = hp->hrec->hu.hudpp;
6354  switch (prop) {
6355   case vpiLineNo:
6356    pval = udpp->usym->sylin_cnt;
6357    break;
6358   case vpiSize:
6359    /* LOOKATME - for now using number of inputs not states */
6360    pval = udpp->numins;
6361    break;
6362   case vpiProtected:
6363    /* no protection in Cver */
6364    pval = FALSE;
6365    break;
6366   case vpiPrimType:
6367    /* SJM 03/01/04 - properties were reversed here */
6368    if (udpp->utyp == U_COMB) pval = vpiCombPrim;
6369    else if (udpp->utyp == U_LEVEL || udpp->utyp == U_EDGE)
6370     pval = vpiSeqPrim;
6371    else __vpi_terr(__FILE__, __LINE__);
6372    break;
6373   default: notpropof_err(hp->hrec->htyp, prop);
6374  }
6375  return(pval);
6376 }
6377 
6378 /*
6379  * get a upd definition property
6380  */
udptabentryprop_vpiget(struct h_t * hp,int32 prop)6381 static int32 udptabentryprop_vpiget(struct h_t *hp, int32 prop)
6382 {
6383  int32 pval;
6384  struct udp_t *udpp;
6385  struct utline_t *utlp;
6386 
6387  pval = vpiUndefined;
6388  udpp = (struct udp_t *) hp->hin_itp;
6389  utlp = hp->hrec->hu.hutlp;
6390 
6391  switch (prop) {
6392   case vpiLineNo:
6393    pval = (int32) utlp->utlin_cnt;
6394    break;
6395   case vpiSize:
6396    /* value is number of states plus one for out */
6397    pval = udpp->numstates + 1;
6398    break;
6399   default: notpropof_err(hp->hrec->htyp, prop);
6400  }
6401  return(pval);
6402 }
6403 
6404 /*
6405  * get property of attribute
6406  */
dig_attrprop_vpiget(struct h_t * hp,int32 prop)6407 static int32 dig_attrprop_vpiget(struct h_t *hp, int32 prop)
6408 {
6409  int32 pval;
6410  double d1;
6411  struct attr_t *attrp;
6412  struct xstk_t *xsp;
6413 
6414  pval = vpiUndefined;
6415  switch (prop) {
6416   case vpiDefAttribute:
6417    /* T if no value or non zero value */
6418    attrp = __find_attrspec(hp);
6419    if (attrp->attr_xp == NULL) { pval = 1; break; }
6420    /* LOOKATME - since know number could access as constant */
6421    xsp = __eval_xpr(attrp->attr_xp);
6422    if (attrp->attr_xp->is_real)
6423     {
6424      memcpy(&d1, xsp->ap, sizeof(double));
6425      if (d1 != 0.0) pval = 1; else pval = 0;
6426      __pop_xstk();
6427      break;
6428     }
6429    if (vval_is0_(xsp->ap, xsp->xslen) && vval_is0_(xsp->bp, xsp->xslen))
6430     pval = 0;
6431    else pval = 1;
6432    __pop_xstk();
6433    break;
6434   case vpiConstType:
6435    attrp = __find_attrspec(hp);
6436    if (attrp->attr_xp == NULL) { pval = vpiUndefined; break; }
6437    pval = get_vpi_const_typ(attrp->attr_xp);
6438    break;
6439   default: notpropof_err(hp->hrec->htyp, prop);
6440  }
6441  return(pval);
6442 }
6443 
6444 /*
6445  * find attribute by getting parent object then moving through list
6446  * passed attribute object returns matching attribute struct
6447  *
6448  * BEWARE - this must be inverse of iterator since goes form iterator
6449  * element to parent
6450  */
__find_attrspec(struct h_t * hp)6451 extern struct attr_t *__find_attrspec(struct h_t *hp)
6452 {
6453  register int32 ai;
6454  struct attr_t *attrp;
6455  struct inst_t *ip;
6456  struct mod_t *mdp;
6457  struct gate_t *gp;
6458  struct hrec_t *hrp;
6459 
6460  attrp = NULL;
6461  hrp = hp->hrec;
6462  switch (hrp->htyp2) {
6463   case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
6464   case vpiNamedEvent: case vpiRealVar:
6465   /* LOOKATME - is this defined in LRM - think so */
6466   case vpiMemory:
6467    attrp = hrp->hu.hnp->nattrs;
6468    break;
6469   case vpiModule:
6470    /* FIXME - need to add and access bit determing where attr is ??? */
6471    ip = hp->hin_itp->itip;
6472    /* if dig attr attached to inst use it */
6473    if (ip->iattrs != NULL) { attrp = ip->iattrs; break; }
6474    /* else use any attached to module */
6475    mdp = ip->imsym->el.emdp;
6476    attrp = mdp->mattrs;
6477    break;
6478   case vpiGate: case vpiSwitch: case vpiUdp:
6479    gp = hrp->hu.hgp;
6480    attrp = gp->gattrs;
6481    break;
6482   default: __vpi_terr(__FILE__, __LINE__);
6483  }
6484  ai = hrp->hi;
6485  for (ai = 0; ai < hrp->hi; ai++)
6486   {
6487    if (attrp == NULL) __vpi_terr(__FILE__, __LINE__);
6488    attrp = attrp->attrnxt;
6489   }
6490  if (attrp == NULL) __vpi_terr(__FILE__, __LINE__);
6491  return(attrp);
6492 }
6493 
6494 
6495 /*
6496  * ROUTINES TO GET STRING PROPERTIES
6497  */
6498 
6499 /*
6500  * get a string property
6501  */
vpi_get_str(PLI_INT32 property,vpiHandle object)6502 extern char *vpi_get_str(PLI_INT32 property, vpiHandle object)
6503 {
6504  PLI_INT32 pval;
6505  struct h_t *hp;
6506  struct gate_t *gp;
6507  struct sy_t *syp;
6508  struct st_t *stp;
6509  struct hrec_t *hrp;
6510 
6511  __last_eip = NULL;
6512  if (__run_state == SS_COMP)
6513   { __still_comp_err("vpi_get_str"); return(NULL); }
6514  if (!validate_property("vpi_get_str", property)) return(NULL);
6515 
6516  if (object == NULL)
6517   {
6518    __vpi_err(1865, vpiError,
6519     "property %s illegal for vpi_get_str with NULL object",
6520     __to_vpipnam(__wrks1, property));
6521    return(NULL);
6522   }
6523 
6524  hp = (struct h_t *) object;
6525  if (!__validate_handle("vpi_get_str", hp)) return(NULL);
6526  hrp = hp->hrec;
6527 
6528  /* LOOKATME - special meta string property - standard needs meta name */
6529  if (property == vpiType)
6530   {
6531    /* every handle has a type */
6532    __to_vpionam(__wrk_vpiget_str, hrp->htyp);
6533    return(__wrk_vpiget_str);
6534   }
6535 
6536  switch (hrp->htyp) {
6537   case vpiModule:
6538    return(modstrprop_vpiget(hp, property));
6539   /* all net string properties the same */
6540   case vpiNet: case vpiNetBit: case vpiReg: case vpiRegBit: case vpiVarSelect:
6541   case vpiIntegerVar: case vpiTimeVar: case vpiNamedEvent:
6542   case vpiRealVar: case vpiParameter: case vpiSpecParam:
6543   case vpiMemory: case vpiMemoryWord:
6544    return(netstrprop_vpiget(hp, property));
6545   case vpiPort: case vpiPortBit:
6546    return(portstrprop_vpiget(hp, property));
6547   case vpiGate: case vpiUdp: case vpiSwitch:
6548    return(gatestrprop_vpiget(hp, property));
6549   case vpiPrimTerm:
6550    if (property != vpiFile)
6551     { __notstrpropof_err(hrp->htyp, property); return(NULL); }
6552    gp = hrp->hu.hgp;
6553    strcpy(__wrk_vpiget_str, __in_fils[gp->gsym->syfnam_ind]);
6554    return(__wrk_vpiget_str);
6555   case vpiFuncCall: case vpiSysFuncCall:
6556    return(fcallstrprop_vpiget(hp, property));
6557   case vpiTaskCall: case vpiSysTaskCall:
6558    return(tcallstrprop_vpiget(hp, property));
6559   /* handles whose only str property is file location */
6560   case vpiTchk: case vpiTchkTerm:
6561    syp = hrp->hu.htcp->tcsym;
6562 ret_fnam:
6563    if (property != vpiFile)
6564     { __notstrpropof_err(hrp->htyp, property); return(NULL); }
6565    strcpy(__wrk_vpiget_str, __in_fils[syp->syfnam_ind]);
6566    return(__wrk_vpiget_str);
6567   case vpiModPath: case vpiPathTerm:
6568    syp = hrp->hu.hpthp->pthsym;
6569    goto ret_fnam;
6570   /* scope def. handles */
6571   case vpiContAssign:
6572    if (hrp->htyp2 == vpiGate) syp = hrp->hu.hgp->gsym;
6573    else syp = hrp->hu.hcap->casym;
6574    goto ret_fnam;
6575   case vpiNamedBegin: case vpiNamedFork: case vpiTask: case vpiFunction:
6576    return(taskstrprop_vpiget(hp, property));
6577   case vpiAssignStmt: case vpiAssignment: case vpiBegin:
6578   case vpiCase: case vpiDeassign: case vpiDelayControl: case vpiEventControl:
6579   case vpiDisable: case vpiEventStmt: case vpiFor: case vpiForce:
6580   case vpiForever: case vpiFork: case vpiIf: case vpiIfElse: case vpiNullStmt:
6581   case vpiRelease: case vpiRepeat: case vpiWait: case vpiWhile:
6582    if (property != vpiFile)
6583     { __notstrpropof_err(hrp->htyp, property); return(NULL); }
6584    stp = hrp->hu.hstp;
6585    strcpy(__wrk_vpiget_str, __in_fils[stp->stfnam_ind]);
6586    return(__wrk_vpiget_str);
6587   case vpiOperation:
6588    /* Cver extension can get the name of operator (i.e. its symbol) */
6589    if (property != vpiName)
6590     { __notstrpropof_err(hrp->htyp, property); return(NULL); }
6591    pval = __expr_optype_get(hrp->hu.hxp);
6592    __to_vpiopchar(__wrk_vpiget_str, pval);
6593    return(__wrk_vpiget_str);
6594   case vpiDefParam:
6595    if (property != vpiFile)
6596     { __notstrpropof_err(hrp->htyp, property); return(NULL); }
6597    strcpy(__wrk_vpiget_str, __in_fils[hrp->hu.hdfp->dfpfnam_ind]);
6598    return(__wrk_vpiget_str);
6599   case vpiParamAssign:
6600    if (property != vpiFile)
6601     { __notstrpropof_err(hrp->htyp, property); return(NULL); }
6602 
6603    strcpy(__wrk_vpiget_str, __in_fils[hrp->hu.hnp->nsym->syfnam_ind]);
6604    return(__wrk_vpiget_str);
6605   case vpiAttribute:
6606    return(dig_attrstrpop_vpiget(hp, property));
6607 
6608   case vpiIODecl: return(iodeclstrprop_vpiget(hp, property));
6609   case vpiUdpDefn:
6610    if (property == vpiFile)
6611     {
6612      strcpy(__wrk_vpiget_str, __in_fils[hrp->hu.hudpp->usym->syfnam_ind]);
6613     }
6614    else if (property == vpiDefName)
6615     {
6616      strcpy(__wrk_vpiget_str, hrp->hu.hudpp->usym->synam);
6617     }
6618    else { __notstrpropof_err(hrp->htyp, property); return(NULL); }
6619    return(__wrk_vpiget_str);
6620   case vpiTableEntry:
6621    if (property != vpiFile)
6622     { __notstrpropof_err(hrp->htyp, property); return(NULL); }
6623    strcpy(__wrk_vpiget_str, __in_fils[hrp->hu.hutlp->utlfnam_ind]);
6624    return(__wrk_vpiget_str);
6625   default: __notstrpropof_err(hrp->htyp, property);
6626  }
6627  return(NULL);
6628 }
6629 
6630 /*
6631  * get string property values for module (inst. itree loc.)
6632  * copy to the one work string for these
6633  */
modstrprop_vpiget(struct h_t * hp,int32 prop)6634 static char *modstrprop_vpiget(struct h_t *hp, int32 prop)
6635 {
6636  struct mod_t *mdp;
6637  struct inst_t *ip;
6638 
6639  mdp = hp->hrec->hu.hmdp;
6640  ip = hp->hin_itp->itip;
6641  switch (prop) {
6642   case vpiName: strcpy(__wrk_vpiget_str, ip->isym->synam); break;
6643   case vpiFullName:
6644    strcpy(__wrk_vpiget_str, __msg2_blditree(__wrks1, hp->hin_itp));
6645    break;
6646   case vpiFile:
6647    strcpy(__wrk_vpiget_str, __in_fils[ip->isym->syfnam_ind]);
6648    break;
6649   case vpiDefName:
6650    strcpy(__wrk_vpiget_str, mdp->msym->synam);
6651    break;
6652   case vpiDefFile:
6653    strcpy(__wrk_vpiget_str, __in_fils[mdp->msym->syfnam_ind]);
6654    break;
6655   default: __notstrpropof_err(hp->hrec->htyp, prop); return(NULL);
6656  }
6657  return(__wrk_vpiget_str);
6658 }
6659 
6660 /*
6661  * emit not property of handle err
6662  *
6663  * know hp non nil or will not get here
6664  */
__notstrpropof_err(word32 typh,int32 prop)6665 extern void __notstrpropof_err(word32 typh, int32 prop)
6666 {
6667  __vpi_err(1875, vpiError,
6668   "string property %s not defined for vpi_get_str of %s",
6669   __to_vpipnam(__wrks1, prop), __to_vpionam(__wrks2, typh));
6670  strcpy(__wrk_vpiget_str, "");
6671 }
6672 
6673 /*
6674  * get string property values for net or array (and bits of)
6675  * copy to the one overwritten work string
6676  *
6677  * notice although strictly speaking a array is not a net str props the same
6678  */
netstrprop_vpiget(struct h_t * hp,int32 prop)6679 static char *netstrprop_vpiget(struct h_t *hp, int32 prop)
6680 {
6681  struct net_t *np;
6682  struct hrec_t *hrp;
6683 
6684  hrp = hp->hrec;
6685  if (hrp->htyp == vpiNetBit || hrp->htyp == vpiRegBit
6686   || hrp->htyp == vpiVarSelect || hrp->htyp == vpiMemoryWord
6687  )
6688   {
6689    if (hrp->bith_ndx) np = hrp->hu.hnp;
6690    else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
6691   }
6692  else np = hrp->hu.hnp;
6693 
6694  switch (prop) {
6695   case vpiFile:
6696    strcpy(__wrk_vpiget_str, __in_fils[np->nsym->syfnam_ind]);
6697    break;
6698   case vpiName: strcpy(__wrk_vpiget_str, np->nsym->synam); break;
6699   case vpiFullName:
6700    if (hrp->hin_tskp == NULL)
6701     sprintf(__wrk_vpiget_str, "%s.%s", __msg2_blditree(__wrks1, hp->hin_itp),
6702      np->nsym->synam);
6703    else sprintf(__wrk_vpiget_str, "%s.%s",
6704     __msg_blditree(__wrks1, hp->hin_itp, hrp->hin_tskp), np->nsym->synam);
6705    break;
6706   default: __notstrpropof_err(hrp->htyp, prop); return(NULL);
6707  }
6708  return(__wrk_vpiget_str);
6709 }
6710 
6711 /*
6712  * get string property values for gates
6713  * copy to the one overwritten work string
6714  *
6715  * LRM 98 removes vpiFullName property for ports
6716  */
portstrprop_vpiget(struct h_t * hp,int32 prop)6717 static char *portstrprop_vpiget(struct h_t *hp, int32 prop)
6718 {
6719  struct mod_t *mdp;
6720  struct mod_pin_t *mpp;
6721 
6722  mdp = hp->hin_itp->itip->imsym->el.emdp;
6723  mpp = &(mdp->mpins[hp->hrec->hu.hpi]);
6724  switch (prop) {
6725   case vpiFile:
6726    strcpy(__wrk_vpiget_str, __in_fils[mpp->mpfnam_ind]);
6727    break;
6728   case vpiName:
6729    if (mpp->mpsnam == NULL) return(NULL);
6730    return(mpp->mpsnam);
6731   default: __notstrpropof_err(hp->hrec->htyp, prop); return(NULL);
6732  }
6733  return(__wrk_vpiget_str);
6734 }
6735 
6736 /*
6737  * get string property values for gates
6738  * copy to the one overwritten work string
6739  */
gatestrprop_vpiget(struct h_t * hp,int32 prop)6740 static char *gatestrprop_vpiget(struct h_t *hp, int32 prop)
6741 {
6742  struct gate_t *gp;
6743 
6744  gp = hp->hrec->hu.hgp;
6745  switch (prop) {
6746   case vpiDefName:
6747    strcpy(__wrk_vpiget_str, gp->gmsym->synam);
6748    break;
6749   case vpiFile:
6750    strcpy(__wrk_vpiget_str, __in_fils[gp->gsym->syfnam_ind]);
6751    break;
6752   case vpiName: strcpy(__wrk_vpiget_str, gp->gsym->synam); break;
6753   case vpiFullName:
6754     sprintf(__wrk_vpiget_str, "%s.%s", __msg2_blditree(__wrks1,
6755      hp->hin_itp), gp->gsym->synam);
6756    break;
6757   default: __notstrpropof_err(hp->hrec->htyp, prop); return(NULL);
6758  }
6759  return(__wrk_vpiget_str);
6760 }
6761 
6762 /*
6763  * get string property values for task call
6764  * copy to the one overwritten work string
6765  */
tcallstrprop_vpiget(struct h_t * hp,int32 prop)6766 static char *tcallstrprop_vpiget(struct h_t *hp, int32 prop)
6767 {
6768  struct st_t *stp;
6769 
6770  stp = hp->hrec->hu.hstp;
6771  switch (prop) {
6772   case vpiFile:
6773    strcpy(__wrk_vpiget_str, __in_fils[stp->stfnam_ind]);
6774    break;
6775   case vpiName:
6776    strcpy(__wrk_vpiget_str, stp->st.stkc.tsksyx->lu.sy->synam);
6777    break;
6778   default: __notstrpropof_err(hp->hrec->htyp, prop); return(NULL);
6779  }
6780  return(__wrk_vpiget_str);
6781 }
6782 
6783 /*
6784  * get string property values for function call
6785  * copy to the one overwritten work string
6786  *
6787  * LOOKATME - for compatibility making location: unkown 0?
6788  */
fcallstrprop_vpiget(struct h_t * hp,int32 prop)6789 static char *fcallstrprop_vpiget(struct h_t *hp, int32 prop)
6790 {
6791  struct hrec_t *hrp;
6792 
6793  hrp = hp->hrec;
6794  switch (prop) {
6795   case vpiFile:
6796    __vpi_err(2112, vpiNotice,
6797     "vpiFile call location property not saved for vpiFuncCall or vpiSysFuncCall - [unknown] returned");
6798    strcpy(__wrk_vpiget_str, "[Unknown]");
6799    break;
6800   case vpiName:
6801    strcpy(__wrk_vpiget_str, hrp->hu.hxp->lu.x->lu.sy->synam);
6802    break;
6803   default: __notstrpropof_err(hrp->htyp, prop); return(NULL);
6804  }
6805  return(__wrk_vpiget_str);
6806 }
6807 
6808 /*
6809  * get string property values for func/task declaration (scope not call)
6810  *
6811  * copy to the one overwritten work string
6812  * also named begin or fork
6813  */
taskstrprop_vpiget(struct h_t * hp,int32 prop)6814 static char *taskstrprop_vpiget(struct h_t *hp, int32 prop)
6815 {
6816  struct task_t *tskp;
6817 
6818  tskp = hp->hrec->hu.htskp;
6819  switch (prop) {
6820   case vpiName:
6821    strcpy(__wrk_vpiget_str, tskp->tsksyp->synam);
6822    break;
6823   case vpiFullName:
6824    sprintf(__wrk_vpiget_str, "%s.%s", __msg2_blditree(__wrks1, hp->hin_itp),
6825     tskp->tsksyp->synam);
6826    break;
6827   case vpiFile:
6828    strcpy(__wrk_vpiget_str, __in_fils[tskp->tsksyp->syfnam_ind]);
6829    break;
6830   default: __notstrpropof_err(hp->hrec->htyp, prop); return(NULL);
6831  }
6832  return(__wrk_vpiget_str);
6833 }
6834 
6835 /*
6836  * get string property values for io decl
6837  * copy to the one overwritten work string
6838  */
iodeclstrprop_vpiget(struct h_t * hp,int32 prop)6839 static char *iodeclstrprop_vpiget(struct h_t *hp, int32 prop)
6840 {
6841  struct hrec_t *hrp;
6842 
6843  hrp = hp->hrec;
6844  switch (prop) {
6845   case vpiName:
6846    if (hrp->htyp2 == vpiUdpDefn)
6847     {
6848      /* DBG remove -- */
6849      if (hrp->hu.hmpp->mpsnam == NULL) __arg_terr(__FILE__, __LINE__);
6850      /* --- */
6851      strcpy(__wrk_vpiget_str, hrp->hu.hmpp->mpsnam);
6852     }
6853    else strcpy(__wrk_vpiget_str, hrp->hu.hnp->nsym->synam);
6854    break;
6855   case vpiFile:
6856    if (hrp->htyp2 == vpiUdpDefn)
6857     strcpy(__wrk_vpiget_str, __in_fils[hrp->hu.hmpp->mpfnam_ind]);
6858    else strcpy(__wrk_vpiget_str, __in_fils[hrp->hu.hnp->nsym->syfnam_ind]);
6859    break;
6860   default: __notstrpropof_err(hrp->htyp, prop); return(NULL);
6861  }
6862  return(__wrk_vpiget_str);
6863 }
6864 
6865 /*
6866  * get string property values for digital attribute
6867  * copy to the one overwritten work string
6868  */
dig_attrstrpop_vpiget(struct h_t * hp,int32 prop)6869 static char *dig_attrstrpop_vpiget(struct h_t *hp, int32 prop)
6870 {
6871  struct attr_t *attrp;
6872 
6873  switch (prop) {
6874   case vpiName:
6875    /* this can't fail */
6876    attrp = __find_attrspec(hp);
6877    strcpy(__wrk_vpiget_str, attrp->attrnam);
6878    break;
6879   default: __notstrpropof_err(hp->hrec->htyp, prop); return(NULL);
6880  }
6881  return(__wrk_vpiget_str);
6882 }
6883