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