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  * 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 int32 chk_delay_num(char *, struct h_t *, int32, struct gate_t *);
50 static int32 fillchk_tim(word64 *, int32 *, p_vpi_delay, struct itree_t *);
51 static void fill_vpi_delay(p_vpi_delay, word64 *, int32, word32,
52  struct mod_t *);
53 
54 static void get_varorparam_val(struct h_t *, p_vpi_value);
55 static void stscal_fill_valuep(p_vpi_value, register byte *, int32);
56 static void stvec_fill_valuep(p_vpi_value, register byte *, int32);
57 static void get_var_bit(struct h_t *, p_vpi_value);
58 static void get_arrwrd_val(struct h_t *, p_vpi_value);
59 static void get_expr_val(struct h_t *, p_vpi_value);
60 static int32 valp_stren_err(struct hrec_t *, p_vpi_value);
61 static void get_primterm_val(struct h_t *, p_vpi_value);
62 static void get_vpisfcall_retval(struct h_t *, p_vpi_value);
63 static void get_vpiudpdefn_val(struct h_t *, p_vpi_value);
64 static void get_vpitabentry_val(struct h_t *, p_vpi_value);
65 static void get_vpi_netdrv_val(struct h_t *, p_vpi_value);
66 static struct xstk_t *push_vpi_drv_val(struct h_t *, struct net_t **);
67 static void get_vpi_netbitdrv_val(struct h_t *, p_vpi_value);
68 static struct xstk_t *push_vpi_bitdrv_val(struct h_t *, struct net_t **);
69 static void get_gate_drv_valuep(struct h_t *, p_vpi_value, struct gate_t *);
70 static void get_vpiconta_drv_valuep(struct h_t *, p_vpi_value,
71  struct conta_t *);
72 static void get_vpiport_drv_valuep(struct h_t *, p_vpi_value,
73  struct mod_pin_t *);
74 static void get_vpiportbit_drv_valuep(struct h_t *, p_vpi_value,
75  struct mod_pin_t *, int32);
76 static void get_vpi_attrval(struct h_t *, p_vpi_value);
77 
78 static void correct_objtypval(p_vpi_value, word32, word32, word32, int32);
79 static void expr_correct_objtypval(struct expr_t *, p_vpi_value);
80 static void fill_valuep(p_vpi_value, struct xstk_t *xsp, word32, int32);
81 static void wrkval_grow(int32);
82 static void udp_line_to_str(char *, struct udp_t *, struct utline_t *);
83 static int32 putv_in_future(word32, p_vpi_time);
84 static int32 chk_putv_args(word32, struct h_t *, p_vpi_value);
85 static char *putv_flag_to_str(char *, word32);
86 static int32 net_ongetpat_lhs(struct net_t *);
87 static int32 good_value_p(p_vpi_value);
88 static void free_putv_sched(struct h_t *);
89 static void free_regwir_putv_sched(struct net_t *, struct itree_t *,
90  i_tev_ndx);
91 static void free_netbitdrv_putv_sched(struct net_t *, int32, struct itree_t *,
92  i_tev_ndx);
93 static struct h_t *add_net_driver(struct h_t *);
94 static struct h_t *add_netbit_driver(struct h_t *);
95 static struct vpi_drv_t *alloc_vpidrv(struct net_t *, int32);
96 static void putv_drvwp_allocinit(struct mod_t *, struct net_t *,
97  struct vpi_drv_t *, int32);
98 static void chg_net_to_multfi(struct net_t *, struct mod_t *);
99 static int32 get_vpibit_index(struct net_t **np, struct h_t *);
100 static struct xstk_t *push_vpi_valuep(p_vpi_value, int32, word32, int32);
101 static void reg_vpi_force(register struct net_t *, word32 *, word32 *);
102 static void reg_vpi_release(register struct net_t *);
103 static void wire_vpi_force(register struct net_t *, word32 *, word32 *,
104  register int32);
105 static void wire_vpi_release(struct net_t *, int32);
106 static void set_vpisfcall_retval(struct h_t *, p_vpi_value);
107 static void set_vpiparam_val(struct h_t *, p_vpi_value);
108 static void set_vpiudpdef_ival(struct h_t *, p_vpi_value);
109 static void immed_vpi_drv_assign(struct net_t *np, int32, word32 *, word32 *);
110 static void immed_vpibit_drv_assign(struct net_t *np, int32, int32, word32 *,
111  word32 *);
112 static void emit_vpiputv_evtrmsg(struct net_t *, struct teputv_t *, int32);
113 static void exec_putv_reg_assign(register struct net_t *, register word32 *,
114  register word32 *, register int32);
115 static void exec_putv_wire_softforce(register struct net_t *, register word32 *,
116  register word32 *, register int32);
117 static struct h_t *setschd_var_fromvaluep(p_vpi_value, struct net_t *, int32,
118  word64, byte, int32);
119 static void emit_vpiputv_schd_trmsg(struct net_t *, struct xstk_t *,
120  struct dltevlst_t *, word64 *, int32, char *);
121 static void bld_regwir_putvrec(struct net_t *);
122 static void cancel_vpievents_toend(struct net_t *, struct dltevlst_t *, int32);
123 static struct h_t *setschd_drvr_fromvaluep(p_vpi_value, struct h_t *, word64,
124  byte, int32);
125 static i_tev_ndx setschd_1bit_drvr(struct net_pin_t *, int32, struct xstk_t *,
126  word64, byte);
127 static int32 chk_vpi_logicval(word32);
128 static int32 bld_vpinewdu(struct gate_t *, struct gate_t *, p_vpi_delay,
129  struct itree_t *, int32, int32);
130 static int32 do_vpi_iact_scopchg(vpiHandle);
131 static int32 do_vpi_cb_onoff(vpiHandle, int32);
132 static void init_pli_einfo(struct t_vpi_error_info *, int32, int32);
133 static int32 to_vpierr_level(int32);
134 
135 
136 /* extern prototypes (maybe defined in this module) */
137 extern struct mipd_t *__get_mipd_from_port(struct mod_pin_t *, int32);
138 extern void __set_vpi_time(struct t_vpi_time *, word64 *, int32, struct mod_t *);
139 extern int32 __get_vpinet_index(struct net_t **, struct h_t *);
140 extern int32 __vpitime_to_ticks(word64 *, p_vpi_time, struct mod_t *);
141 extern void __reinit_regwir_putvrec(struct net_t *, int32);
142 extern void __reinit_netdrvr_putvrec(struct net_t *, struct mod_t *);
143 extern void __process_vpi_varputv_ev(i_tev_ndx);
144 extern void __process_vpidrv_ev(i_tev_ndx);
145 extern void __pli_dofinish(int32, char *);
146 extern void __reinit_vpi(void);
147 extern void __dmp_listof_handles(struct h_t *);
148 extern char *__to_vpionam(char *, word32);
149 extern int32 __validate_otyp(word32);
150 extern char *__to_vpiopnam(char *, int32);
151 extern char *__to_vpiopchar(char *, int32);
152 extern void __sim_notbegun_err(char *);
153 extern void __still_comp_err(char *);
154 extern void __bad_rosync_err(char *);
155 extern int32 __validate_handle(char *, register struct h_t *);
156 extern int32 __validate_nonit_handle(char *, struct h_t *);
157 extern int32 __validate_accessm(char *, int32, char *);
158 extern int32 __validate_time_type(char *, int32);
159 extern int32 __validate_value_fmt(char *, int32);
160 extern void __free_iterator(vpiHandle);
161 extern void __free_hp(struct h_t *);
162 
163 extern vpiHandle __mk_handle(word32, void *, struct itree_t *,
164  struct task_t *);
165 extern int32 __get_arrwide(struct net_t *);
166 extern char *__msg2_blditree(char *, struct itree_t *);
167 extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
168 extern void __extract_delval(word64 *, int32 *, union del_u, word32);
169 extern char *__to_tcnam(char *, word32);
170 extern void __fill_16vconst(word64 *, word64 *, int32);
171 extern void __map_16v_to_12vform(word64 *, word64 *);
172 extern int32 __v64_to_real(double *, word64 *);
173 extern char *__to_timstr(char *, word64 *);
174 extern int32 __add_gate_pnd0del(struct gate_t *, struct mod_t *, char *);
175 extern void __chg_1inst_del(struct gate_t *, struct itree_t *, struct gate_t *);
176 extern void __free_del(union del_u, word32, int32);
177 extern char *__to_mpnam(char *, char *);
178 extern void __add_alloc_mipd_npp(struct net_t *, struct mod_t *);
179 extern void __setup_mipd(struct mipd_t *, struct net_t *, int32);
180 extern int32 __add_conta_pnd0del(struct conta_t *, struct mod_t *, char *);
181 extern void __fill_4vconst(word64 *, word64 *, word64 *, word64 *, int32, int32);
182 extern int32 __real_to_v64tim(word64 *, double);
183 extern void __grow_xstk(void);
184 extern void __chg_xstk_width(struct xstk_t *, int32);
185 extern void __grow_tevtab(void);
186 extern void __ld_wire_val(register word32 *, register word32 *, struct net_t *);
187 extern void __ld_bit(register word32 *, register word32 *,
188  register struct net_t *, int32);
189 extern void __ld_stval(register word32 *, register word32 *, register byte *, int32);
190 extern void __lhsbsel(register word32 *, register int32, word32);
191 extern struct xstk_t *__eval2_xpr(register struct expr_t *);
192 extern struct xstk_t *__ndst_eval_xpr(struct expr_t *);
193 extern void __ld_arr_val(register word32 *, register word32 *, union pck_u,
194  int32, int32, int32);
195 extern void __cnv_stk_fromreal_toreg32(struct xstk_t *);
196 extern void __regab_disp(word32 *, word32 *, int32, int32, int32, int32);
197 extern char *__to_wtnam(char *, struct net_t *);
198 extern char *__to_wtnam2(char *, word32);
199 extern void __cnv_stk_fromreg_toreal(struct xstk_t *, int32);
200 extern char *__alloc_vval_to_cstr(word32 *, int32, int32, int32);
201 extern struct xstk_t *__cstr_to_vval(char *);
202 extern int32 __wide_vval_is0(register word32 *, int32);
203 extern int32 __vval_is1(register word32 *, int32);
204 extern char *__my_realloc(char *, int32, int32);
205 extern void __my_free(char *, int32);
206 extern char *__my_malloc(int32);
207 extern int32 __unnormalize_ndx(struct net_t *, int32);
208 extern struct dltevlst_t *__spliceout_last(register struct dltevlst_t *);
209 extern struct dltevlst_t *__find_last_bdltevp(register struct dltevlst_t *,
210  word64);
211 extern void __insert_event(register i_tev_ndx);
212 extern struct xstk_t *__putdstr_to_val(char *, int32, int32, int32);
213 extern double __cnvt_stk_to_real(struct xstk_t *, int32);
214 extern void __sizchgxs(register struct xstk_t *, int32);
215 extern struct net_pin_t *__alloc_npin(int32, int32, int32);
216 extern int32 __get_pcku_chars(int32, int32);
217 extern void __st_perinst_val(union pck_u, int32, register word32 *,
218  register word32 *);
219 extern void __vpi_set_chg_proc(struct gate_t *);
220 extern void __allocinit_perival(union pck_u *, int32, int32, int32);
221 extern void __vpi_set_upiconnport_proc(struct mod_pin_t *);
222 extern void __vpi_set_downtomdport_proc(struct mod_pin_t *, struct net_t *);
223 extern void __alloc_tfdrv_wp(struct tfarg_t *, struct expr_t *, struct mod_t *);
224 extern void __chg_st_arr_val(union pck_u, int32, int32, int32, register word32 *,
225  register word32 *);
226 extern void __st_arr_val(union pck_u, int32, int32, int32, register word32 *,
227  register word32 *);
228 extern void __chg_st_val(struct net_t *, register word32 *, register word32 *);
229 extern void __st_val(struct net_t *, register word32 *, register word32 *);
230 extern void __chg_st_bit(struct net_t *, int32, register word32, register word32);
231 extern void __st_bit(struct net_t *, int32, register word32, register word32);
232 extern int32 __correct_forced_newwireval(struct net_t *, word32 *, word32 *);
233 extern void __ld_perinst_val(register word32 *, register word32 *,
234  union pck_u, int32);
235 extern word32 __ld_gate_out(register struct gate_t *, int32 *);
236 extern word32 __ld_gate_in(struct gate_t *, int32, int32 *);
237 extern int32 __update_tran_harddrvs(struct net_t *);
238 extern void __tran_wire_vpi_force(struct net_t *, word32 *, word32 *, int32);
239 extern void __tran_wire_vpi_release(struct net_t *, int32);
240 extern void __tran_exec_putv_wire_softforce(struct net_t *, word32 *, word32 *,
241  int32);
242 
243 extern void __eval_tran_bits(register struct net_t *);
244 extern void __eval_tran_1bit(register struct net_t *, register int32);
245 extern void __sched_1mdrwire(register struct net_t *);
246 extern void __assign_1mdrwire(register struct net_t *);
247 extern char *__st_regab_tostr(char *, byte *, int32);
248 extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
249 extern void __evtr_resume_msg(void);
250 extern void __chg_param_tois(struct net_t *, struct mod_t *);
251 extern void __re_prep_dels(struct net_t *, struct itree_t *, struct mod_t *,
252  int32);
253 extern void __alloc_qcval(struct net_t *);
254 extern void __find_call_force_cbs(struct net_t *, int32);
255 extern void __cb_all_rfs(struct net_t *, int32, int32);
256 extern void __do_qc_store(struct net_t *, struct qcval_t *, int32);
257 extern void __find_call_rel_cbs(struct net_t *, int32);
258 extern void __st_standval(register byte *, register struct xstk_t *, byte);
259 extern char *__pv_stralloc(char *);
260 extern word32 __mc1_fopen(char *, int32, int32);
261 extern word32 __close_mcd(word32, int32);
262 extern void __free_xtree(struct expr_t *);
263 extern void __vpi_plierror_trycall(void);
264 extern char *__to_vpipnam(char *, int32);
265 extern void __bld_vpi_argv(void);
266 extern int32 __em_suppr(int32);
267 extern int32 __do_vpi_stop(int32);
268 extern void __do_vpi_reset(int32, int32, int32);
269 extern void __call_misctfs_scope(void);
270 extern void __vpi_iactscopechg_trycall(void);
271 extern char *__match_cdir(char *, char *);
272 extern int32 __exec_rdinserted_src(char *);
273 extern int32 __comp_ndx(register struct net_t *, register struct expr_t *);
274 extern int32 __expr_is_vpiconst(struct expr_t *);
275 extern word32 __map_tovpi_stren(word32);
276 extern int32 __map_frvpi_stren(int32);
277 extern struct expr_t *__sim_copy_expr(struct expr_t *);
278 extern void __exec_dumpvars(struct expr_t *);
279 extern void __my_dv_flush(void);
280 extern void __push_wrkitstk(struct mod_t *, int32);
281 extern void __pop_wrkitstk(void);
282 extern int32 __chk_showobj(struct h_t *, int32 *, int32 *);
283 extern word32 __to_vpi_tasktyp(word32);
284 extern int32 __my_vpi_chk_error(void);
285 extern struct attr_t *__find_attrspec(struct h_t *);
286 extern int32 __move_to_npprefloc(struct net_pin_t *);
287 extern void __add_nchglst_el(register struct net_t *);
288 extern void __add_select_nchglst_el(register struct net_t *, register int32,
289  register int32);
290 extern void __wakeup_delay_ctrls(register struct net_t *, register int32,
291  register int32);
292 extern void __add_dmpv_chglst_el(struct net_t *);
293 extern char *__cb_reason_to_nam(char *, int32);
294 extern void __bit1_vpi_or_tran_wireforce(struct net_t *, word32 *, word32 *, int32,
295  int32, int32, char *);
296 extern struct tenp_t *__bld_portbit_netbit_map(struct mod_pin_t *);
297 extern int32 __trim1_0val(word32 *, int32);
298 extern void __sgn_xtnd_widen(struct xstk_t *, int32);
299 extern void __sizchg_widen(register struct xstk_t *, int32);
300 
301 extern int32 __fd_do_fclose(int32);
302 
303 extern void __my_fprintf(FILE *, char *, ...);
304 extern void __tr_msg(char *, ...);
305 extern void __dbg_msg(char *, ...);
306 extern void __arg_terr(char *, int32);
307 extern void __pv_terr(int32, char *, ...);
308 extern void __misc_terr(char *, int32);
309 
310 extern void __vpi_terr(char *, int32);
311 extern void __vpi_err(int32, int32, char *, ...);
312 
313 extern word32 __masktab[];
314 extern double __dbl_toticks_tab[];
315 
316 /* vpi only storage that is defined here */
317 struct t_vpi_error_info __wrk_einfo;/* if err, vpi routine fills this */
318 struct t_vpi_error_info *__last_eip;/* if err, ptr to wrk eifo or nil */
319 
320 /*
321  * ROUTINES FOR ACCESSING DELAYS
322  */
323 
324 /*
325  * get a delay
326  *
327  * convention for pulsere flag is to use delay for other 2
328  */
vpi_get_delays(vpiHandle object,p_vpi_delay delay_p)329 extern void vpi_get_delays(vpiHandle object, p_vpi_delay delay_p)
330 {
331  register int32 di, di2;
332  int32 ndels, nrep, ndx;
333  word32 getdrep;
334  word64 tim[12], timval;
335  struct mod_t *mdp;
336  struct h_t *hp;
337  struct gate_t *gp, ogat;
338  struct mod_pin_t *mpp;
339  struct net_t *np;
340  struct conta_t *cap;
341  struct tchk_t *tcp;
342  struct spcpth_t *pthp;
343  struct delctrl_t *dctp;
344  union del_u getdu;
345  struct t_vpi_delay tmpdel;
346  struct t_vpi_time tmpda[12];
347  struct hrec_t *hrp;
348  struct mipd_t *mipdp;
349 
350  if (__run_state == SS_COMP)
351   { __still_comp_err("vpi_get_delays"); return; }
352  hp = (struct h_t *) object;
353  if (!__validate_handle("vpi_get_delays", hp)) return;
354  hrp = hp->hrec;
355  nrep = 1;
356  if (delay_p->pulsere_flag)
357   {
358    __vpi_err(2107, vpiNotice,
359     "vpi_get_delays pulsere_flag values not supported - both same as delay");
360    /* still must access from callers description */
361    nrep *= 3;
362   }
363  if (delay_p->mtm_flag)
364   {
365    __vpi_err(2108, vpiNotice,
366     "vpi_get_delays mtm_flag set but min-typ-max values not supported - all 3 same");
367    nrep *= 3;
368   }
369  /* on error here, user must call error check routine */
370  /* can access delays for any run state but still compiling */
371  if (!chk_delay_num("vpi_get_delays", hp, delay_p->no_of_delays, &ogat))
372   return;
373 
374  /* must extract using exact properties from passed vpi_delay */
375  tmpdel = *delay_p;
376  tmpdel.da = &(tmpda[0]);
377 
378  __push_itstk(hp->hin_itp);
379  /* need module type since need to scale delay */
380  mdp = hp->hin_itp->itip->imsym->el.emdp;
381  /* assume if handle created, good - fill the delay union */
382  switch (hrp->htyp) {
383   case vpiGate: case vpiUdp: case vpiSwitch:
384    gp = hrp->hu.hgp;
385    getdu = gp->g_du;
386    getdrep = gp->g_delrep;
387    break;
388   case vpiPort: case vpiPortBit:
389    mpp = &(mdp->mpins[hrp->hu.hpi]);
390    if (hrp->htyp == vpiPort && mpp->mpwide != 1)
391     {
392      __vpi_err(2109, vpiNotice,
393       "vpi_get_delays of non scalar vpiPort (for MIPD) using low bit");
394     }
395    if (!mpp->has_mipd) { getdu.d1v = NULL; getdrep = DT_NONE; }
396    else
397     {
398      if (hrp->htyp == vpiPort) ndx = 0; else ndx = hrp->hi;
399      mipdp = __get_mipd_from_port(mpp, ndx);
400      getdu = mipdp->pb_mipd_du;
401      getdrep = mipdp->pb_mipd_delrep;
402     }
403    break;
404   case vpiNet:
405    np = hrp->hu.hnp;
406    /* can check for no delay with property */
407    if (np->nrngrep == NX_DWIR)
408     { getdu = np->nu.rngdwir->n_du; getdrep = np->nu.rngdwir->n_delrep; }
409    else { getdu.d1v = NULL; getdrep = DT_NONE; }
410    break;
411   case vpiContAssign:
412    if (hrp->htyp2 == vpiGate)
413     { gp = hrp->hu.hgp; getdu = gp->g_du; getdrep = gp->g_delrep; }
414    else { cap = hrp->hu.hcap; getdu = cap->ca_du; getdrep = cap->ca_delrep; }
415    break;
416   case vpiTchk:
417    tcp = hrp->hu.htcp;
418    /* know always at least one delay */
419    getdu = tcp->tclim_du;
420    getdrep = tcp->tc_delrep;
421    /* know limit is present */
422    if (getdrep == DT_NONE) __vpi_terr(__FILE__, __LINE__);
423    __extract_delval(tim, &ndels, getdu, getdrep);
424    if (ndels != 1) __vpi_terr(__FILE__, __LINE__);
425    __set_vpi_time(&(tmpdel.da[0]), &(tim[0]), delay_p->time_type, mdp);
426    if (tcp->tc_haslim2 && delay_p->no_of_delays == 2)
427     {
428      getdu = tcp->tclim2_du;
429      __extract_delval(tim, &ndels, getdu, getdrep);
430      if (ndels != 1) __vpi_terr(__FILE__, __LINE__);
431      __set_vpi_time(&(tmpdel.da[1]), &(tim[0]), delay_p->time_type, mdp);
432     }
433    __pop_itstk();
434    goto done;
435   case vpiModPath:
436    pthp = hrp->hu.hpthp; getdu = pthp->pth_du; getdrep = pthp->pth_delrep;
437    break;
438   /* procedural delays */
439   case vpiAssignment:
440    dctp = hrp->hu.hstp->st.sdc;
441    if (dctp->dctyp != DC_RHSDELAY)
442     {
443      __vpi_err(1882, vpiError,
444       "vpi_get_delays of vpiAssignment right hand side delay control impossible - no delay control");
445      __pop_itstk();
446      goto done;
447     }
448    getdu = dctp->dc_du;
449    getdrep = dctp->dc_delrep;
450    break;
451   case vpiDelayControl:
452    dctp = hrp->hu.hstp->st.sdc;
453    /* DBG remove --- */
454    if (dctp->dctyp != DC_DELAY) __vpi_terr(__FILE__, __LINE__);
455    /* --- */
456    getdu = dctp->dc_du;
457    getdrep = dctp->dc_delrep;
458    break;
459   /* will not get to case if not element with delay */
460   default: __vpi_terr(__FILE__, __LINE__); goto done;
461  }
462  if (getdrep == DT_NONE)
463   {
464    __vpi_err(2009, vpiWarning,
465     "vpi_get_delays for object %s that has no delay - value(s) 0 but not #0",
466     __to_vpionam(__wrks1, hrp->htyp));
467    timval = 0ULL;
468    for (di = 0; di < delay_p->no_of_delays; di++)
469     __set_vpi_time(&(tmpdel.da[di]), &timval, delay_p->time_type, mdp);
470    __pop_itstk();
471    goto done;
472   }
473  __extract_delval(tim, &ndels, getdu, getdrep);
474  /* this may emit warning that can be checked by calling vpi check */
475  fill_vpi_delay(&tmpdel, tim, ndels, hrp->htyp, mdp);
476  __pop_itstk();
477 
478 done:
479  /* final step is copying back into user supplied delay p from tmp */
480  for (di = 0; di < delay_p->no_of_delays; di++)
481   {
482    for (di2 = 0; di2 < nrep; di2++)
483     delay_p->da[nrep*di + di2] = tmpdel.da[di];
484   }
485 }
486 
487 /*
488  * routine to check that right number of delays passed for object type
489  *
490  * also checks for object (handle) that can have delay and fill ogp with del
491  * if return T
492  */
chk_delay_num(char * rnam,struct h_t * hp,int32 numdels,struct gate_t * ogp)493 static int32 chk_delay_num(char *rnam, struct h_t *hp, int32 numdels,
494  struct gate_t *ogp)
495 {
496  int32 ndx;
497  struct gate_t *gp;
498  struct conta_t *cap;
499  struct mod_t *mdp;
500  struct mod_pin_t *mpp;
501  struct mipd_t *mipdp;
502  struct net_t *np;
503  struct tchk_t *tcp;
504  struct spcpth_t *pthp;
505  struct delctrl_t *dctp;
506  struct hrec_t *hrp;
507 
508  hrp = hp->hrec;
509  switch (hrp->htyp) {
510   case vpiGate: case vpiUdp: case vpiSwitch:
511    gp = hrp->hu.hgp;
512    ogp->g_du = gp->g_du;
513    ogp->g_delrep = gp->g_delrep;
514 chk_prim_num:
515    if (numdels != 1 && numdels != 2 && numdels != 3)
516     {
517      __vpi_err(1881, vpiError,
518       "%s called for object %s delay number %d wrong - must be 1, 2 or 3",
519       rnam, __to_vpionam(__wrks1, hrp->htyp), numdels);
520      return(FALSE);
521     }
522    break;
523   case vpiContAssign:
524    if (hrp->htyp2 == vpiGate)
525     {
526      gp = hrp->hu.hgp;
527      ogp->g_du = gp->g_du;
528      ogp->g_delrep = gp->g_delrep;
529     }
530    else
531     {
532      cap = hrp->hu.hcap;
533      ogp->g_du = cap->ca_du;
534      ogp->g_delrep = cap->ca_delrep;
535     }
536    goto chk_prim_num;
537   case vpiNet:
538    np = hrp->hu.hnp;
539    if (np->nrngrep == NX_DWIR)
540     {
541      ogp->g_du = np->nu.rngdwir->n_du;
542      ogp->g_delrep = np->nu.rngdwir->n_delrep;
543     }
544    else { ogp->g_du.d1v = NULL; ogp->g_delrep = DT_NONE; }
545    goto chk_prim_num;
546   case vpiPort: case vpiPortBit:
547    /* MIPD delays for vector vpiPortBit, if vpiPort use low bit with note */
548    /* notice check for input or inout port handled below */
549    mdp = hp->hin_itp->itip->imsym->el.emdp;
550    mpp = &(mdp->mpins[hrp->hu.hpi]);
551    if (mpp->mptyp != IO_IN && mpp->mptyp != IO_BID)
552     {
553      __vpi_err(2023, vpiWarning,
554       "vpi_get_delays of non input or inout %s - no values returned since no MIPD possible",
555       __to_vpionam(__wrks1, hrp->htyp));
556      return(FALSE);
557     }
558    if (!mpp->has_mipd) { ogp->g_du.d1v = NULL; ogp->g_delrep = DT_NONE; }
559    else
560     {
561      if (hrp->htyp == vpiPort) ndx = 0; else ndx = hrp->hi;
562      mipdp = __get_mipd_from_port(mpp, ndx);
563      ogp->g_du = mipdp->pb_mipd_du;
564      ogp->g_delrep = mipdp->pb_mipd_delrep;
565     }
566    /* SJM 10/28/99 - 12 delay values now possible for MIPDs */
567    if (!(numdels == 1 || numdels == 2 || numdels == 3 || numdels == 6
568     || numdels == 12))
569     {
570      __vpi_err(1881, vpiError,
571       "%s called for object %s delay number %d wrong - must be 1, 2, 3, 6, or 12",
572       rnam, __to_vpionam(__wrks1, hrp->htyp), numdels);
573      return(FALSE);
574     }
575    break;
576   case vpiModPath:
577    if (!(numdels == 1 || numdels == 2 || numdels == 3 || numdels == 6
578     || numdels == 12))
579     {
580      __vpi_err(1881, vpiError,
581       "%s called for object %s delay number %d wrong - must be 1, 2, 3, 6, or 12",
582       rnam, __to_vpionam(__wrks1, hrp->htyp), numdels);
583      return(FALSE);
584     }
585    pthp = hrp->hu.hpthp;
586    ogp->g_du = pthp->pth_du;
587    ogp->g_delrep = pthp->pth_delrep;
588    break;
589   case vpiTchk:
590    tcp = hrp->hu.htcp;
591    /* different delay unions but type must be the same */
592    ogp->g_du = tcp->tclim_du;
593    ogp->g_delrep = tcp->tc_delrep;
594    if (numdels != 1 && numdels != 2)
595     {
596      __vpi_err(1889, vpiError,
597       "%s called for object %s %s delay number %d wrong - must be 1 or 2",
598       rnam, __to_tcnam(__wrks2, tcp->tchktyp), __to_vpionam(__wrks1,
599       hrp->htyp), numdels);
600      return(FALSE);
601     }
602    if (tcp->tc_haslim2)
603     {
604      if (numdels != 2)
605       {
606        __vpi_err(2021, vpiWarning,
607         "%s called for object %s %s delay number %d wrong - missing 2nd omitted",
608         rnam, __to_tcnam(__wrks2, tcp->tchktyp), __to_vpionam(__wrks1,
609         hrp->htyp), numdels);
610       }
611     }
612    else
613     {
614      if (numdels != 1)
615       {
616        __vpi_err(2021, vpiWarning,
617         "%s called for object %s %s delay number %d wrong - only 1 returned or set",
618         rnam, __to_tcnam(__wrks2, tcp->tchktyp), __to_vpionam(__wrks1,
619         hrp->htyp), numdels);
620       }
621     }
622    break;
623   /* procedural delays */
624   case vpiAssignment: case vpiDelayControl:
625    dctp = hrp->hu.hstp->st.sdc;
626    if (numdels != 1)
627     {
628      __vpi_err(1881, vpiError,
629       "%s called for procedural object %s delay number %d wrong - must be 1",
630       rnam, __to_vpionam(__wrks1, hrp->htyp), numdels);
631      return(FALSE);
632     }
633    ogp->g_du = dctp->dc_du;
634    ogp->g_delrep = dctp->dc_delrep;
635    break;
636   default:
637    __vpi_err(1883, vpiError, "object %s does not have delays",
638     __to_vpionam(__wrks1, hrp->htyp));
639    return(FALSE);
640  }
641  return(TRUE);
642 }
643 
644 /*
645  * given an extracted tim array, vpi_ delay
646  *
647  * extraction produces smallest possible number if any identical values
648  * nvals can be 1, 2, 3, 6, or 12 and gives number of tim[] filled
649  *
650  * 2 delays (nvals) now happens for logic gates and UDPs
651  * for 6 and 16, order is 0-1 (a rise), 1-0 (a fall), 0-z (a toz)
652  * so can just use
653  * delay_p can need 1,2,3,6,12
654  */
fill_vpi_delay(p_vpi_delay delay_p,word64 * tim,int32 nvals,word32 otyp,struct mod_t * mdp)655 static void fill_vpi_delay(p_vpi_delay delay_p, word64 *tim, int32 nvals,
656  word32 otyp, struct mod_t *mdp)
657 {
658  register int32 di;
659  word64 ntim[16];
660 
661  /* if nvals 1, just duplicate in all */
662  if (nvals == 1)
663   {
664    for (di = 0; di < delay_p->no_of_delays; di++)
665     __set_vpi_time(&(delay_p->da[di]), &(tim[0]), delay_p->time_type, mdp);
666    return;
667   }
668  /* if nvals 2, if need 1, warn use first, if 2 if path warn and use 2 */
669  if (nvals == 2)
670   {
671    if (delay_p->no_of_delays == 1)
672     {
673      __vpi_err(2011, vpiWarning,
674       "vpi_get_delays for object %s that has 2 delays but get only 1",
675       __to_vpionam(__wrks1, otyp));
676      __set_vpi_time(&(delay_p->da[0]), &(tim[0]), delay_p->time_type, mdp);
677      return;
678     }
679    /* if need 2 just copy */
680    if (delay_p->no_of_delays == 2) goto do_copy;
681 
682    /* if need 3 fill third following normal rule and copy */
683    /* rule is that to-z is as slow as possible */
684    if (delay_p->no_of_delays == 3)
685     {
686      if (tim[0] > tim[1]) tim[2] = tim[0]; else tim[2] = tim[1];
687      goto do_copy;
688     }
689 
690    /* if need 6 convert to 12 (then ok to just ignore high 6 */
691    if (delay_p->no_of_delays >= 6)
692     { __fill_16vconst(ntim, tim, nvals); __map_16v_to_12vform(tim, ntim); }
693    goto do_copy;
694   }
695  /* if nvals 3, if need 1, use warn, use first, if 2 if path warn and */
696  /* use first 2, else no warn use 1st 2 */
697  if (nvals == 3)
698   {
699    if (delay_p->no_of_delays == 1)
700     {
701      __vpi_err(2011, vpiWarning,
702       "vpi_get_delays for object %s that has 3 delays but get only 1",
703       __to_vpionam(__wrks1, otyp));
704      __set_vpi_time(&(delay_p->da[0]), &(tim[0]), delay_p->time_type, mdp);
705      return;
706     }
707    /* 2 if different toz, warning and ignore */
708    if (delay_p->no_of_delays == 2)
709     {
710      if (tim[0] != tim[2] && tim[1] != tim[2])
711       {
712        __vpi_err(2011, vpiWarning,
713        "vpi_get_delays for object %s that has 3 delays but get only 2",
714         __to_vpionam(__wrks1, otyp));
715       }
716      goto do_copy;
717     }
718    /* if need 6 convert to 12 (then ok to just ignore high 6 */
719    if (delay_p->no_of_delays >= 6)
720     { __fill_16vconst(ntim, tim, nvals); __map_16v_to_12vform(tim, ntim); }
721    goto do_copy;
722   }
723  /* know can not reduce to 3 - and stored as 6v form */
724  if (nvals == 6)
725   {
726    if (delay_p->no_of_delays < 6)
727     {
728      __vpi_err(2011, vpiWarning,
729       "vpi_get_delays for object %s that has 6 delays but get only %d",
730       __to_vpionam(__wrks1, otyp), delay_p->no_of_delays);
731      goto do_copy;
732     }
733    /* if need more than 6 must map to 12v form */
734    if (delay_p->no_of_delays > 6)
735     { __fill_16vconst(ntim, tim, nvals); __map_16v_to_12vform(tim, ntim); }
736    goto do_copy;
737   }
738  /* know can not reduce to 6 */
739  if (nvals == 12)
740   {
741    if (delay_p->no_of_delays < 12)
742     {
743      __vpi_err(2011, vpiWarning,
744       "vpi_get_delays for object %s that has 12 delays but get only %d",
745       __to_vpionam(__wrks1, otyp), delay_p->no_of_delays);
746      goto do_copy;
747     }
748    goto do_copy;
749   }
750  __arg_terr(__FILE__, __LINE__);
751 
752 do_copy:
753  /* copy for 2, 3, 6, or 12 case, know tim has enough */
754  for (di = 0; di < delay_p->no_of_delays; di++)
755   __set_vpi_time(&(delay_p->da[di]), &(tim[di]), delay_p->time_type, mdp);
756 }
757 
758 /*
759  * fill a vpi time struct from a word64
760  */
__set_vpi_time(struct t_vpi_time * vpitimp,word64 * timp,int32 timtyp,struct mod_t * mdp)761 extern void __set_vpi_time(struct t_vpi_time *vpitimp, word64 *timp,
762  int32 timtyp, struct mod_t *mdp)
763 {
764  int32 unit;
765  double d1;
766 
767  /* for getting delays, supress times means use 0 (not real) */
768  if (timtyp == vpiSuppressTime)
769   { vpitimp->high = 0L; vpitimp->low = 0L; return; }
770  vpitimp->type = timtyp;
771  /* vpi sim time is internal ticks (lowest precision in design) */
772  if (timtyp == vpiSimTime)
773   {
774    vpitimp->high = (int32) ((*timp >> 32) & WORDMASK_ULL);
775    vpitimp->low = (int32) (*timp & WORDMASK_ULL);
776    return;
777   }
778  /* vpiScaledRealTime case */
779  /* convert module specific ticks to real then scaled real */
780  if (!__v64_to_real(&d1, timp))
781   {
782    __vpi_err(2014, vpiWarning,
783     "conversion from internal time %s to time as real lost precision",
784    __to_timstr(__wrks1, timp));
785   }
786  if (mdp != NULL && !mdp->mno_unitcnv)
787   {
788    unit = __des_timeprec - mdp->mtime_units;
789    d1 /= __dbl_toticks_tab[unit];
790   }
791  vpitimp->real = d1;
792 }
793 
794 /*
795  * set delays
796  */
vpi_put_delays(vpiHandle object,p_vpi_delay delay_p)797 extern void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p)
798 {
799  int32 is_trireg, ndx, sav_num_dels, bi;
800  struct mod_t *mdp;
801  struct h_t *hp;
802  struct tenp_t *prtnetmap;
803  struct mipd_t *mipdp;
804  struct gate_t *gp, ngat, ogat;
805  struct net_t *np;
806  struct conta_t *cap;
807  struct tchk_t *tcp;
808  struct spcpth_t *pthp;
809  struct delctrl_t *dctp;
810  struct t_vpi_time tmpda[3];
811  struct t_vpi_delay wrkdel;
812  struct mod_pin_t *mpp;
813  struct hrec_t *hrp;
814 
815  if (__run_state == SS_COMP) { __still_comp_err("vpi_put_delays"); return; }
816  hp = (struct h_t *) object;
817  if (!__validate_handle("vpi_put_delays", hp)) return;
818  hrp = hp->hrec;
819 
820  if (__rosync_slot) { __bad_rosync_err("vpi_put_delays"); return; }
821  if (__run_state == SS_RESET || __run_state == SS_SIM)
822   {
823    /* inform since sim delay setting may not be supported by other sims */
824    __vpi_err(2106, vpiNotice,
825     "vpi_put_delays to object %s after simulation started - non standard feature",
826     __to_vpionam(__wrks1, hrp->htyp));
827   }
828  /* on error here, user must call error check routine */
829  if (!chk_delay_num("vpi_put_delays", hp, delay_p->no_of_delays, &ogat))
830   return;
831  /* can only set MIPD and replace DT NONE during SS_LOAD */
832  /* SJM - 02/16/00 - must allow changing MIPDs after start of sim */
833  /* to mimic XL acc_ */
834  /* ---
835  if (__run_state == SS_RESET || __run_state == SS_SIM)
836   {
837    -* once delays elaborated (after prep, before var init) can only change *-
838    -* delays if already exist *-
839    if (ogat.g_delrep == DT_NONE)
840     {
841      __vpi_err(1891, vpiError,
842       "vpi_put_delays to object %s with no delay in source illegal after simulation started",
843       __to_vpionam(__wrks1, hrp->htyp));
844      return;
845     }
846   }
847  -- */
848  if (delay_p->pulsere_flag)
849   {
850    if (hrp->htyp != vpiTchk)
851     {
852      __vpi_err(2107, vpiNotice,
853       "vpi_put_delays pulsere_flag values ignored - delay used for both limits");
854     }
855    else
856     {
857      __vpi_err(1884, vpiError,
858       "vpi_put_delays pulsere_flag illegal when setting timing check limit");
859      return;
860     }
861   }
862 
863  /* need module type since need to scale delay */
864  is_trireg = FALSE;
865  mdp = hp->hin_itp->itip->imsym->el.emdp;
866  /* assume if handle created, good - fill the delay union */
867 
868  switch (hrp->htyp) {
869   case vpiGate: case vpiUdp: case vpiSwitch:
870 really_gate:
871    gp = hrp->hu.hgp;
872    /* already checked for adding delay in non load run state */
873    if (gp->g_delrep == DT_NONE)
874     {
875      if (!__add_gate_pnd0del(gp, mdp, (char *) NULL)) return;
876     }
877    ogat.g_du = gp->g_du;
878    ogat.g_delrep = gp->g_delrep;
879    /* build the new value, maybe using old to append to if append flag */
880    /* uses itree loc. from hp if needed for append access */
881    /* new delay only allocated if returns T */
882    if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, FALSE, FALSE)) return;
883 
884    /* this must always recomputer toz (logic) and tox all because never */
885    /* explicitly given */
886    if (ngat.g_delrep == DT_4V)
887     {
888      if (gp->g_class == GC_UDP || gp->g_class == GC_LOGIC)
889       {
890        if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
891         {
892          ngat.g_du.d4v[2] = ngat.g_du.d4v[0];
893          ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
894         }
895        else
896         {
897          ngat.g_du.d4v[2] = ngat.g_du.d4v[1];
898          ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
899         }
900       }
901      else
902       {
903        if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
904         ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
905        else ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
906       }
907     }
908 
909    /* this handles freeing and realloc of delay union if needed */
910    __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
911    gp->g_du = ogat.g_du;
912    gp->g_delrep = ogat.g_delrep;
913    __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
914    break;
915   case vpiPort: case vpiPortBit:
916    /* SJM 07/13/01 - notice only for (PORT form MIPD, not src-dst */
917    /* know this is only for one bit, i.e. scalar port of port bit */
918    mpp = &(mdp->mpins[hrp->hu.hpi]);
919    if (mpp->mptyp != IO_IN && mpp->mptyp != IO_BID)
920     {
921      __vpi_err(1885, vpiError,
922       "vpi_put_delays of non input or inout %s %s - not set because MIPD impossible",
923       __to_vpionam(__wrks1, hrp->htyp), __to_mpnam(__wrks2, mpp->mpsnam));
924      return;
925     }
926    if (hrp->htyp == vpiPort && mpp->mpwide != 1)
927     {
928      __vpi_err(2109, vpiNotice,
929       "vpi_put_delays of non scalar vpiPort (for MIPD) setting low bit");
930     }
931    if (hrp->htyp == vpiPort) ndx = 0; else ndx = hrp->hi;
932 
933    /* build map between ports bit and connected net/bit */
934    prtnetmap = __bld_portbit_netbit_map(mpp);
935    if (!mpp->has_mipd)
936     {
937      /* notice must build mipd table for all of every net connecting to port */
938      for (bi = 0; bi < mpp->mpwide; bi++)
939       {
940        np = prtnetmap[bi].tenu.np;
941        /* LOOKATME - think unc not possible here */
942        if (np == NULL || (np->nlds != NULL
943         && np->nlds->npntyp == NP_MIPD_NCHG)) continue;
944 
945        /* allocate path for every net connected to port */
946        __add_alloc_mipd_npp(np, mdp);
947       }
948      mdp->mod_has_mipds = TRUE;
949      mpp->has_mipd = TRUE;
950     }
951 
952    /* ndx is actual port bit that connects */
953    np = prtnetmap[ndx].tenu.np;
954    bi = prtnetmap[ndx].nbi;
955 
956    /* DBG remove -- */
957    if (np->nlds == NULL || np->nlds->npntyp != NP_MIPD_NCHG)
958     __misc_terr(__FILE__, __LINE__);
959    /* --- */
960    mipdp = &(np->nlds->elnpp.emipdbits[bi]);
961 
962    /* if no active mipd for this net/bit, must enable with 0 delay */
963    if (mipdp->no_mipd) __setup_mipd(mipdp, np, mdp->flatinum);
964 
965    ogat.g_du = mipdp->pb_mipd_du;
966    ogat.g_delrep = mipdp->pb_mipd_delrep;
967    /* treat this as 16 value path style delay - not 3 value gate type */
968    if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, TRUE, FALSE)) return;
969 
970    /* set to x since can never explicitly set */
971    if (ngat.g_delrep == DT_4V)
972     {
973      if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
974       ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
975      else ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
976     }
977 
978    __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
979    mipdp->pb_mipd_du = ogat.g_du;
980    mipdp->pb_mipd_delrep = ogat.g_delrep;
981    __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
982    __my_free((char *) prtnetmap, mpp->mpwide*sizeof(struct tenp_t));
983    break;
984   case vpiNet:
985    np = hrp->hu.hnp;
986    if (np->nrngrep != NX_DWIR)
987     {
988      __vpi_err(1899, vpiError,
989       "vpi_put_delays to wire %s with no delay in source illegal - net must have delay in source",
990       __to_vpionam(__wrks1, hrp->htyp));
991      return;
992     }
993    ogat.g_du = np->nu.rngdwir->n_du;
994    ogat.g_delrep = np->nu.rngdwir->n_delrep;
995    if (np->ntyp == N_TRIREG) is_trireg = TRUE;
996    if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, FALSE, is_trireg))
997     return;
998 
999    if (ngat.g_delrep == DT_4V)
1000     {
1001      /* set to x since can never explicitly set */
1002      if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
1003       ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
1004      else ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
1005     }
1006 
1007    __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
1008    np->nu.rngdwir->n_du = ogat.g_du;
1009    np->nu.rngdwir->n_delrep = ogat.g_delrep;
1010    __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
1011    break;
1012   case vpiContAssign:
1013    /* 1 bit contas internally gates */
1014    if (hrp->htyp2 == vpiGate) goto really_gate;
1015 
1016    cap = hrp->hu.hcap;
1017    /* already checked for adding delay if non load run state */
1018    if (cap->ca_delrep == DT_NONE)
1019     {
1020      if (!__add_conta_pnd0del(cap, mdp, (char *) NULL)) return;
1021     }
1022    ogat.g_du = cap->ca_du;
1023    ogat.g_delrep = cap->ca_delrep;
1024 
1025    if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, FALSE, FALSE))
1026     return;
1027    /* notice bld vpi new du can only produce DT 1V or DT 4V here */
1028    if (ngat.g_delrep == DT_4V)
1029     {
1030      /* set to x since can never explicitly set */
1031      if (ngat.g_du.d4v[0] < ngat.g_du.d4v[1])
1032       ngat.g_du.d4v[3] = ngat.g_du.d4v[0];
1033      else ngat.g_du.d4v[3] = ngat.g_du.d4v[1];
1034     }
1035    __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
1036    cap->ca_du = ogat.g_du;
1037    cap->ca_delrep = ogat.g_delrep;
1038 
1039    /* must always make sure if needed ca_4vdel value changes */
1040    switch ((byte) cap->ca_delrep) {
1041     case DT_4V: case DT_IS4V: case DT_IS4V1: case DT_IS4V2: case DT_4X:
1042      cap->ca_4vdel = TRUE;
1043      break;
1044     default: cap->ca_4vdel = FALSE;
1045    }
1046    __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
1047    break;
1048   case vpiTchk:
1049    tcp = hrp->hu.htcp;
1050    /* if can have 2 set and 2 passed only, set both */
1051    if (tcp->tc_haslim2 && delay_p->no_of_delays == 2)
1052     {
1053      /* 2nd need same fields as first */
1054      wrkdel = *delay_p;
1055      if (wrkdel.mtm_flag)
1056       {
1057        tmpda[0] = delay_p->da[3];
1058        tmpda[1] = delay_p->da[4];
1059        tmpda[2] = delay_p->da[5];
1060       }
1061      else tmpda[0] = delay_p->da[1];
1062      wrkdel.da = &(tmpda[0]);
1063      sav_num_dels = 2;
1064      wrkdel.no_of_delays = 1;
1065      delay_p->no_of_delays = 1;
1066     }
1067    else sav_num_dels = delay_p->no_of_delays;
1068    /* know only 1 or 2 delays (not pulserr but maybe mtm) - copies both */
1069    /* always set at least one */
1070    ogat.g_du = tcp->tclim_du;
1071    ogat.g_delrep = tcp->tc_delrep;
1072    /* know at least one limit is present */
1073    /* DBG remove -- */
1074    if (ogat.g_delrep == DT_NONE) __vpi_terr(__FILE__, __LINE__);
1075    /* --- */
1076    if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, FALSE, FALSE))
1077     goto tc_done;
1078    __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
1079    tcp->tclim_du = ogat.g_du;
1080    tcp->tc_delrep = ogat.g_delrep;
1081    __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
1082 
1083    /* has 2 and timing checks also has 2 limits */
1084    if (tcp->tc_haslim2 && delay_p->no_of_delays == 2)
1085     {
1086      ogat.g_du = tcp->tclim2_du;
1087      ogat.g_delrep = tcp->tc_delrep2;
1088      if (!bld_vpinewdu(&ngat, &ogat, &wrkdel, hp->hin_itp, TRUE, FALSE))
1089       goto tc_done;
1090      __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
1091      tcp->tclim2_du = ogat.g_du;
1092      tcp->tc_delrep2 = ogat.g_delrep;
1093      __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
1094     }
1095 tc_done:
1096    /* must put back passed number so user can free */
1097    delay_p->no_of_delays = sav_num_dels;
1098    break;
1099   case vpiModPath:
1100    pthp = hrp->hu.hpthp;
1101    ogat.g_du = pthp->pth_du;
1102    ogat.g_delrep = pthp->pth_delrep;
1103    if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, TRUE, FALSE))
1104     return;
1105    __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
1106    pthp->pth_du = ogat.g_du;
1107    pthp->pth_delrep = ogat.g_delrep;
1108    __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
1109    break;
1110   /* procedural delays */
1111   case vpiAssignment:
1112    dctp = hrp->hu.hstp->st.sdc;
1113    if (dctp->dctyp != DC_RHSDELAY)
1114     {
1115      __vpi_err(1886, vpiError,
1116       "vpi_put_delays of vpiAssignment right hand side delay control impossible - no delay control");
1117      return;
1118     }
1119 set_dctrl_delay:
1120    ogat.g_du = dctp->dc_du;
1121    ogat.g_delrep = dctp->dc_delrep;
1122    if (!bld_vpinewdu(&ngat, &ogat, delay_p, hp->hin_itp, FALSE, FALSE)) return;
1123    __chg_1inst_del(&ogat, hp->hin_itp, &ngat);
1124    dctp->dc_du = ogat.g_du;
1125    dctp->dc_delrep = ogat.g_delrep;
1126    __free_del(ngat.g_du, ngat.g_delrep, mdp->flatinum);
1127    break;
1128   case vpiDelayControl:
1129    dctp = hrp->hu.hstp->st.sdc;
1130    /* DBG remove --- */
1131    if (dctp->dctyp != DC_DELAY) __vpi_terr(__FILE__, __LINE__);
1132    /* --- */
1133    goto set_dctrl_delay;
1134   /* will not get to this case if not legal element with delay */
1135   default: __vpi_terr(__FILE__, __LINE__);
1136  }
1137 }
1138 
1139 /*
1140  * given a vpi delay_p filled by user, build the _du for it
1141  *
1142  * know delay number correct
1143  * if no source delay, caller changes to #0 before calling
1144  */
bld_vpinewdu(struct gate_t * ngp,struct gate_t * ogp,p_vpi_delay delay_p,struct itree_t * itp,int32 is_path,int32 is_trireg)1145 static int32 bld_vpinewdu(struct gate_t *ngp, struct gate_t *ogp,
1146  p_vpi_delay delay_p, struct itree_t *itp, int32 is_path, int32 is_trireg)
1147 {
1148  register int32 di;
1149  int32 ndels, ondels, negdel[16];
1150  word64 tim[16], otim[16], ntim[16], *dtab;
1151 
1152  if (!fillchk_tim(tim, negdel, delay_p, itp)) return(FALSE);
1153  ndels = delay_p->no_of_delays;
1154 
1155  /* handle appending - must be on delay_p array */
1156  if (delay_p->append_flag)
1157   {
1158    __push_itstk(itp);
1159    __extract_delval(otim, &ondels, ogp->g_du, ogp->g_delrep);
1160    __pop_itstk();
1161    /* if either 1, widen with inform by replicating the 1 to width of other */
1162    if ((ondels == 1 || ndels == 1) && (ondels != ndels))
1163     {
1164      __vpi_err(2008, vpiNotice,
1165       "vpi_put_delays append mode old (%d) and new (%d) number of delays differ - one delay replicated",
1166       ondels, ndels);
1167 
1168      if (ondels != 1)
1169       {
1170        for (di = 1; di < ondels; di++) tim[di] = tim[0];
1171        ndels = ondels;
1172       }
1173      else
1174       {
1175        for (di = 1; di < ndels; di++) otim[di] = otim[0];
1176        ondels = ndels;
1177       }
1178     }
1179    /* here need 2 delay case that is not normally reduced to */
1180    if (!is_path && ondels == 3)
1181     {
1182      if (is_trireg)
1183       { if (otim[3] == otim[0] || otim[3] == otim[1]) ondels = 2; }
1184      else
1185       {
1186        if ((otim[2] == otim[0] || otim[2] == otim[1])
1187         && (otim[3] == otim[0] || otim[3] == otim[1])) ondels = 2;
1188       }
1189     }
1190    /* if too few new delays, use 0 for those (i.e. unchanged) */
1191    if (ndels < ondels)
1192     {
1193      __vpi_err(2005, vpiNotice,
1194       "vpi_put_delays append mode more old delays (%d) than new (%d) - 0 used for missing",
1195       ondels, ndels);
1196      for (di = ndels; di < ondels; di++) tim[di] = 0ULL;
1197      ndels = ondels;
1198     }
1199    /* too many - ignore with warning */
1200    else if (ndels > ondels)
1201     {
1202      __vpi_err(2006, vpiWarning,
1203       "vpi_put_delays append mode more new delays (%d) than old (%d) - extra ignored",
1204       ndels, ondels);
1205      ndels = ondels;
1206     }
1207    /* do the update - know ndels and odels same */
1208    for (di = 0; di < ndels; di++) ntim[di] = tim[di];
1209    for (di = 0; di < ndels; di++)
1210     {
1211      if (negdel[di])
1212       {
1213        if (ntim[di] > otim[di])
1214         {
1215          __vpi_err(2004, vpiWarning,
1216           "vpi_put_delays append result (pos. %d) negative (0 used)", di + 1);
1217          tim[di] = 0ULL;
1218         }
1219        else tim[di] = otim[di] - ntim[di];
1220       }
1221      else tim[di] = otim[di] + ntim[di];
1222     }
1223   }
1224  /* now tim has right new delay value */
1225  /* fill dtab (always 4 or 16 for path) */
1226  if (ndels == 1)
1227   {
1228 del1form:
1229    ngp->g_du.d1v = (word64 *) __my_malloc(sizeof(word64));
1230    *(ngp->g_du.d1v) = tim[0];
1231    ngp->g_delrep = DT_1V;
1232    return(TRUE);
1233   }
1234 
1235  /* see if can reduce to 1 - know at least 2 */
1236  for (di = 1; di < ndels; di++) { if (tim[0] != tim[di]) goto no_reduce1; }
1237  goto del1form;
1238 
1239 no_reduce1:
1240  if (is_path)
1241   {
1242    dtab = (word64 *) __my_malloc(16*sizeof(word64));
1243    __fill_16vconst(dtab, tim, ndels);
1244    ngp->g_delrep = DT_16V;
1245    ngp->g_du.d16v = dtab;
1246   }
1247  else
1248   {
1249    dtab = (word64 *) __my_malloc(4*sizeof(word64));
1250    __fill_4vconst(dtab, &(tim[0]), &(tim[1]), &(tim[2]), ndels, is_trireg);
1251    ngp->g_delrep = DT_4V;
1252    ngp->g_du.d4v = dtab;
1253   }
1254  return(TRUE);
1255 }
1256 
1257 /*
1258  * fill and check internal tim[] value from delay p
1259  * return F on error
1260  *
1261  * mtm and pulsere possible here, pulsere no effect though
1262  * scaling depends upon module of handle
1263  * LOOKATME - is it true only vpiScaledRealTime can be negative
1264  */
fillchk_tim(word64 * tim,int32 * negdel,p_vpi_delay delay_p,struct itree_t * itp)1265 static int32 fillchk_tim(word64 *tim, int32 *negdel, p_vpi_delay delay_p,
1266  struct itree_t *itp)
1267 {
1268  register int32 di;
1269  int32 stride, ofset, ndels;
1270  double d1;
1271  word64 t1;
1272  struct t_vpi_time *vpitimp;
1273  struct mod_t *mdp;
1274 
1275  ndels = delay_p->no_of_delays;
1276  for (di = 0; di < ndels; di++) negdel[di] = FALSE;
1277  stride = 1;
1278  ofset = 0;
1279  if (delay_p->pulsere_flag) stride *= 3;
1280  if (delay_p->mtm_flag)
1281   {
1282    stride *= 3;
1283    if (__mintypmax_sel == DEL_MIN) ofset = 0;
1284    else if (__mintypmax_sel == DEL_TYP) ofset = 1;
1285    else if (__mintypmax_sel == DEL_MAX) ofset = 2;
1286    else __vpi_terr(__FILE__, __LINE__);
1287   }
1288  /* step 1: convert to internal ticks and set neg - maybe needed for inc */
1289  for (di = 0; di < ndels; di++)
1290   {
1291    /* always ignore any pulse limits (2 and 3 or 3 through 8 if mtm) */
1292    vpitimp = &(delay_p->da[stride*di + ofset]);
1293 
1294    /* suppress ok for append - just do not change (0 if none) */
1295    if (vpitimp->type == vpiSuppressTime)
1296     {
1297      if (!delay_p->append_flag)
1298       {
1299        /* () form normal 0 for SDF so do no need warning */
1300        __vpi_err(2003, vpiWarning,
1301         "vpi_put_delays vpiSuppressTime (pos. %d) ignored for replace mode - 0 used",
1302          di + 1);
1303       }
1304      tim[di] = 0ULL;
1305      continue;
1306     }
1307    if (vpitimp->type == vpiScaledRealTime)
1308     {
1309      d1 = vpitimp->real;
1310      if (d1 < 0.0)
1311       {
1312        if (!delay_p->append_flag)
1313         {
1314          __vpi_err(2004, vpiWarning,
1315           "replace mode vpi_put_delays value %g (pos. %d) negative (0 used)",
1316           d1, di + 1);
1317          tim[di] = 0ULL;
1318          continue;
1319         }
1320        d1 = -d1;
1321        negdel[di] = TRUE;
1322       }
1323      if (!__real_to_v64tim(&t1, d1))
1324       {
1325        __vpi_err(1895, vpiError,
1326         "vpi_put_delays value %g (pos. %d) too large for vpiScaledRealTime",
1327          d1, di + 1);
1328        return(FALSE);
1329       }
1330      mdp = itp->itip->imsym->el.emdp;
1331      if (!mdp->mno_unitcnv) cnv_num64to_ticks_(tim[di], t1, mdp);
1332      else tim[di] = t1;
1333      continue;
1334     }
1335    if (vpitimp->type != vpiSimTime)
1336     {
1337      __vpi_err(1820, vpiError,
1338       "vpi_put_delays t_vpi_time type value %d illegal (pos. %d)",
1339       vpitimp->type, di + 1);
1340      return(FALSE);
1341     }
1342    /* vpiSimTime is internal ticks */
1343    /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
1344    t1 = (word64) ((word32) vpitimp->low)
1345     | (((word64) ((word32) vpitimp->high)) << 32);
1346    tim[di] = t1;
1347   }
1348  return(TRUE);
1349 }
1350 
1351 /*
1352  * VALUE PROCESSING ROUTINES
1353  */
1354 
1355 /*
1356  * get value into value_p record
1357  *
1358  * LOOKATME - does fcall have a value (think not)
1359  *
1360  * SJM 10/21/99 - changed so if value not set causes vpi_ error
1361  */
vpi_get_value(vpiHandle expr,p_vpi_value value_p)1362 extern void vpi_get_value(vpiHandle expr, p_vpi_value value_p)
1363 {
1364  struct h_t *hp;
1365  struct hrec_t *hrp;
1366  struct gate_t *gp;
1367  struct mod_t *mdp;
1368  struct mod_pin_t *mpp;
1369 
1370  /* must reset at start of call to no error */
1371  __last_eip = NULL;
1372  if (__run_state == SS_COMP)
1373   { __still_comp_err("vpi_get_value"); return; }
1374 
1375  hp = (struct h_t *) expr;
1376  if (!__validate_handle("vpi_get_value", hp)) return;
1377  hrp = hp->hrec;
1378 
1379  /* no access for suppress - LOOKATME - is this true */
1380  if (value_p->format == vpiSuppressVal) return;
1381 
1382  switch (hrp->htyp) {
1383   case vpiNet: case vpiReg: case vpiIntegerVar: case vpiTimeVar:
1384   case vpiRealVar: case vpiParameter: case vpiSpecParam:
1385     __push_itstk(hp->hin_itp);
1386     get_varorparam_val(hp, value_p);
1387    __pop_itstk();
1388    break;
1389   case vpiNetBit: case vpiRegBit: case vpiVarSelect:
1390    get_var_bit(hp, value_p);
1391    break;
1392   case vpiMemoryWord:
1393    get_arrwrd_val(hp, value_p);
1394    break;
1395   case vpiConstant: case vpiPartSelect: case vpiOperation: case vpiFuncCall:
1396    __push_itstk(hp->hin_itp);
1397    get_expr_val(hp, value_p);
1398    __pop_itstk();
1399    break;
1400   case vpiPrimTerm:
1401    get_primterm_val(hp, value_p);
1402    break;
1403   case vpiSysFuncCall:
1404    /* LOOKATME - what is this supposed to do? */
1405    get_vpisfcall_retval(hp, value_p);
1406    break;
1407   case vpiUdpDefn:
1408    get_vpiudpdefn_val(hp, value_p);
1409    break;
1410   case vpiTableEntry:
1411    get_vpitabentry_val(hp, value_p);
1412    break;
1413   /* LOOKATME - no get value of quasi-continue force/assign because */
1414   /* can build driver iterator and then access lhs expr. - is this right */
1415 
1416   /* remaining access drivers - i.e. access internal driving code not val */
1417   case vpiNetDriver:
1418    get_vpi_netdrv_val(hp, value_p);
1419    break;
1420   case vpiNetBitDriver:
1421    get_vpi_netbitdrv_val(hp, value_p);
1422    break;
1423   case vpiGate: case vpiUdp:
1424    gp = hrp->hu.hgp;
1425 conta_gate:
1426    get_gate_drv_valuep(hp, value_p, gp);
1427    break;
1428   case vpiContAssign:
1429    if (hrp->htyp2 == vpiGate)
1430     {gp = hrp->hu.hgp; goto conta_gate; }
1431    get_vpiconta_drv_valuep(hp, value_p, hrp->hu.hcap);
1432    break;
1433   case vpiPort:
1434    mdp = hp->hin_itp->itip->imsym->el.emdp;
1435    mpp = &(mdp->mpins[hrp->hu.hpi]);
1436    get_vpiport_drv_valuep(hp, value_p, mpp);
1437    break;
1438   case vpiPortBit:
1439    mdp = hp->hin_itp->itip->imsym->el.emdp;
1440    mpp = &(mdp->mpins[hrp->hu.hpi]);
1441    get_vpiportbit_drv_valuep(hp, value_p, mpp, hrp->hi);
1442    break;
1443   case vpiAttribute:
1444    get_vpi_attrval(hp, value_p);
1445    break;
1446   default:
1447    __vpi_err(1897, vpiError,
1448     "vpi_get_value can not access value of %s (variable, param or expression needed)",
1449     __to_vpionam(__wrks1, hrp->htyp));
1450    return;
1451  }
1452 }
1453 
1454 /*
1455  * get value of any variable or parameter include global param
1456  * caller has set itree loc
1457  */
get_varorparam_val(struct h_t * hp,p_vpi_value value_p)1458 static void get_varorparam_val(struct h_t *hp, p_vpi_value value_p)
1459 {
1460  register struct net_t *np;
1461  register struct xstk_t *xsp;
1462  byte *sbp;
1463  struct xstk_t *xsp2;
1464 
1465  /* no checking needed */
1466 
1467  np = hp->hrec->hu.hnp;
1468  /* correct for type determined format */
1469  if (value_p->format == vpiObjTypeVal)
1470   correct_objtypval(value_p, np->ntyp, np->n_isavec, np->n_stren, FALSE);
1471 
1472  /* non stren */
1473  if (value_p->format != vpiStrengthVal)
1474   {
1475    push_xstk_(xsp, np->nwid);
1476    __ld_wire_val(xsp->ap, xsp->bp, np);
1477    fill_valuep(value_p, xsp, np->ntyp, np->nwid);
1478    __pop_xstk();
1479    return;
1480   }
1481 
1482  /* need strength */
1483  /* net stored as strength */
1484  if (np->n_stren)
1485   {
1486    get_stwire_addr_(sbp, np);
1487    if (np->nwid == 1) stscal_fill_valuep(value_p, sbp, 0);
1488    else stvec_fill_valuep(value_p, sbp, np->nwid);
1489    return;
1490   }
1491  /* load as non stren and convert to stren case */
1492  push_xstk_(xsp, np->nwid);
1493  __ld_wire_val(xsp->ap, xsp->bp, np);
1494 
1495  push_xstk_(xsp2, 4*np->nwid);
1496  sbp = (byte *) xsp2->ap;
1497  /* add strong */
1498  __st_standval(sbp, xsp, ST_STRVAL);
1499  if (np->nwid == 1) stscal_fill_valuep(value_p, sbp, 0);
1500  else stvec_fill_valuep(value_p, sbp, np->nwid);
1501  __pop_xstk();
1502  __pop_xstk();
1503 }
1504 
1505 /*
1506  * fill a scalar strength valuep field from a strength vector
1507  */
stscal_fill_valuep(p_vpi_value value_p,register byte * sbp,int32 bi)1508 static void stscal_fill_valuep(p_vpi_value value_p, register byte *sbp, int32 bi)
1509 {
1510  register s_vpi_strengthval *svalp;
1511  int32 slen;
1512 
1513  slen = sizeof(struct t_vpi_strengthval);
1514  if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
1515  value_p->value.strength = (struct t_vpi_strengthval *) __wrkvalbufp;
1516 
1517  svalp = &(value_p->value.strength[0]);
1518  svalp[0].logic = (int32) (sbp[bi] & 3L);
1519  svalp[0].s0 = __map_tovpi_stren((int32) ((sbp[bi] >> 5) & 7));
1520  svalp[0].s1 = __map_tovpi_stren((int32) ((sbp[bi] >> 2) & 7));
1521 }
1522 
1523 /*
1524  * fill a strength valuep field from a strength vector
1525  *
1526  * 04/01/00 - for veriog 2000 now can access/stren strength in vectors
1527  * user must allocate wide enough t vpi_strengthval array
1528  * caller must convert value to strength if non strength
1529  */
stvec_fill_valuep(p_vpi_value value_p,register byte * sbp,int32 swid)1530 static void stvec_fill_valuep(p_vpi_value value_p, register byte *sbp,
1531  int32 swid)
1532 {
1533  register int32 bi;
1534  register s_vpi_strengthval *svalp;
1535  int32 slen;
1536 
1537  slen = swid*sizeof(struct t_vpi_strengthval);
1538  if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
1539  value_p->value.strength = (struct t_vpi_strengthval *) __wrkvalbufp;
1540 
1541  svalp = &(value_p->value.strength[0]);
1542  for (bi = 0; bi < swid; bi++)
1543   {
1544    svalp[bi].logic = (int32) (sbp[bi] & 3L);
1545    svalp[bi].s0 = __map_tovpi_stren((int32) ((sbp[bi] >> 5) & 7));
1546    svalp[bi].s1 = __map_tovpi_stren((int32) ((sbp[bi] >> 2) & 7));
1547   }
1548 }
1549 
1550 /*
1551  * map from vpi strength values to internal Cver values
1552  * returns -1 on bad value
1553  */
__map_frvpi_stren(int32 vpistval)1554 extern int32 __map_frvpi_stren(int32 vpistval)
1555 {
1556  int32 stval;
1557 
1558  /* must be left as int32 in case bad value_p record */
1559  switch (vpistval) {
1560   case vpiSupplyDrive: stval = ST_SUPPLY; break;
1561   case vpiStrongDrive: stval = ST_STRONG; break;
1562   case vpiPullDrive: stval = ST_PULL; break;
1563   case vpiWeakDrive: stval = ST_WEAK; break;
1564   case vpiLargeCharge: stval = ST_LARGE; break;
1565   case vpiMediumCharge: stval = ST_MEDIUM; break;
1566   case vpiSmallCharge: stval = ST_SMALL; break;
1567   case vpiHiZ: stval = ST_HIGHZ; break;
1568   default: return(-1);
1569  }
1570  return(stval);
1571 }
1572 
1573 /*
1574  * map from internal strength values to vpi strength constant
1575  */
__map_tovpi_stren(word32 stval)1576 extern word32 __map_tovpi_stren(word32 stval)
1577 {
1578  word32 vpistval;
1579 
1580  switch ((byte) stval) {
1581   case ST_SUPPLY: vpistval = vpiSupplyDrive; break;
1582   case ST_STRONG: vpistval = vpiStrongDrive; break;
1583   case ST_PULL: vpistval = vpiPullDrive; break;
1584   case ST_WEAK: vpistval = vpiWeakDrive; break;
1585   case ST_LARGE: vpistval = vpiLargeCharge; break;
1586   case ST_MEDIUM: vpistval = vpiMediumCharge; break;
1587   case ST_SMALL: vpistval = vpiSmallCharge; break;
1588   case ST_HIGHZ: vpistval = vpiHiZ; break;
1589   default: __vpi_terr(__FILE__, __LINE__); return(0);
1590  }
1591  return(vpistval);
1592 }
1593 
1594 /*
1595  * get variable bit
1596  *
1597  * this must set itree context
1598  */
get_var_bit(struct h_t * hp,p_vpi_value value_p)1599 static void get_var_bit(struct h_t *hp, p_vpi_value value_p)
1600 {
1601  register int32 biti;
1602  struct net_t *np;
1603  byte *sbp;
1604  struct xstk_t *xsp, *xsp2;
1605 
1606  /* nothing to check */
1607 
1608  /* DBG remove --- */
1609  if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__);
1610  /* --- */
1611  __push_itstk(hp->hin_itp);
1612 
1613  biti = get_vpibit_index(&np, hp);
1614 
1615  if (value_p->format == vpiObjTypeVal)
1616   correct_objtypval(value_p, np->ntyp, np->n_isavec, np->n_stren, FALSE);
1617 
1618  /* non strength case */
1619  if (value_p->format != vpiStrengthVal)
1620   {
1621    push_xstk_(xsp, 1);
1622    __ld_bit(xsp->ap, xsp->bp, np, biti);
1623    fill_valuep(value_p, xsp, np->ntyp, 1);
1624    __pop_xstk();
1625    __pop_itstk();
1626    return;
1627   }
1628 
1629  /* stored as stren */
1630  if (np->n_stren)
1631   {
1632    get_stwire_addr_(sbp, np);
1633    stscal_fill_valuep(value_p, sbp, biti);
1634    __pop_itstk();
1635    return;
1636   }
1637 
1638  /* stored as non stren but get val asked for stren */
1639  push_xstk_(xsp, 1);
1640  __ld_bit(xsp->ap, xsp->bp, np, biti);
1641  push_xstk_(xsp2, 4);
1642  sbp = (byte *) xsp2->ap;
1643  __st_standval(sbp, xsp, ST_STRVAL);
1644  /* SJM 02/08/01 - for (net/reg) bit object sbp is the one bit */
1645  stscal_fill_valuep(value_p, sbp, 0);
1646  __pop_xstk();
1647  __pop_xstk();
1648  __pop_itstk();
1649 }
1650 
1651 /*
1652  * get value of one array word32 given a array word32 (indexed) handle
1653  *
1654  * know passed handle is array word32 and correct index in range for well
1655  * formed handle
1656  */
get_arrwrd_val(struct h_t * hp,p_vpi_value value_p)1657 static void get_arrwrd_val(struct h_t *hp, p_vpi_value value_p)
1658 {
1659  int32 arri, arrwid;
1660  byte *sbp;
1661  struct net_t *np;
1662  struct xstk_t *xsp, *xsp2;
1663 
1664  /* nothing to check - stren legal */
1665 
1666  /* DBG remove --- */
1667  if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__);
1668  /* --- */
1669  __push_itstk(hp->hin_itp);
1670 
1671  /* notice union field is index and since array word32 is in has itree */
1672  /* inst., can use for ptr to the containing handle */
1673  /* this uses comp_ndx that works for arrays too */
1674  arri = get_vpibit_index(&np, hp);
1675 
1676  if (value_p->format == vpiObjTypeVal)
1677   correct_objtypval(value_p, np->ntyp, np->n_isavec, np->n_stren, FALSE);
1678 
1679  /* never strength - but may need to convert */
1680  arrwid = __get_arrwide(np);
1681  push_xstk_(xsp, np->nwid);
1682  __ld_arr_val(xsp->ap, xsp->bp, np->nva, arrwid, np->nwid, arri);
1683 
1684  if (value_p->format != vpiStrengthVal)
1685   {
1686    fill_valuep(value_p, xsp, np->ntyp, np->nwid);
1687    __pop_xstk();
1688    __pop_itstk();
1689    return;
1690   }
1691 
1692  /* always need to add stren here */
1693  push_xstk_(xsp2, 4*np->nwid);
1694  sbp = (byte *) xsp2->ap;
1695  __st_standval(sbp, xsp, ST_STRVAL);
1696 
1697  if (np->nwid == 1) stscal_fill_valuep(value_p, sbp, 0);
1698  else stvec_fill_valuep(value_p, sbp, np->nwid);
1699  __pop_xstk();
1700  __pop_xstk();
1701  __pop_itstk();
1702 }
1703 
1704 /*
1705  * get value of expression
1706  * caller has set itree loc
1707  */
get_expr_val(struct h_t * hp,p_vpi_value value_p)1708 static void get_expr_val(struct h_t *hp, p_vpi_value value_p)
1709 {
1710  int32 wtyp;
1711  struct expr_t *xp;
1712  struct xstk_t *xsp;
1713  struct hrec_t *hrp;
1714 
1715  hrp = hp->hrec;
1716 
1717  /* only error is stren illegal */
1718  if (valp_stren_err(hrp, value_p)) return;
1719 
1720  /* notice expr. handle itree loc. is always ref. location */
1721  /* LOOKATME - these are never strength - think this is right - check */
1722  xp = hrp->hu.hxp;
1723  xsp = __eval_xpr(xp);
1724  if (value_p->format == vpiObjTypeVal) expr_correct_objtypval(xp, value_p);
1725 
1726  if (xp->is_real) wtyp = N_REAL; else wtyp = N_REG;
1727  fill_valuep(value_p, xsp, wtyp, xsp->xslen);
1728  __pop_xstk();
1729 }
1730 
1731 /*
1732  * check for illegal strength - return T if stren (error) F if non stren
1733  * if error if stren
1734  */
valp_stren_err(struct hrec_t * hrp,p_vpi_value value_p)1735 static int32 valp_stren_err(struct hrec_t *hrp, p_vpi_value value_p)
1736 {
1737  /* for expressons - strength not allowed */
1738  if (value_p->format == vpiStrengthVal)
1739   {
1740    __vpi_err(1929, vpiError,
1741     "vpi_get_value vpiStrengthVal format illegal for expression object %s",
1742     __to_vpionam(__wrks1, hrp->htyp));
1743    return(TRUE);
1744   }
1745  return(FALSE);
1746 }
1747 
1748 /*
1749  * get value of primitve terminal
1750  *
1751  * notice legal to get any terminal including input
1752  *
1753  * SJM 11/26/00 - change so for all but tran and pull gets get internal
1754  * driving value for gate/udp/mos-gates in gstate
1755  * this now adds strengths for outputs if gate drives strength and
1756  * computes
1757  *
1758  * LOOKATME - for tran and pull gates think net value and driving value same?
1759  */
get_primterm_val(struct h_t * hp,p_vpi_value value_p)1760 static void get_primterm_val(struct h_t *hp, p_vpi_value value_p)
1761 {
1762  register struct gate_t *gp;
1763  register word32 gtermwrd;
1764  int32 has_stren;
1765  byte sbv, *sbp;
1766  struct hrec_t *hrp;
1767  struct expr_t *xp;
1768  struct xstk_t *xsp;
1769 
1770  hrp = hp->hrec;
1771  /* DBG remove --- */
1772  if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__);
1773  /* --- */
1774  __push_itstk(hp->hin_itp);
1775 
1776  gp = hrp->hu.hgp;
1777  /* case 1: accessing value of connecting wire as terminal value */
1778  /* know these always have stren */
1779  if (gp->g_class == GC_PULL || gp->g_class == GC_TRAN
1780   || gp->g_class == GC_TRANIF)
1781   {
1782    xp = hrp->hu.hgp->gpins[hrp->hi];
1783    if (value_p->format == vpiObjTypeVal) expr_correct_objtypval(xp, value_p);
1784 
1785    /* LOOKATME - is it possible for tran channels to not have stren? */
1786    if (value_p->format == vpiStrengthVal)
1787     {
1788      /* this adds strong if expr non strength */
1789      xsp = __ndst_eval_xpr(xp);
1790      sbp = (byte *) xsp->ap;
1791      stscal_fill_valuep(value_p, sbp, 0);
1792     }
1793    else
1794     {
1795      xsp = __eval_xpr(xp);
1796      /* type since no net can be reg since reg can connect to input */
1797      fill_valuep(value_p, xsp, N_REG, xsp->xslen);
1798     }
1799    __pop_xstk();
1800    __pop_itstk();
1801    return;
1802   }
1803  /* case 2: logic/udp/mos gate - this is same as gate value */
1804  if (hrp->hi == 0)
1805   {
1806    /* case 2a: gate output value */
1807    get_gate_drv_valuep(hp, value_p, gp);
1808    __pop_itstk();
1809    return;
1810   }
1811  /* case 2b primitive terminal input value - first input is 1 */
1812  /* this gets gstate terminal value since within tick gstate may not be */
1813  /* updated yet after connecting expr change */
1814 
1815  /* SJM 11/26/00 - allowing strength where added as strong */
1816  xp = hrp->hu.hgp->gpins[hrp->hi];
1817  if (value_p->format == vpiObjTypeVal) expr_correct_objtypval(xp, value_p);
1818 
1819  gtermwrd = __ld_gate_in(gp, hrp->hi, &has_stren);
1820  if (value_p->format != vpiStrengthVal)
1821   {
1822    push_xstk_(xsp, 1);
1823    xsp->ap[0] = gtermwrd & 1L;
1824    xsp->bp[0] = (gtermwrd >> 1) & 1L;
1825    fill_valuep(value_p, xsp, N_WIRE, 1);
1826    __pop_xstk();
1827    __pop_itstk();
1828    return;
1829   }
1830  /* need stren */
1831  push_xstk_(xsp, 4);
1832  sbv = (byte) gtermwrd;
1833  /* add gate driving stren if needed */
1834  if (!has_stren && sbv != 2) sbv |= (ST_STRVAL << 2);
1835  stscal_fill_valuep(value_p, &(sbv), 0);
1836  __pop_itstk();
1837 }
1838 
1839 /*
1840  * get return value for current user task or function only
1841  *
1842  * must be called from current system function or error
1843  * uses own itree context
1844  * LOOKATME - no internal vpi storage but LRM not clear
1845  * LOOKATME - what is this supposed to do - get last value?
1846  */
get_vpisfcall_retval(struct h_t * hp,p_vpi_value value_p)1847 static void get_vpisfcall_retval(struct h_t *hp, p_vpi_value value_p)
1848 {
1849  int32 sf_ind;
1850  word32 isavec;
1851  p_vpi_systf_data tfdatp;
1852  struct systftab_t *sfp;
1853  struct sysfunc_t *sfbp;
1854  struct hrec_t *hrp;
1855  char s1[RECLEN];
1856 
1857  hrp = hp->hrec;
1858  /* --- DBG remove --- */
1859  if (hrp->hu.hxp == NULL) __vpi_terr(__FILE__, __LINE__);
1860  /* --- */
1861 
1862  if (valp_stren_err(hrp, value_p)) return;
1863 
1864  if (hrp->hu.hxp != __cur_sysf_expr)
1865   {
1866    if (__cur_sysf_expr != NULL)
1867     {
1868      sf_ind = __cur_sysf_expr->lu.x->lu.sy->el.esyftbp->syfnum;
1869      sf_ind -= (__last_veriusertf + 1);
1870      sfp = &(__systftab[sf_ind]);
1871      tfdatp = (p_vpi_systf_data) sfp->vpi_sytfdat;
1872      strcpy(s1, tfdatp->tfname);
1873     }
1874    else strcpy(s1, "**none called**");
1875    __vpi_err(1848, vpiError,
1876     "vpi_get_value of vpiSysFuncCall %s (return value) illegal - must use from calltf cb",
1877     s1);
1878    return;
1879   }
1880  sf_ind = __cur_sysf_expr->lu.x->lu.sy->el.esyftbp->syfnum;
1881  sf_ind -= (__last_veriusertf + 1);
1882  sfp = &(__systftab[sf_ind]);
1883  tfdatp = (p_vpi_systf_data) sfp->vpi_sytfdat;
1884  sfbp = sfp->sfu.sfbp;
1885  if (value_p->format == vpiObjTypeVal)
1886   {
1887    isavec = (sfbp->retwid == 1) ? FALSE : TRUE;
1888    correct_objtypval(value_p, sfbp->retntyp, isavec, FALSE, FALSE);
1889   }
1890  __push_itstk(hp->hin_itp);
1891  fill_valuep(value_p, __cur_sysf_xsp, sfbp->retntyp, sfbp->retwid);
1892  __pop_itstk();
1893 }
1894 
1895 /*
1896  * get udp definition value
1897  * value not per instance
1898  */
get_vpiudpdefn_val(struct h_t * hp,p_vpi_value value_p)1899 static void get_vpiudpdefn_val(struct h_t *hp, p_vpi_value value_p)
1900 {
1901  struct hrec_t *hrp;
1902  struct udp_t *udpp;
1903  struct xstk_t *xsp;
1904 
1905  hrp = hp->hrec;
1906  /* checking */
1907  if (hrp->hu.hudpp->ival == NO_VAL)
1908   {
1909    __vpi_err(1939, vpiError,
1910     "vpi_get_value of vpiUdpDefn but no initial value - value_p unchanged");
1911    return;
1912   }
1913  if (value_p->format == vpiTimeVal)
1914   {
1915    __vpi_err(1892, vpiError,
1916     "vpi_get_value of vpiUdpDefn initial value VpiTimeVal value illegal - no module context");
1917     return;
1918   }
1919  if (valp_stren_err(hrp, value_p)) return;
1920 
1921  /* get initial value - if get here know present */
1922  udpp = hrp->hu.hudpp;
1923  if (value_p->format == vpiObjTypeVal)
1924   correct_objtypval(value_p, N_REG, FALSE, FALSE, FALSE);
1925  push_xstk_(xsp, 1);
1926  xsp->bp[0] = 0L;
1927  if (udpp->ival == 3) { xsp->ap[0] = 1L; xsp->bp[0] = 1L; }
1928  else xsp->ap[0] = (word32) udpp->ival;
1929  fill_valuep(value_p, xsp, N_REG, xsp->xslen);
1930  __pop_xstk();
1931 }
1932 
1933 /*
1934  * get udp definition value
1935  * value not per instance
1936  */
get_vpitabentry_val(struct h_t * hp,p_vpi_value value_p)1937 static void get_vpitabentry_val(struct h_t *hp, p_vpi_value value_p)
1938 {
1939  int32 slen;
1940  struct hrec_t *hrp;
1941  struct udp_t *udpp;
1942  struct utline_t *utlp;
1943 
1944  hrp = hp->hrec;
1945 
1946  /* special correction of obj type here */
1947  if (value_p->format != vpiObjTypeVal)
1948   {
1949    if (value_p->format != vpiStringVal)
1950     {
1951      __vpi_err(1892, vpiError,
1952      "vpi_get_value of vpiTableEntry udp line only vpiStringVal format supported");
1953      return;
1954     }
1955    else value_p->format = vpiStringVal;
1956   }
1957 
1958  utlp = hrp->hu.hutlp;
1959  udpp = (struct udp_t *) hp->hin_itp;
1960  slen = 5*(udpp->numstates + 1) + 1;
1961  if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
1962  value_p->value.str = __wrkvalbufp;
1963  udp_line_to_str(value_p->value.str, udpp, utlp);
1964 }
1965 
1966 /*
1967  * DRIVER GET VALUE ROUTINES
1968  */
1969 
1970 /*
1971  * get net driver value
1972  *
1973  * 04/01/00 SJM - for verilog 2000 vectors of strens legal
1974  */
get_vpi_netdrv_val(struct h_t * hp,p_vpi_value value_p)1975 static void get_vpi_netdrv_val(struct h_t *hp, p_vpi_value value_p)
1976 {
1977  byte *sbp;
1978  struct net_t *np;
1979  struct xstk_t *xsp, *xsp2;
1980 
1981  /* nothing to check */
1982 
1983  /* DBG remove --- */
1984  if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__);
1985  /* --- */
1986  __push_itstk(hp->hin_itp);
1987 
1988  /* notice must access net value through here */
1989  xsp = push_vpi_drv_val(hp, &np);
1990 
1991  /* correct for type determined format */
1992  if (value_p->format == vpiObjTypeVal)
1993   correct_objtypval(value_p, np->ntyp, np->n_isavec, np->n_stren, FALSE);
1994 
1995  /* non stren case */
1996  if (value_p->format != vpiStrengthVal)
1997   {
1998    fill_valuep(value_p, xsp, np->ntyp, np->nwid);
1999    __pop_xstk();
2000    __pop_itstk();
2001    return;
2002   }
2003 
2004  /* this uses net fields since stren expr value impossible */
2005  /* net stored as stren - loaded stren driver */
2006  if (np->n_stren)
2007   {
2008    sbp = (byte *) xsp->ap;
2009    if (np->nwid == 1) stscal_fill_valuep(value_p, sbp, 0);
2010    else stvec_fill_valuep(value_p, sbp, np->nwid);
2011    __pop_xstk();
2012    __pop_itstk();
2013    return;
2014   }
2015  /* else convert to stren */
2016  push_xstk_(xsp2, 4*np->nwid);
2017  sbp = (byte *) xsp2->ap;
2018  /* add strong */
2019  __st_standval(sbp, xsp, ST_STRVAL);
2020 
2021  if (np->nwid == 1) stscal_fill_valuep(value_p, sbp, 0);
2022  else stvec_fill_valuep(value_p, sbp, np->nwid);
2023 
2024  __pop_xstk();
2025  __pop_xstk();
2026  __pop_itstk();
2027 }
2028 
2029 /*
2030  * push vpi net driver value onto stack (entire net case)
2031  *
2032  * existence of handle means all bits of this instance of net have added drvr
2033  */
push_vpi_drv_val(struct h_t * hp,struct net_t ** pnp)2034 static struct xstk_t *push_vpi_drv_val(struct h_t *hp, struct net_t **pnp)
2035 {
2036  register struct net_t *np;
2037  register struct xstk_t *xsp;
2038  register struct vpi_drv_t *vpidrvp;
2039  byte *sbp, *sbp2;
2040  struct net_pin_t *npp;
2041 
2042  npp = hp->hrec->hu.hnpp;
2043  np = npp->elnpp.enp;
2044  *pnp = np;
2045  /* obnum is index of driver */
2046  vpidrvp = np->vpi_ndrvs[npp->obnum];
2047  if (np->n_stren)
2048   {
2049    push_xstk_(xsp, 4*np->nwid);
2050    sbp = (byte *) xsp->ap;
2051    sbp2 = &(vpidrvp->vpi_drvwp.bp[__inum*np->nwid]);
2052    memcpy(sbp, sbp2, np->nwid);
2053   }
2054  else
2055   {
2056    push_xstk_(xsp, np->nwid);
2057    __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_drvwp, np->nwid);
2058   }
2059  return(xsp);
2060 }
2061 
2062 /*
2063  * get net bit driver value
2064  */
get_vpi_netbitdrv_val(struct h_t * hp,p_vpi_value value_p)2065 static void get_vpi_netbitdrv_val(struct h_t *hp, p_vpi_value value_p)
2066 {
2067  byte *sbp;
2068  struct net_t *np;
2069  struct xstk_t *xsp, *xsp2;
2070 
2071  /* DBG remove --- */
2072  if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__);
2073  /* --- */
2074  __push_itstk(hp->hin_itp);
2075 
2076  xsp = push_vpi_bitdrv_val(hp, &np);
2077 
2078  /* correct for type determined format */
2079  if (value_p->format == vpiObjTypeVal)
2080   correct_objtypval(value_p, np->ntyp, np->n_isavec, np->n_stren, TRUE);
2081 
2082  /* this uses net since stren expr value impossible */
2083  if (value_p->format != vpiStrengthVal)
2084   {
2085    fill_valuep(value_p, xsp, np->ntyp, 1);
2086    __pop_xstk();
2087    __pop_itstk();
2088    return;
2089   }
2090 
2091  if (np->n_stren)
2092   {
2093    sbp = (byte *) xsp->ap;
2094    stscal_fill_valuep(value_p, sbp, 0);
2095    __pop_xstk();
2096    __pop_itstk();
2097    return;
2098   }
2099 
2100  /* must add strong */
2101  push_xstk_(xsp2, 4);
2102  sbp = (byte *) xsp2->ap;
2103  __st_standval(sbp, xsp, ST_STRVAL);
2104  stscal_fill_valuep(value_p, sbp, 0);
2105  __pop_xstk();
2106  __pop_xstk();
2107  __pop_itstk();
2108 }
2109 
2110 /*
2111  * push vpi net bit driver value onto stack
2112  *
2113  * existence of handle means handle's bit of this instance of net has add drvr
2114  */
push_vpi_bitdrv_val(struct h_t * hp,struct net_t ** pnp)2115 static struct xstk_t *push_vpi_bitdrv_val(struct h_t *hp, struct net_t **pnp)
2116 {
2117  register struct net_t *np;
2118  register struct xstk_t *xsp, *xsp2;
2119  register struct vpi_drv_t *vpidrvp;
2120  byte *sbp;
2121  struct net_pin_t *npp;
2122 
2123  npp = hp->hrec->hu.hnpp;
2124  np = npp->elnpp.enp;
2125  *pnp = np;
2126  /* obnum is index of driver */
2127  vpidrvp = np->vpi_ndrvs[npp->obnum];
2128  if (np->n_stren)
2129   {
2130    push_xstk_(xsp, 4);
2131    sbp = (byte *) xsp->ap;
2132    sbp[0] = vpidrvp->vpi_drvwp.bp[__inum*np->nwid + hp->hrec->hi];
2133   }
2134  else
2135   {
2136    push_xstk_(xsp, 1);
2137    push_xstk_(xsp2, np->nwid);
2138    __ld_perinst_val(xsp2->ap, xsp2->bp, vpidrvp->vpi_drvwp, np->nwid);
2139    xsp->ap[0] = rhsbsel_(xsp2->ap, hp->hrec->hi);
2140    xsp->bp[0] = rhsbsel_(xsp2->bp, hp->hrec->hi);
2141    __pop_xstk();
2142   }
2143  return(xsp);
2144 }
2145 
2146 /*
2147  * fill a gate driver valuep
2148  */
get_gate_drv_valuep(struct h_t * hp,p_vpi_value value_p,struct gate_t * gp)2149 static void get_gate_drv_valuep(struct h_t *hp, p_vpi_value value_p,
2150  struct gate_t *gp)
2151 {
2152  int32 has_stren;
2153  word32 uwrd;
2154  byte *sbp;
2155  struct xstk_t *xsp;
2156 
2157  /* DBG remove --- */
2158  if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__);
2159  /* --- */
2160  __push_itstk(hp->hin_itp);
2161 
2162  /* correct for type determined format */
2163  if (value_p->format == vpiObjTypeVal)
2164   correct_objtypval(value_p, N_WIRE, FALSE, (gp->g_hasst) ? TRUE : FALSE,
2165    FALSE);
2166 
2167  if (value_p->format != vpiStrengthVal)
2168   {
2169    push_xstk_(xsp, 1);
2170    uwrd = __ld_gate_out(gp, &has_stren);
2171    /* this must load value and remove strength since drives constant */
2172    /* notice this is non stren case - stren passing gates not proc. here */
2173    xsp->ap[0] = uwrd & 1L;
2174    xsp->bp[0] = (uwrd >> 1) & 1L;
2175    fill_valuep(value_p, xsp, N_WIRE, 1);
2176    __pop_xstk();
2177    __pop_itstk();
2178    return;
2179   }
2180  /* need stren */
2181  push_xstk_(xsp, 4);
2182  sbp = (byte *) xsp->ap;
2183  sbp[0] = (byte) __ld_gate_out(gp, &has_stren);
2184  /* add gate driving stren if needed */
2185  if (!has_stren && sbp[0] != 2)
2186   {
2187    /* 04/01/00 - add gate strength since that is driven */
2188    /* 08/07/01 - only possibility here is both strong since no stren */
2189    sbp[0] |= (ST_STRVAL << 2);
2190   }
2191  stscal_fill_valuep(value_p, sbp, 0);
2192  __pop_xstk();
2193  __pop_itstk();
2194 }
2195 
2196 /*
2197  * for vpi get value - get conta driving value and assign to value p
2198  *
2199  * 1 bit conta drivers not seen here (converted to gates)
2200  * in Verilog conta strength hard coded in gate so only or in if needed
2201  *
2202  * SJM 09/28/02 - for rhs conta per bit must combine PB drv values
2203  */
get_vpiconta_drv_valuep(struct h_t * hp,p_vpi_value value_p,struct conta_t * cap)2204 static void get_vpiconta_drv_valuep(struct h_t *hp, p_vpi_value value_p,
2205  struct conta_t *cap)
2206 {
2207  register int32 bi;
2208  int32 blen;
2209  byte *sbp;
2210  struct xstk_t *xsp, *xsp2;
2211  struct conta_t *pbcap;
2212 
2213  /* DBG remove --- */
2214  if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__);
2215  /* --- */
2216  __push_itstk(hp->hin_itp);
2217 
2218  /* correct for type determined format - know lhs is some kind of wire */
2219  if (value_p->format == vpiObjTypeVal)
2220   correct_objtypval(value_p, N_WIRE, TRUE, (cap->ca_hasst) ? TRUE : FALSE,
2221    FALSE);
2222 
2223  blen = cap->lhsx->szu.xclen;
2224  if (cap->ca_pb_sim)
2225   {
2226    /* SJM 09/28/02 - for per bit rhs concat conta, must assemble val */
2227    push_xstk_(xsp, blen);
2228    for (bi = 0; bi < blen; bi++)
2229     {
2230      pbcap = &(cap->pbcau.pbcaps[bi]);
2231      if (pbcap->ca_drv_wp.wp == NULL)
2232       {
2233        xsp2 = __eval2_xpr(pbcap->rhsx);
2234        /* DBG remove -- */
2235        if (xsp2->xslen != 1) __misc_terr(__FILE__, __LINE__);
2236        /* --- */
2237       }
2238      else
2239       {
2240        push_xstk_(xsp2, 1);
2241        __ld_perinst_val(xsp2->ap, xsp2->bp, pbcap->ca_drv_wp, 1);
2242       }
2243      __lhsbsel(xsp->ap, bi, xsp2->ap[0]);
2244      __lhsbsel(xsp->bp, bi, xsp2->bp[0]);
2245     }
2246   }
2247  else
2248   {
2249    if (cap->ca_drv_wp.wp == NULL)
2250     {
2251      xsp = __eval2_xpr(cap->rhsx);
2252      if (xsp->xslen != blen)
2253       {
2254        if (xsp->xslen < blen)
2255         {
2256          /* SJM 05/10/04 - if widening and signed, must sign extend */
2257          if (cap->rhsx->has_sign) __sgn_xtnd_widen(xsp, blen);
2258          else __sizchg_widen(xsp, blen);
2259         }
2260        else __sizchgxs(xsp, blen);
2261       }
2262     }
2263    else
2264     {
2265      push_xstk_(xsp, blen);
2266      __ld_perinst_val(xsp->ap, xsp->bp, cap->ca_drv_wp, blen);
2267     }
2268   }
2269 
2270  /* 04/01/00 - now for verilog 2000 handling strength vectors */
2271  if (value_p->format != vpiStrengthVal)
2272   {
2273    fill_valuep(value_p, xsp, N_WIRE, blen);
2274    __pop_xstk();
2275    __pop_itstk();
2276    return;
2277   }
2278 
2279  /* else convert to stren */
2280  push_xstk_(xsp2, 4*blen);
2281  sbp = (byte *) xsp2->ap;
2282  /* add stren - if does not have st val, stren is strong */
2283  __st_standval(sbp, xsp, cap->ca_stval);
2284 
2285  /* DBG remove --
2286  if (blen == 1) __vpi_terr(__FILE__, __LINE__);
2287  --- */
2288 
2289  stvec_fill_valuep(value_p, sbp, blen);
2290  __pop_xstk();
2291  __pop_xstk();
2292  __pop_itstk();
2293 }
2294 
2295 /*
2296  * for vpi get value - get mod. port driving value and assign to value p
2297  *
2298  * port driver is just value of expr.
2299  */
get_vpiport_drv_valuep(struct h_t * hp,p_vpi_value value_p,struct mod_pin_t * mpp)2300 static void get_vpiport_drv_valuep(struct h_t *hp, p_vpi_value value_p,
2301  struct mod_pin_t *mpp)
2302 {
2303  int32 is_stren, isavec;
2304  byte *sbp;
2305  struct xstk_t *xsp, *xsp2;
2306 
2307  /* DBG remove --- */
2308  if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__);
2309  /* --- */
2310  __push_itstk(hp->hin_itp);
2311 
2312  if (mpp->mpref->x_stren) is_stren = TRUE; else is_stren = FALSE;
2313  if (mpp->mpwide == 1) isavec = FALSE; else isavec = TRUE;
2314  /* correct for type determined format - know lhs is some kind of wire */
2315  if (value_p->format == vpiObjTypeVal)
2316   correct_objtypval(value_p, N_WIRE, isavec, is_stren, FALSE);
2317 
2318  /* if module input port, use driving value */
2319  sbp = NULL;
2320  /* no delay - driver is expr. value */
2321  /* module port (down) side is expr. - no need for width change */
2322  if (is_stren) xsp = __ndst_eval_xpr(mpp->mpref);
2323  else xsp = __eval2_xpr(mpp->mpref);
2324 
2325  if (value_p->format != vpiStrengthVal)
2326   {
2327    if (is_stren)
2328     {
2329      /* here must remove strength */
2330      sbp = (byte *) xsp->ap;
2331      push_xstk_(xsp2, mpp->mpwide);
2332      __ld_stval(xsp2->ap, xsp2->bp, sbp, mpp->mpwide);
2333      fill_valuep(value_p, xsp2, N_WIRE, mpp->mpwide);
2334      __pop_xstk();
2335     }
2336    else fill_valuep(value_p, xsp, N_WIRE, mpp->mpwide);
2337    __pop_xstk();
2338    __pop_itstk();
2339    return;
2340   }
2341  /* 04/01/00 SJM - for strength now loading entire vector */
2342  if (is_stren)
2343   {
2344    sbp = (byte *) xsp->ap;
2345    if (mpp->mpwide == 1) stscal_fill_valuep(value_p, sbp, 0);
2346    else stvec_fill_valuep(value_p, sbp, mpp->mpwide);
2347    __pop_xstk();
2348    __pop_itstk();
2349    return;
2350   }
2351  /* driving value non strength - must add strong */
2352  /* load as non stren and convert to stren case */
2353  push_xstk_(xsp2, 4*mpp->mpwide);
2354  sbp = (byte *) xsp2->ap;
2355  /* add strong */
2356  __st_standval(sbp, xsp, ST_STRVAL);
2357  if (mpp->mpwide == 1) stscal_fill_valuep(value_p, sbp, 0);
2358  else stvec_fill_valuep(value_p, sbp, mpp->mpwide);
2359  __pop_xstk();
2360  __pop_xstk();
2361  __pop_itstk();
2362 }
2363 
2364 /*
2365  * for vpi get value - get mod. port bit driving value and assign to value p
2366  * routine for vpi Port Bit
2367  */
get_vpiportbit_drv_valuep(struct h_t * hp,p_vpi_value value_p,struct mod_pin_t * mpp,int32 bi)2368 static void get_vpiportbit_drv_valuep(struct h_t *hp, p_vpi_value value_p,
2369  struct mod_pin_t *mpp, int32 bi)
2370 {
2371  int32 is_stren, ind;
2372  word32 av, bv;
2373  byte *sbp;
2374  struct xstk_t *xsp, *xsp2, *xsp3;
2375 
2376  /* DBG remove --- */
2377  if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__);
2378  /* --- */
2379  __push_itstk(hp->hin_itp);
2380 
2381  if (mpp->mpref->x_stren) is_stren = TRUE; else is_stren = FALSE;
2382  /* DBG remove --- */
2383  if (mpp->mpwide == 1) __vpi_terr(__FILE__, __LINE__);
2384  /* --- */
2385  /* correct for type determined format - know lhs is some kind of wire */
2386  if (value_p->format == vpiObjTypeVal)
2387   correct_objtypval(value_p, N_WIRE, FALSE, is_stren, TRUE);
2388 
2389  xsp2 = NULL;
2390  sbp = NULL;
2391  /* no delay - driver is expr. value */
2392  /* module port (down) side is expr. - no need for width change */
2393  if (is_stren)
2394   {
2395    xsp2 = __ndst_eval_xpr(mpp->mpref);
2396    sbp = (byte *) xsp2->ap;
2397    ind = __inum*mpp->mpwide + bi;
2398    sbp = &(sbp[ind]);
2399   }
2400  else
2401   {
2402    xsp = __eval2_xpr(mpp->mpref);
2403    av = rhsbsel_(xsp->ap, bi);
2404    bv = rhsbsel_(xsp->bp, bi);
2405    __pop_xstk();
2406    push_xstk_(xsp2, 1);
2407    xsp2->ap[0] = av;
2408    xsp2->bp[0] = bv;
2409   }
2410 
2411  /* know one bit driving val on stack either stren or non stren */
2412  if (value_p->format != vpiStrengthVal)
2413   {
2414    if (is_stren)
2415     {
2416      /* remove bit's stren */
2417      av = sbp[0] & 1L;
2418      bv = ((sbp[0] & 2L) >> 1);
2419      __pop_xstk();
2420      push_xstk_(xsp2, 1);
2421      xsp2->ap[0] = av;
2422      xsp2->bp[0] = bv;
2423      fill_valuep(value_p, xsp2, N_WIRE, 1);
2424     }
2425    else fill_valuep(value_p, xsp2, N_WIRE, mpp->mpwide);
2426    __pop_xstk();
2427    __pop_itstk();
2428    return;
2429   }
2430  /* need stren in value p */
2431  if (!is_stren)
2432   {
2433    push_xstk_(xsp3, 4);
2434    /* add strong for bit */
2435    sbp = (byte *) xsp3->ap;
2436    sbp[0] = (byte) (xsp2->ap[0] | (xsp2->bp[0] << 1));
2437    if (sbp[0] != 2) sbp[0] |= (ST_STRVAL << 2);
2438    stscal_fill_valuep(value_p, sbp, 0);
2439    __pop_xstk();
2440    __pop_xstk();
2441    __pop_itstk();
2442    return;
2443   }
2444  stscal_fill_valuep(value_p, sbp, 0);
2445  __pop_xstk();
2446  __pop_itstk();
2447 }
2448 
2449 /*
2450  * get attribute value
2451  */
get_vpi_attrval(struct h_t * hp,p_vpi_value value_p)2452 static void get_vpi_attrval(struct h_t *hp, p_vpi_value value_p)
2453 {
2454  int32 wtyp;
2455  struct expr_t *xp;
2456  struct xstk_t *xsp;
2457  struct hrec_t *hrp;
2458  struct attr_t *attrp;
2459 
2460  hrp = hp->hrec;
2461 
2462  /* only error is stren illegal */
2463  if (valp_stren_err(hrp, value_p)) return;
2464 
2465  /* DBG remove --- */
2466  if (hp->hin_itp == NULL) __vpi_terr(__FILE__, __LINE__);
2467  /* --- */
2468  __push_itstk(hp->hin_itp);
2469 
2470  /* can't fail - internal error if not found */
2471  attrp = __find_attrspec(hp);
2472 
2473  xp = attrp->attr_xp;
2474  if (value_p->format == vpiObjTypeVal) expr_correct_objtypval(xp, value_p);
2475  if (xp == NULL)
2476   {
2477    /* 32 bit 1 if no expr - i.e. defaults to T */
2478    push_xstk_(xsp, WBITS);
2479    xsp->ap[0] = 1;
2480    xsp->bp[0] = 0;
2481   }
2482  else xsp = __eval_xpr(xp);
2483 
2484  if (xp != NULL && xp->is_real) wtyp = N_REAL; else wtyp = N_REG;
2485  fill_valuep(value_p, xsp, wtyp, xsp->xslen);
2486  __pop_xstk();
2487  __pop_itstk();
2488 }
2489 
2490 
2491 /*
2492  * correct value_p for vpiObjTypeVal given the net accessing value from
2493  *
2494  * notice semantics is to really change and fill in the format field
2495  */
correct_objtypval(p_vpi_value value_p,word32 ntyp,word32 isavec,word32 is_stren,int32 is_bsel)2496 static void correct_objtypval(p_vpi_value value_p, word32 ntyp,
2497  word32 isavec, word32 is_stren, int32 is_bsel)
2498 {
2499  if (ntyp == N_INT) { value_p->format = vpiIntVal; return; }
2500  if (ntyp == N_REAL) { value_p->format = vpiRealVal; return; }
2501  if (ntyp == N_TIME) { value_p->format = vpiTimeVal; return; }
2502  if (!isavec || is_bsel)
2503   {
2504    if (is_stren) value_p->format = vpiStrengthVal;
2505    else value_p->format = vpiScalarVal;
2506    return;
2507   }
2508  value_p->format = vpiVectorVal;
2509 }
2510 
2511 /*
2512  * correct value_p for vpiObjTypeVal given the net accessing value from
2513  *
2514  * notice semantics is to really change and fill in the format field
2515  */
expr_correct_objtypval(struct expr_t * xp,p_vpi_value value_p)2516 static void expr_correct_objtypval(struct expr_t *xp, p_vpi_value value_p)
2517 {
2518  if (xp->is_real) { value_p->format = vpiRealVal; return; }
2519  if (xp->has_sign) { value_p->format = vpiIntVal; return; }
2520  if (xp->szu.xclen == 1)
2521   {
2522    if (xp->x_stren) value_p->format = vpiStrengthVal;
2523    else value_p->format = vpiScalarVal;
2524    return;
2525   }
2526  value_p->format = vpiVectorVal;
2527 }
2528 
2529 /*
2530  * fill a value_p record
2531  *
2532  * only for non strength value, strength filled in other routine
2533  * caller loads value and places on stack
2534  *
2535  * for reals using non real format, conversion before call
2536  * for strings this uses and must enlarge a vpi get value specific work string
2537  * caller must place right itree location on top of itree loc. stack
2538  */
fill_valuep(p_vpi_value value_p,struct xstk_t * xsp,word32 vwtyp,int32 vwid)2539 static void fill_valuep(p_vpi_value value_p, struct xstk_t *xsp,
2540  word32 vwtyp, int32 vwid)
2541 {
2542  register int32 wi;
2543  int32 slen, has_sign, blen;
2544  char *chp;
2545  int32 sav_sofs, dispfmt;
2546  double d1;
2547  word64 tim;
2548 
2549  sav_sofs = __cur_sofs;
2550  has_sign = FALSE;
2551  switch ((byte) value_p->format) {
2552    case vpiBinStrVal:
2553     dispfmt = BBIN;
2554 dispstr_fmt:
2555     /* convert real to reg */
2556     if (vwtyp == N_REAL) __cnv_stk_fromreal_toreg32(xsp);
2557 
2558     /* AIV 03/12/04 - changed so does not trim to match XL */
2559     __regab_disp(xsp->ap, xsp->bp, vwid, dispfmt, FALSE, has_sign);
2560     slen = __cur_sofs - sav_sofs;
2561     if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
2562     value_p->value.str = __wrkvalbufp;
2563     strcpy(value_p->value.str, &(__exprline[sav_sofs]));
2564     /* exprline reset below */
2565     break;
2566    case vpiOctStrVal: dispfmt = BOCT; goto dispstr_fmt;
2567    case vpiDecStrVal:
2568     if (vwtyp == N_INT) has_sign = TRUE;
2569     dispfmt = BDEC;
2570     goto dispstr_fmt;
2571    case vpiHexStrVal: dispfmt = BHEX; goto dispstr_fmt;
2572 
2573    case vpiScalarVal:
2574     if (vwid > 1)
2575      {
2576       __vpi_err(2017, vpiWarning,
2577        "vpi_get_delays format type vpiScalarVal for %s vector - low bit only",
2578        __to_wtnam2(__wrks1, vwtyp));
2579      }
2580     if (vwtyp == N_REAL) __cnv_stk_fromreal_toreg32(xsp);
2581     /* notice this assume vpi[0,1,z,x] are 0, 1, 2, 3 as stored */
2582     value_p->value.scalar = ((xsp->bp[0] & 1L) << 1) | (xsp->ap[0] & 1L);
2583     break;
2584    case vpiIntVal:
2585     if (xsp->xslen > WBITS)
2586      {
2587       __vpi_err(2017, vpiWarning,
2588        "vpi_get_delays format type vpiIntVal for %s wider than 32 bits - low 32 bits only",
2589        __to_wtnam2(__wrks1, vwtyp));
2590      }
2591     if (vwtyp == N_REAL) __cnv_stk_fromreal_toreg32(xsp);
2592     /* notice integer x/z bits are always 0 - LOOKATME - is this right? */
2593     value_p->value.integer = (int32) (xsp->ap[0] & ~(xsp->bp[0]));
2594     break;
2595    case vpiRealVal:
2596     if (vwtyp != N_REAL)
2597      {
2598       if (vwtyp == N_INT) __cnv_stk_fromreg_toreal(xsp, TRUE);
2599       else __cnv_stk_fromreg_toreal(xsp, FALSE);
2600      }
2601     memcpy(&d1, xsp->ap, sizeof(double));
2602     value_p->value.real = d1;
2603     break;
2604    case vpiStringVal:
2605     /* SJM 07/30/01 - conversion to c string requires removing high pad 0's */
2606     blen = __trim1_0val(xsp->ap, xsp->xslen);
2607     /* chp malloced */
2608     chp = __alloc_vval_to_cstr(xsp->ap, blen, FALSE, FALSE);
2609     slen = strlen(chp);
2610     if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
2611     value_p->value.str = __wrkvalbufp;
2612     strcpy(value_p->value.str, chp);
2613     /* expr line sofs reset before here */
2614     __my_free(chp, slen + 1);
2615     return;
2616    case vpiVectorVal:
2617     if (vwtyp == N_REAL) __cnv_stk_fromreal_toreg32(xsp);
2618     slen = wlen_(xsp->xslen)*sizeof(struct t_vpi_vecval);
2619     if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
2620     value_p->value.vector = (struct t_vpi_vecval *) __wrkvalbufp;
2621     for (wi = 0; wi < wlen_(xsp->xslen); wi++)
2622      {
2623       value_p->value.vector[wi].aval = (int32) xsp->ap[wi];
2624       value_p->value.vector[wi].bval = (int32) xsp->bp[wi];
2625      }
2626     break;
2627    case vpiTimeVal:
2628     /* value is vpiSimTime internal ticks */
2629     /* SJM 02/03/00 - works because stack word32 - no sign extend */
2630     tim = (word64) xsp->ap[0] | (((word64) xsp->ap[1]) << 32);
2631     slen = sizeof(struct t_vpi_time);
2632     if (slen >= __wrkval_buflen) wrkval_grow(slen + RECLEN);
2633     value_p->value.time = (struct t_vpi_time *) __wrkvalbufp;
2634     value_p->value.time->type = vpiSimTime;
2635     value_p->value.time->high = (int32) ((tim >> 32) & WORDMASK_ULL);
2636     value_p->value.time->low = (int32) (tim & WORDMASK_ULL);
2637     break;
2638    /* strength value never pushed because not expression */
2639    default:
2640     __vpi_err(1902, vpiError,
2641      "vpi_get_value passed s_vpi_value format value %d illegal",
2642      value_p->format);
2643   }
2644  __cur_sofs = sav_sofs;
2645  __exprline[__cur_sofs] = '\0';
2646 }
2647 
2648 /*
2649  * grow the one work string used by get value routine
2650  */
wrkval_grow(int32 nsize)2651 static void wrkval_grow(int32 nsize)
2652 {
2653  int32 osize;
2654 
2655  osize = __wrkval_buflen;
2656  if (osize == 0)
2657   {
2658    if (nsize > RECLEN) __wrkval_buflen = nsize;
2659    else __wrkval_buflen = RECLEN;
2660    __wrkvalbufp = __my_malloc(__wrkval_buflen);
2661    return;
2662   }
2663  __wrkvalbufp = __my_realloc(__wrkvalbufp, osize, nsize);
2664  __wrkval_buflen = nsize;
2665 }
2666 
2667 /*
2668  * convert one
2669  * need to also dump initial value
2670  */
udp_line_to_str(char * s,struct udp_t * udpp,struct utline_t * utlp)2671 static void udp_line_to_str(char *s, struct udp_t *udpp, struct utline_t *utlp)
2672 {
2673  register int32 i;
2674  int32 numins;
2675  char *chp, s1[RECLEN];
2676 
2677  numins = udpp->numins;
2678  strcpy(s, "");
2679  for (chp = utlp->tline, i = 0; i < numins; i++, chp++)
2680   {
2681    /* the one possible edge */
2682    if (utlp->uledinum == i)
2683     {
2684      /* special wild card types edges are kept as original char */
2685      /* 01 and 10 are converted from rise-fall - convert back */
2686      if (utlp->utabsel == '0' && *chp == '1') strcat(s, "    r");
2687      else if (utlp->utabsel == '1' && *chp == '0') strcat(s, "    f");
2688      else if (utlp->utabsel == '*') strcat(s, "    *");
2689      else if (utlp->utabsel == 'p') strcat(s, "    p");
2690      else if (utlp->utabsel == 'n') strcat(s, "    n");
2691      else
2692       {
2693        sprintf(s1, " (%c%c)", (char) utlp->utabsel, *chp);
2694        strcat(s, s1);
2695       }
2696     }
2697    /* various wild cards and states left as input char */
2698    else { sprintf(s1, "%5c", *chp); strcat(s, s1); }
2699   }
2700  if (udpp->utyp != U_COMB)
2701   { sprintf(s1, " : %c ", *chp); strcat(s, s1); chp++; }
2702  sprintf(s1, " : %c ;", *chp);
2703  strcat(s, s1);
2704 }
2705 
2706 /*
2707  * VPI PUT VALUE ROUTINES
2708  */
2709 
2710 /*
2711  * assign to an object from value_p possibly forcing or scheduled
2712  *
2713  * if vpiReturnEvent bit on in flags, return event else nil
2714  */
vpi_put_value(vpiHandle object,p_vpi_value value_p,p_vpi_time time_p,PLI_INT32 flags)2715 extern vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
2716  p_vpi_time time_p, PLI_INT32 flags)
2717 {
2718  int32 ndx, bi, wid, ret_event;
2719  word32 dtyp;
2720  struct h_t *hp, *hp2;
2721  word64 ticksdel;
2722  struct net_t *np;
2723  struct xstk_t *xsp;
2724  struct net_pin_t *npp;
2725  struct hrec_t *hrp;
2726 
2727  /* must reset at start of call to no error */
2728  __last_eip = NULL;
2729  if (__run_state == SS_COMP)
2730   { __still_comp_err("vpi_put_value"); return(NULL); }
2731  hp = (struct h_t *) object;
2732  if (!__validate_handle("vpi_put_value", hp)) return(NULL);
2733  hrp = hp->hrec;
2734  if (__run_state != SS_SIM)
2735   {
2736    if (hrp->htyp != vpiSpecParam && hrp->htyp != vpiParameter)
2737     {
2738      __sim_notbegun_err("vpi_put_value of non param");
2739      return(NULL);
2740     }
2741   }
2742  /* set extra flag and remove return event bit */
2743  ret_event = FALSE;
2744  if ((flags & vpiReturnEvent) != 0)
2745   { dtyp = (word32) (flags & ~vpiReturnEvent); ret_event = TRUE; }
2746  else dtyp = (word32) flags;
2747 
2748  if (__rosync_slot)
2749   {
2750    /* put value for future time is legal in ro sync slot */
2751    if (!putv_in_future(dtyp, time_p))
2752     {
2753      __bad_rosync_err("vpi_put_value");
2754      return(NULL);
2755     }
2756   }
2757 
2758  __push_itstk(hp->hin_itp);
2759 
2760  /* check all flag and handle combinations - does not check vpi_time rec */
2761  if (!chk_putv_args(dtyp, hp, value_p))
2762   {
2763    __pop_itstk();
2764    return(NULL);
2765   }
2766 
2767  switch (dtyp) {
2768   case vpiCancelEvent:
2769    /* remove scheduled (must exist) and free dputv record */
2770    /* free needed because marking cancelled free does not free guts */
2771    /* does nothing if event (or some from vectored table done) */
2772    free_putv_sched(hp);
2773    /* user problem to free this handle if needed */
2774    break;
2775   case vpiAddDriver:
2776    if (hrp->htyp == vpiNet) hp2 = add_net_driver(hp);
2777    else if (hrp->htyp == vpiNetBit) hp2 = add_netbit_driver(hp);
2778    else { __vpi_terr(__FILE__, __LINE__); hp2 = NULL; }
2779    __pop_itstk();
2780    return((vpiHandle) hp2);
2781   case vpiForceFlag:
2782    /* force release on wire not on special array form driver or event */
2783    ndx = __get_vpinet_index(&np, hp);
2784    wid = (ndx == -1) ? np->nwid : 1;
2785    /* for vpi wire bit push the bit value will force bit ndx in wire */
2786    /* always need to push non strength even if strength wire because */
2787    /* must add strong not use actual strength */
2788    if ((xsp = push_vpi_valuep(value_p, wid, np->ntyp, FALSE)) == NULL)
2789     break;
2790 
2791    if (np->ntyp >= NONWIRE_ST) reg_vpi_force(np, xsp->ap, xsp->bp);
2792    else
2793     {
2794      /* SJM 11/14/00 - if wire in tran channel force all wires in it */
2795      /* SJM 03/15/01 - can't force all of tran channel - just soft force */
2796      /* this tran wire and re-eval tran channel */
2797      if (np->ntraux != NULL)
2798       {
2799        __tran_wire_vpi_force(np, xsp->ap, xsp->bp, ndx);
2800        /* SJM 03/15/01 - not sure if vector legal but for scalar -1 illegal */
2801        if (ndx == -1) __eval_tran_bits(np);
2802        else __eval_tran_1bit(np, ndx);
2803       }
2804      else wire_vpi_force(np, xsp->ap, xsp->bp, ndx);
2805     }
2806    __pop_xstk();
2807    break;
2808   case vpiReleaseFlag:
2809    ndx = __get_vpinet_index(&np, hp);
2810    if (np->ntyp >= NONWIRE_ST) reg_vpi_release(np);
2811    else
2812     {
2813      if (np->ntraux != NULL)
2814       {
2815        /* SJM 03/15/01 - did't force all of tran channel - just release */
2816        /* this tran wire and re-eval tran channel */
2817        __tran_wire_vpi_release(np, ndx);
2818        /* SJM 02/23/05 - bit objects can be released - not just entire vecs */
2819        /* thanks to Greenlight for this fix */
2820        if (ndx == -1) __eval_tran_bits(np);
2821        else __eval_tran_1bit(np, ndx);
2822       }
2823      else wire_vpi_release(np, ndx);
2824     }
2825    /* nothing to pop from expr. stack here */
2826    break;
2827   case vpiNoDelay:
2828    switch (hrp->htyp) {
2829     case vpiSysFuncCall:
2830      /* special immediate (no schedule) assign case */
2831      set_vpisfcall_retval(hp, value_p);
2832      break;
2833     case vpiSpecParam: case vpiParameter:
2834      set_vpiparam_val(hp, value_p);
2835      break;
2836     case vpiUdpDefn:
2837      set_vpiudpdef_ival(hp, value_p);
2838      break;
2839     case vpiNetDriver: case vpiNetBitDriver:
2840      /* can only putv to reg or wire driver which is always per bit */
2841      /* according to LRM - time p can be nil if not needed */
2842      /* handle consists of table of per bit handles */
2843      npp = hrp->hu.hnpp;
2844      np = npp->elnpp.enp;
2845      if (npp->npaux == NULL || npp->npaux->nbi1 == -1)
2846       {
2847        /* nothing pushed on stack if returns nil */
2848        if ((xsp = push_vpi_valuep(value_p, np->nwid, np->ntyp, np->n_stren))
2849         == NULL) break;
2850        immed_vpi_drv_assign(np, npp->obnum, xsp->ap, xsp->bp);
2851        __pop_xstk();
2852        break;
2853       }
2854      bi = npp->npaux->nbi1;
2855      if ((xsp = push_vpi_valuep(value_p, 1, np->ntyp, np->n_stren)) == NULL)
2856       break;
2857      immed_vpibit_drv_assign(np, npp->obnum, bi, xsp->ap, xsp->bp);
2858      __pop_xstk();
2859      /* no scheduled event handle to return */
2860      break;
2861     case vpiNet: case vpiNetBit:
2862      /* SJM 07/24/00 - no delay assign just changes net value */
2863      ndx = __get_vpinet_index(&np, hp);
2864      wid = (ndx == -1) ? np->nwid : 1;
2865      /* wire and expected can never be strength here */
2866      /* SJM 08/03/00 - this may be soft force of strength value */
2867      if ((xsp = push_vpi_valuep(value_p, wid, np->ntyp, np->n_stren)) == NULL)
2868       break;
2869 
2870      /* following acc_ routines, no delay set ignored any pending assigns */
2871      /* SJM 11/14/00 - for soft force of in tran chan (inout), now soft */
2872      /* all wires in tran chan */
2873      /* SJM 03/15/01 - can't force all of tran channel - just soft force */
2874      /* this tran wire and re-eval tran channel */
2875      if (np->ntraux != NULL)
2876       {
2877        __tran_exec_putv_wire_softforce(np, xsp->ap, xsp->bp, ndx);
2878        /* SJM 03/15/01 - not sure if vector legal but for scalar -1 illegal */
2879        if (np->n_isavec) __eval_tran_1bit(np, ndx);
2880        else __eval_tran_bits(np);
2881       }
2882      else exec_putv_wire_softforce(np, xsp->ap, xsp->bp, ndx);
2883 
2884      __pop_xstk();
2885      break;
2886     default:
2887      /* all regs and vars here */
2888      /* know good - checking in already called putv check routine */
2889      /* final case is immedate assign to reg or reg bit */
2890      ndx = __get_vpinet_index(&np, hp);
2891      wid = (ndx == -1) ? np->nwid : 1;
2892      /* can never be wire or strength here */
2893      if ((xsp = push_vpi_valuep(value_p, wid, np->ntyp, FALSE)) == NULL)
2894       break;
2895      /* following acc_ routines, no delay set ignored any pending assigns */
2896      exec_putv_reg_assign(np, xsp->ap, xsp->bp, ndx);
2897      __pop_xstk();
2898    }
2899    break;
2900   case vpiInertialDelay: case vpiTransportDelay: case vpiPureTransportDelay:
2901    if (!__vpitime_to_ticks(&ticksdel, time_p, __inst_mod)) return(NULL);
2902    if (hrp->htyp != vpiNetDriver && hrp->htyp != vpiNetBitDriver)
2903     {
2904      /* know this is wire or reg or bit of reg (or var) or net or net bit */
2905      ndx = __get_vpinet_index(&np, hp);
2906      hp2 = setschd_var_fromvaluep(value_p, np, ndx, ticksdel, dtyp, ret_event);
2907     }
2908    else
2909     {
2910      /* wire delayed wire driver assignm (bit or table entire wire) */
2911      hp2 = setschd_drvr_fromvaluep(value_p, hp, ticksdel, dtyp, ret_event);
2912     }
2913 
2914    /* for release if no error, final step is getting after released value */
2915    if (__last_eip == NULL && (flags & ~vpiReturnEvent) == vpiReleaseFlag)
2916     vpi_get_value(object, value_p);
2917    __pop_itstk();
2918    return((vpiHandle) hp2);
2919   default:
2920     /* should never get here because of previous checking */
2921    __vpi_terr(__FILE__, __LINE__);
2922    break;
2923   }
2924  __pop_itstk();
2925  return(NULL);
2926 }
2927 
2928 /*
2929  * return T if put value is for future time so is allowed in ro sync slot
2930  */
putv_in_future(word32 dtyp,p_vpi_time time_p)2931 static int32 putv_in_future(word32 dtyp, p_vpi_time time_p)
2932 {
2933  word64 ticksdel;
2934 
2935  switch (dtyp) {
2936   case vpiCancelEvent:
2937    /* can always cancel since only events in queue are for future */
2938    return(TRUE);
2939   case vpiAddDriver: case vpiForceFlag: case vpiReleaseFlag: case vpiNoDelay:
2940    /* these always immediate */
2941    break;
2942   case vpiInertialDelay: case vpiTransportDelay: case vpiPureTransportDelay:
2943    /* these ok if delay not 0 */
2944    /* LOOKATME - maybe these errors should be caught elsewhere - not stop */
2945    if (time_p == NULL) break;
2946    if (!__vpitime_to_ticks(&ticksdel, time_p, __inst_mod)) break;
2947    if (ticksdel != 0ULL) return(TRUE);
2948    break;
2949   default: break;
2950  }
2951  return(FALSE);
2952 }
2953 
2954 /*
2955  * PUTV CHECKING ROUTINES
2956  */
2957 
2958 /*
2959  * routine to check combination of dtyp (flag with vpiReturnEvent) and object
2960  * for put value - emits errors and return F on error
2961  *
2962  * this requires pushed itree context
2963  */
chk_putv_args(word32 dtyp,struct h_t * hp,p_vpi_value value_p)2964 static int32 chk_putv_args(word32 dtyp, struct h_t *hp, p_vpi_value value_p)
2965 {
2966  register struct hrec_t *hrp;
2967  register struct net_t *np;
2968  char s1[RECLEN];
2969 
2970  hrp = hp->hrec;
2971  switch (dtyp) {
2972   case vpiCancelEvent:
2973    /* this can be reg (also var) or scalar net or bit of vector net */
2974    if (hrp->htyp != vpiSchedEvent && hrp->htyp != vpiSchedBitEvent)
2975     {
2976      __vpi_err(1904, vpiError,
2977       "vpi_put_value flag vpiCancelEvent requires vpiSchedEvent or vpiSchedBitEvent - %s passed",
2978       __to_vpionam(__wrks1, hrp->htyp));
2979      return(FALSE);
2980     }
2981    break;
2982   case vpiAddDriver:
2983    if (hrp->htyp == vpiNetBit)
2984     {
2985      if (hrp->bith_ndx) np = hrp->hu.hnp;
2986      else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
2987 
2988      /* DBG remove --- */
2989      if (!np->n_isavec) __vpi_terr(__FILE__, __LINE__);
2990      /* ---*/
2991     }
2992    else if (hrp->htyp == vpiNet) np = hrp->hu.hnp;
2993    else
2994     {
2995      __vpi_err(1903, vpiError,
2996       "vpi_put_value flag vpiAddDriver object %s illegal not vpiNet or vpiNetBit",
2997       __to_vpionam(__wrks1, hrp->htyp));
2998      return(FALSE);
2999     }
3000    /* DBG remove --- */
3001    if (np->ntyp >= NONWIRE_ST) __vpi_terr(__FILE__, __LINE__);
3002    /* --- */
3003    if (np->n_gone) goto net_gone;
3004    /* can not add driver getpat lhs wire - can only have one driver */
3005    if (net_ongetpat_lhs(np))
3006     {
3007      putv_flag_to_str(s1, dtyp);
3008      __vpi_err(1913, vpiError,
3009       "vpi_put_value %s flag wire %s part of $getpattern lvalue concatenate illegal - can only have one driver",
3010       s1, np->nsym->synam);
3011      return(FALSE);
3012     }
3013    /* SJM 03/23/00 - now because global nodes are XMRs can add */
3014    break;
3015   case vpiForceFlag: case vpiReleaseFlag:
3016    /* can not force/release vpi added driver terminals only nets and bits of */
3017    /* force release always immediate */
3018    switch (hrp->htyp) {
3019     case vpiNetBit:
3020      if (hrp->bith_ndx) np = hrp->hu.hnp;
3021      else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
3022 
3023      if (np->n_gone) goto net_gone;
3024      break;
3025     case vpiIntegerVar: case vpiTimeVar: case vpiReg: case vpiNet:
3026      np = hrp->hu.hnp;
3027      if (np->n_gone) goto net_gone;
3028      break;
3029     case vpiRegBit: case vpiVarSelect:
3030      putv_flag_to_str(s1, dtyp);
3031      __vpi_err(1914, vpiError,
3032       "vpi_put_value illegal %s flag for vpiRegBit/vpiVarSelect - entire variable only", s1);
3033      return(FALSE);
3034     default:
3035      putv_flag_to_str(s1, dtyp);
3036      __vpi_err(1915, vpiError,
3037       "vpi_put_value %s flag object %s illegal - must be variable or variable bit",
3038       s1, __to_vpionam(__wrks1, hrp->htyp));
3039      return(FALSE);
3040    }
3041    break;
3042   case vpiNoDelay: case vpiInertialDelay: case vpiTransportDelay:
3043   case vpiPureTransportDelay:
3044    if (!good_value_p(value_p)) return(FALSE);
3045    /* net type specific checking */
3046    switch (hrp->htyp) {
3047     case vpiReg: case vpiIntegerVar: case vpiTimeVar: case vpiRealVar:
3048      np = hrp->hu.hnp;
3049      break;
3050     case vpiRegBit: case vpiVarSelect: case vpiMemoryWord:
3051      /* can assign to (but not force release) reg that is word32 of array */
3052      if (hrp->bith_ndx) np = hrp->hu.hnp;
3053      else np = hrp->hu.hxp->lu.x->lu.sy->el.enp;
3054      break;
3055     case vpiNetDriver:
3056      np = hrp->hu.hnpp->elnpp.enp;
3057      if (np->n_stren && np->n_isavec)
3058       {
3059        putv_flag_to_str(s1, dtyp);
3060        __vpi_err(2012, vpiWarning,
3061         "vpi_put_value %s flag to vpiNetDriver strength vector object width %d will only assign to low bit - use vpiNetBitDriver",
3062        s1, np->nwid);
3063       }
3064      /* LOOKATME - maybe need warning for strength wire non strength format */
3065      break;
3066     case vpiNetBitDriver:
3067      np = hrp->hu.hnpp->elnpp.enp;
3068      /* LOOKATME - maybe need warning for strength wire non strength format */
3069      break;
3070     case vpiSpecParam: case vpiParameter:
3071      /* special case immediate assigns only */
3072      if (dtyp != vpiNoDelay)
3073       {
3074 nd_nodel:
3075        putv_flag_to_str(s1, dtyp);
3076        __vpi_err(1844, vpiError,
3077         "vpi_put_value to %s object only vpiNoDelay flag allowed - %s illegal",
3078         __to_vpionam(__wrks1, hrp->htyp), s1);
3079        return(FALSE);
3080       }
3081      np = hrp->hu.hnp;
3082      break;
3083     case vpiSysFuncCall:
3084      if (dtyp != vpiNoDelay) goto nd_nodel;
3085      /* handle is function call expr. */
3086      return(TRUE);
3087     case vpiUdpDefn:
3088      if (dtyp != vpiNoDelay) goto nd_nodel;
3089      /* will extract the needed 1 scalar bit form any value_p - no extra */
3090      /* checking needed */
3091      return(TRUE);
3092     case vpiNet: case vpiNetBit:
3093      /* SJM 07/24/00 - now supporting soft force (proc assign until next */
3094      /* driver change) for put value to wires */
3095      np = hrp->hu.hnp;
3096      break;
3097     default:
3098      putv_flag_to_str(s1, dtyp);
3099      __vpi_err(1919, vpiError,
3100       "vpi_put_value %s flag object %s illegal - must be non wire variable or bit of",
3101       s1, __to_vpionam(__wrks1, hrp->htyp));
3102      return(FALSE);
3103    }
3104    if (np->n_gone)
3105     {
3106 net_gone:
3107      putv_flag_to_str(s1, dtyp);
3108      __vpi_err(1911, vpiError,
3109       "vpi_put_value %s to net %s illegal - net removed by gate eater - rerun without +gateeater",
3110       s1, np->nsym->synam);
3111      return(FALSE);
3112     }
3113    break;
3114   default:
3115    __vpi_err(1916, vpiError,
3116     "vpi_put_value delay mode flag %u illegal value", dtyp);
3117    return(FALSE);
3118  }
3119  return(TRUE);
3120 }
3121 
3122 /*
3123  * convert a flag constant (with vpiReturnEvent bit removed) to its name
3124  */
putv_flag_to_str(char * s,word32 dtyp)3125 static char *putv_flag_to_str(char *s, word32 dtyp)
3126 {
3127  switch (dtyp) {
3128   case vpiAddDriver: strcpy(s, "vpiAddDriver"); break;
3129   case vpiCancelEvent: strcpy(s, "vpiCancelEvent"); break;
3130   case vpiForceFlag: strcpy(s, "vpiForceFlag"); break;
3131   case vpiReleaseFlag: strcpy(s, "vpiReleaseFlag"); break;
3132   case vpiNoDelay: strcpy(s, "vpiNoDelay"); break;
3133   case vpiInertialDelay: strcpy(s, "vpiInertial"); break;
3134   case vpiTransportDelay: strcpy(s, "vpiTransportDelay"); break;
3135   case vpiPureTransportDelay: strcpy(s, "vpiPureTransportDelay"); break;
3136   default: sprintf(s, "unknown (%lu)", dtyp);
3137  }
3138  return(s);
3139 }
3140 
3141 /*
3142  * return T if net is on getpattern lhs - can not putv assign to it
3143  */
net_ongetpat_lhs(struct net_t * np)3144 static int32 net_ongetpat_lhs(struct net_t *np)
3145 {
3146  register struct net_pin_t *npp;
3147  struct conta_t *cap;
3148 
3149  for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
3150   {
3151    if (npp->npntyp == NP_CONTA)
3152     {
3153      cap = npp->elnpp.ecap;
3154      if (cap->lhsx->getpatlhs) return(TRUE);
3155     }
3156   }
3157  return(FALSE);
3158 }
3159 
3160 /*
3161  * return T if value_p has good value that can be assigned from
3162  * also emits error
3163  */
good_value_p(p_vpi_value value_p)3164 static int32 good_value_p(p_vpi_value value_p)
3165 {
3166  int32 sval, s0, s1;
3167 
3168  if (value_p->format == vpiSuppressVal || value_p->format == vpiObjTypeVal)
3169   {
3170    if (value_p->format == vpiSuppressVal) strcpy(__wrks1, "vpiSuppressVal");
3171    else strcpy(__wrks1, "vpiObjTypeVal");
3172    __vpi_err(1908, vpiError,
3173     "vpi_put_value value_p record format %s illegal", __wrks1);
3174    return(FALSE);
3175   }
3176  /* strength value is only other one that can be checked */
3177  else if (value_p->format != vpiStrengthVal) return(TRUE);
3178 
3179  /* check strength value */
3180  sval = value_p->value.strength->logic;
3181  s0 = value_p->value.strength->s0;
3182  s1 = value_p->value.strength->s1;
3183  /* LOOKATME - XL seems to allow 0 to 7 but contradicts LRM and include */
3184  /* strength must be legal vpi_ constant value */
3185  if (__map_frvpi_stren(s0) == -1 || __map_frvpi_stren(s1) == -1)
3186   goto bad_stren;
3187  if (sval == vpiZ)
3188   {
3189    /* for z both must be high z */
3190    if (s0 != vpiHiZ || s1 != vpiHiZ) goto bad_stren;
3191   }
3192  else if (sval == vpiX)
3193   {
3194    /* for x, both can't be hiz - but can be edge of range */
3195    if (s0 == vpiHiZ && s1 != vpiHiZ) goto bad_stren;
3196   }
3197  else if (sval == vpi0 || sval == vpi1)
3198   {
3199    /* for 0 and 1 both can't be hiz */
3200    if (s0 == vpiHiZ && s1 == vpiHiZ) goto bad_stren;
3201   }
3202  else goto bad_stren;
3203  return(TRUE);
3204 
3205 bad_stren:
3206  __vpi_err(1924, vpiError,
3207   "vpi_put_value passed illegal strength value %d <s1=%d:s0=%d>",
3208   sval, s1, s0);
3209  return(FALSE);
3210 }
3211 
3212 /*
3213  * PUTV DESCHEDULING ROUTINES
3214  */
3215 
3216 /*
3217  * free one putv scheduled - handle is vpiSchedEvent or vpiSchedBitEvent
3218  *
3219  * this can be either schedule reg putv assign or net driver putv change
3220  * or net soft force putv assign
3221  *
3222  * reg/soft force can be one bit or entire reg but only one scheduled event
3223  * always entire reg even if one bit select because vectored
3224  *
3225  * for wire this can either be bit of vectored (vpiSchedBitEvent) or special
3226  * array (one for each bit) or just the one for scalared (vpiSchedEvent)
3227  *
3228  * notice users responsibility to make sure event not occurred because
3229  * storage this handle points to may be gone if user does not check
3230  * and calls will core dump
3231  */
free_putv_sched(struct h_t * hp)3232 static void free_putv_sched(struct h_t *hp)
3233 {
3234  register int32 bi;
3235  register i_tev_ndx tevpi;
3236  register struct hrec_t *hrp;
3237  i_tev_ndx *evtabi;
3238  struct net_t *np;
3239  struct tev_t *tevp;
3240 
3241  hrp = hp->hrec;
3242  /* does nothing if event completed (or maybe already cancelled) */
3243  if (hrp->evnt_done) return;
3244 
3245  /* case 1: vpi Sched Event and not scalar */
3246  if (hrp->bith_ndx)
3247   {
3248    /* table form only for vectored entire wire scheduled */
3249    /* cancel each bit event that has not already been canceled or happened */
3250    np = hrp->hu.hevrec->evnp;
3251    evtabi = hrp->hu.hevrec->evndxtab;
3252    for (bi = np->nwid - 1; bi >= 0; bi--)
3253     {
3254      tevpi = evtabi[bi];
3255      if (tevpi == -1 || __tevtab[tevpi].te_cancel) continue;
3256      free_netbitdrv_putv_sched(np, bi, hp->hin_itp, tevpi);
3257     }
3258    /* LOOKATME - maybe should free table here? */
3259    hrp->evnt_done = TRUE;
3260    return;
3261   }
3262  tevpi = hrp->hu.htevpi;
3263  tevp = &(__tevtab[tevpi]);
3264  np = tevp->tu.teputvp->np;
3265 
3266  /* case 2: reg putv assign (not driver) - can be bit or entire vector */
3267  /* but in both case only one event */
3268  /* SJM 07/25/00 - also free soft force event here */
3269  /* here hp set to done if event canceled */
3270  if (np->ntyp >= NONWIRE_ST || tevp->vpi_regwir_putv)
3271   {
3272    free_regwir_putv_sched(np, hp->hin_itp, tevpi);
3273    hrp->evnt_done = TRUE;
3274    return;
3275   }
3276 
3277  /* case 3: scheduled scalar wire or bit of vectored wire */
3278  if (!np->n_isavec) bi = 0; else bi = __tevtab[tevpi].tu.teputvp->nbi;
3279  free_netbitdrv_putv_sched(np, bi, hp->hin_itp, tevpi);
3280  hrp->evnt_done = TRUE;
3281 }
3282 
3283 /*
3284  * free putv scheduled reg or wire soft force event either entire net or bit
3285  */
free_regwir_putv_sched(struct net_t * np,struct itree_t * itp,i_tev_ndx tevpi)3286 static void free_regwir_putv_sched(struct net_t *np, struct itree_t *itp,
3287  i_tev_ndx tevpi)
3288 {
3289  register struct dltevlst_t *dlp;
3290  struct teputv_t *tepvp;
3291 
3292  tepvp = __tevtab[tevpi].tu.teputvp;
3293  dlp = np->regwir_putv_tedlst[itp->itinum];
3294  /* find event */
3295  for (; dlp != NULL; dlp = dlp->terp)
3296   { if (tevpi == dlp->tevpi) goto found_event; }
3297 
3298 found_event:
3299  /* link out event - case 1: at front */
3300  if (dlp->telp == NULL)
3301   {
3302    np->regwir_putv_tedlst[itp->itinum] = dlp->terp;
3303    if (dlp->terp != NULL) dlp->terp->telp = NULL;
3304   }
3305  /* case 2: at end and list longer than 1 */
3306  else if (dlp->terp == NULL) dlp->telp->terp = NULL;
3307  /* case 3: inside - excise out dlp */
3308  else { dlp->telp->terp = dlp->terp; dlp->terp->telp = dlp->telp; }
3309 
3310  /* never strength but can be entire vector or 1 bit for reg bit object */
3311  if (tepvp->nbi == -1)
3312   __my_free((char *) tepvp->putv_wp, 2*wlen_(np->nwid)*WRDBYTES);
3313  else __my_free((char *) tepvp->putv_wp, 2*WRDBYTES);
3314 
3315  tepvp->putv_wp = NULL;
3316  /* free te putv by linking on free list */
3317  tepvp->np =  (struct net_t *) __teputvfreelst;
3318  __teputvfreelst = tepvp;
3319  /* done with dlp */
3320  dlp->terp = __dltevfreelst;
3321  __dltevfreelst = dlp;
3322  /* finally empty the event (not really needed) */
3323  __tevtab[tevpi].tu.teputvp = NULL;
3324  __tevtab[tevpi].te_cancel = TRUE;
3325 }
3326 
3327 /*
3328  * free a putv scheduled net driver bit event
3329  * scalar possible where index is 0 not -1
3330  */
free_netbitdrv_putv_sched(struct net_t * np,int32 bi,struct itree_t * itp,i_tev_ndx tevpi)3331 static void free_netbitdrv_putv_sched(struct net_t *np, int32 bi,
3332  struct itree_t *itp, i_tev_ndx tevpi)
3333 {
3334  register struct dltevlst_t *dlp;
3335  int32 evi;
3336  struct teputv_t *tepvp;
3337  struct vpi_drv_t *vpidrvp;
3338 
3339  evi = np->nwid*itp->itinum + bi;
3340  tepvp = __tevtab[tevpi].tu.teputvp;
3341  vpidrvp = np->vpi_ndrvs[tepvp->di];
3342  dlp = vpidrvp->putv_drv_tedlst[evi];
3343 
3344  /* find event */
3345  for (; dlp != NULL; dlp = dlp->terp)
3346   { if (tevpi == dlp->tevpi) goto found_event; }
3347 
3348 found_event:
3349  /* link out event - case 1: at front */
3350  if (dlp->telp == NULL)
3351   {
3352    vpidrvp->putv_drv_tedlst[evi] = dlp->terp;
3353    if (dlp->terp != NULL) dlp->terp->telp = NULL;
3354   }
3355  /* case 2: at end and list longer than 1 */
3356  else if (dlp->terp == NULL) dlp->telp->terp = NULL;
3357  /* case 3: inside - excise out dlp */
3358  else { dlp->telp->terp = dlp->terp; dlp->terp->telp = dlp->telp; }
3359 
3360  /* always 1 bit */
3361  __my_free((char *) tepvp->putv_wp, 2*WRDBYTES);
3362 
3363  tepvp->putv_wp = NULL;
3364  /* free te putv by linking on free list */
3365  tepvp->np =  (struct net_t *) __teputvfreelst;
3366  __teputvfreelst = tepvp;
3367  /* done with dlp */
3368  dlp->terp = __dltevfreelst;
3369  __dltevfreelst = dlp;
3370  /* finally empty the event (not really needed) */
3371  __tevtab[tevpi].tu.teputvp = NULL;
3372  __tevtab[tevpi].te_cancel = TRUE;
3373 }
3374 
3375 /*
3376  * ROUTINES TO DYNAMICALLY ADD VPI DRIVER (TERMINAL) TO NET
3377  */
3378 
3379 /*
3380  * dynamically add a vpi put value record for entire net
3381  * construct driver object
3382  *
3383  * vpi put value driver and scheduled record allocated when driver terminal
3384  * added using vpi_put_value with flag vpiAddDriver (this routine does it)
3385  *
3386  * only needed for vpi_ since only one possibly added tf_ driver can be added
3387  * during prep because only works across systf arguments and must be registered
3388  * in available at compile time fixed table
3389  *
3390  * added driver always initialized to hiz
3391  *
3392  * called with current itree loc on itree stack
3393  * LOOKATME - maybe need error for "vectored" wire
3394  */
add_net_driver(struct h_t * hp)3395 static struct h_t *add_net_driver(struct h_t *hp)
3396 {
3397  register int32 di;
3398  register struct vpi_drv_t *vpidrvp;
3399  int32 drvi, osize, nsize;
3400  struct mod_t *mdp;
3401  struct net_t *np;
3402  struct net_pin_t *npp;
3403  struct xstk_t *xsp;
3404  struct h_t *hp2;
3405 
3406  mdp = hp->hin_itp->itip->imsym->el.emdp;
3407  np = hp->hrec->hu.hnp;
3408  push_xstk_(xsp, np->nwid);
3409  /* build and initialize the added driver - maybe just set some active bits */
3410  /* case 1: no drivers */
3411  if (np->vpi_ndrvs == NULL)
3412   {
3413    vpidrvp = alloc_vpidrv(np, mdp->flatinum);
3414    /* allocate driving values and initialize to z */
3415    putv_drvwp_allocinit(mdp, np, vpidrvp, TRUE);
3416 
3417    /* build the table will nil ptr fence one past end */
3418    np->vpi_ndrvs =
3419     (struct vpi_drv_t **) __my_malloc(2*sizeof(struct vpi_drv_t *));
3420    np->vpi_ndrvs[0] = vpidrvp;
3421    np->vpi_ndrvs[1] = NULL;
3422    drvi = 0;
3423    /* since new, know will be unused */
3424    __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_hasdrv, np->nwid);
3425    goto set_vec_used;
3426   }
3427  /* case 2: some drivers and one has all vector bits for cur. itree unused */
3428  for (di = 0;; di++)
3429   {
3430    if ((vpidrvp = np->vpi_ndrvs[di]) == NULL) break;
3431 
3432    __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_hasdrv, np->nwid);
3433    if (vval_is0_(xsp->ap, np->nwid)) { drvi = di; goto set_vec_used; }
3434   }
3435  /* case 3: need to add new (after first) driver in pos. di */
3436  if (di >= MAXNUMPORTS)
3437   {
3438    char s1[RECLEN];
3439 
3440    strcpy(s1, np->nsym->synam);
3441    __pv_terr(326,
3442     "INTERNAL FATAL - more than %d vpi wire drivers added to %s - contact Pragmatic C",
3443      MAXNUMPORTS, s1);
3444   }
3445  /* alloc and fill new every inst. and every bit driver - marks inst. used */
3446  vpidrvp = alloc_vpidrv(np, mdp->flatinum);
3447  /* allocate driving values and initialize to z */
3448  putv_drvwp_allocinit(mdp, np, vpidrvp, TRUE);
3449 
3450  /* realloc to increase size of table - set new driver and end fence */
3451  osize = (di + 1)*sizeof(struct vpi_drv_t *);
3452  nsize = osize + sizeof(struct vpi_drv_t *);
3453  np->vpi_ndrvs = (struct vpi_drv_t **)
3454   __my_realloc((char *) np->vpi_ndrvs, osize, nsize);
3455  np->vpi_ndrvs[di] = vpidrvp;
3456  np->vpi_ndrvs[di + 1] = NULL;
3457  drvi = di;
3458  __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_hasdrv, np->nwid);
3459 
3460 set_vec_used:
3461  /* know instance's has driver value loaded */
3462  one_allbits_(xsp->ap, np->nwid);
3463  __st_perinst_val(vpidrvp->vpi_hasdrv, np->nwid, xsp->ap, xsp->bp);
3464  __pop_xstk();
3465 
3466  /* convert to fi>1 (even if only the new vpi driver) */
3467  if (!np->n_multfi) chg_net_to_multfi(np, mdp);
3468 
3469 
3470  /* build and add the npp */
3471  __cur_npnum = 0;
3472  __cur_npnp = np;
3473  npp = __alloc_npin(NP_VPIPUTV, -1, -1);
3474  /* object number for vpi driver is index among many possible added drivers */
3475  npp->obnum = drvi;
3476  npp->npnxt = np->ndrvs;
3477  np->ndrvs = npp;
3478  /* DBG remove --- */
3479  if (__debug_flg)
3480   {
3481    __dbg_msg(
3482     ".. mod %s adding %s wire vpi_put_value driver to front\n",
3483     mdp->msym->synam, np->nsym->synam);
3484   }
3485  /* --- */
3486 
3487  /* build the driver handle */
3488  hp2 = (struct h_t *) __mk_handle(vpiNetDriver, (void *) npp, hp->hin_itp,
3489   NULL);
3490  return(hp2);
3491 }
3492 
3493 /*
3494  * allocate and initialize a vpi entire wire driver
3495  */
alloc_vpidrv(struct net_t * np,int32 insts)3496 static struct vpi_drv_t *alloc_vpidrv(struct net_t *np, int32 insts)
3497 {
3498  int32 nbytes;
3499  struct vpi_drv_t *vpidrvp;
3500 
3501  vpidrvp = (struct vpi_drv_t *) __my_malloc(sizeof(struct vpi_drv_t));
3502  nbytes = __get_pcku_chars(np->nwid, insts);
3503  vpidrvp->vpi_hasdrv.wp = (word32 *) __my_malloc(nbytes);
3504  /* to start no insts or bits have drivers */
3505  memset(vpidrvp->vpi_hasdrv.bp, 0, nbytes);
3506 
3507  /* need scheduled list for every bit of every inst */
3508  nbytes = insts*np->nwid*sizeof(struct dltevlst_t *);
3509  vpidrvp->putv_drv_tedlst = (struct dltevlst_t **) __my_malloc(nbytes);
3510  memset(vpidrvp->putv_drv_tedlst, 0, nbytes);
3511  return(vpidrvp);
3512 }
3513 
3514 /*
3515  * dynamically add a vpi put value record for one vpi net bit
3516  * construct driver object
3517  *
3518  * vpi put value driver and scheduled record allocated when driver terminal
3519  * added using vpi_put_value with flag vpiAddDriver (this routine does it)
3520  *
3521  * only needed for vpi_ since only one possibly added tf_ driver can be added
3522  * during prep because only works across systf arguments and must be registered
3523  * in available at compile time fixed table
3524  *
3525  * even for bit case always add entire wire driver
3526  *
3527  * added driver always initialized to hiz
3528  *
3529  * called with current itree loc on itree stack
3530  * LOOKATME - maybe need error for "vectored" wire
3531  */
add_netbit_driver(struct h_t * hp)3532 static struct h_t *add_netbit_driver(struct h_t *hp)
3533 {
3534  register int32 di;
3535  word32 val;
3536  int32 bi, drvi, osize, nsize;
3537  struct mod_t *mdp;
3538  struct net_t *np;
3539  struct net_pin_t *npp;
3540  struct vpi_drv_t *vpidrvp;
3541  struct xstk_t *xsp;
3542  struct h_t *hp2;
3543 
3544  mdp = hp->hin_itp->itip->imsym->el.emdp;
3545  bi = get_vpibit_index(&np, hp);
3546  push_xstk_(xsp, np->nwid);
3547  /* build and initialize the added driver - maybe just set some active bits */
3548  /* case 1: no drivers */
3549  if (np->vpi_ndrvs == NULL)
3550   {
3551    vpidrvp = alloc_vpidrv(np, mdp->flatinum);
3552    /* allocate driving values and initialize to z */
3553    putv_drvwp_allocinit(mdp, np, vpidrvp, TRUE);
3554 
3555    /* build the table will nil ptr fence one past end */
3556    np->vpi_ndrvs =
3557     (struct vpi_drv_t **) __my_malloc(2*sizeof(struct vpi_drv_t *));
3558    np->vpi_ndrvs[0] = vpidrvp;
3559    np->vpi_ndrvs[1] = NULL;
3560    drvi = 0;
3561    __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_hasdrv, np->nwid);
3562    goto set_bit_used;
3563   }
3564  /* case 2: some drivers and one has all vector bits for cur. itree unused */
3565  for (di = 0;; di++)
3566   {
3567    if ((vpidrvp = np->vpi_ndrvs[di]) == NULL) break;
3568    /* b part unused */
3569    __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_hasdrv, np->nwid);
3570    val = rhsbsel_(xsp->ap, bi);
3571    if (val == 0) { drvi = di; goto set_bit_used; }
3572   }
3573  /* case 3: need to add new (after first) driver in pos. di */
3574  if (di >= MAXNUMPORTS)
3575   {
3576    char s1[RECLEN];
3577 
3578    strcpy(s1, np->nsym->synam);
3579    __pv_terr(326,
3580     "INTERNAL FATAL - more than %d vpi wire drivers added to %s - contact Pragmatic C",
3581      MAXNUMPORTS, s1);
3582   }
3583  /* alloc and fill new every inst. and every bit driver - marks inst. used */
3584  vpidrvp = alloc_vpidrv(np, mdp->flatinum);
3585  /* allocate driving values and initialize to z */
3586  putv_drvwp_allocinit(mdp, np, vpidrvp, TRUE);
3587 
3588  /* realloc to increase size of table - set new driver and end fence */
3589  osize = (di + 1)*sizeof(struct vpi_drv_t *);
3590  nsize = osize + sizeof(struct vpi_drv_t *);
3591  np->vpi_ndrvs = (struct vpi_drv_t **)
3592   __my_realloc((char *) np->vpi_ndrvs, osize, nsize);
3593  np->vpi_ndrvs[di] = vpidrvp;
3594  np->vpi_ndrvs[di + 1] = NULL;
3595  drvi = di;
3596 
3597 set_bit_used:
3598  /* set the one inst-bit that is used */
3599  val = 1;
3600  __lhsbsel(xsp->ap, bi, val);
3601  __st_perinst_val(vpidrvp->vpi_hasdrv, np->nwid, xsp->ap, xsp->bp);
3602  __pop_xstk();
3603 
3604  /* convert to fi>1 (even if only the new vpi driver) */
3605  if (!np->n_multfi) chg_net_to_multfi(np, mdp);
3606 
3607  /* build and add the npp */
3608  __cur_npnum = 0;
3609  __cur_npnp = np;
3610  npp = __alloc_npin(NP_VPIPUTV, bi, bi);
3611 
3612  /* object number for vpi driver is index among many possible added drivers */
3613  npp->obnum = drvi;
3614  npp->npnxt = np->ndrvs;
3615  np->ndrvs = npp;
3616  /* DBG remove --- */
3617  if (__debug_flg)
3618   {
3619    __dbg_msg(
3620     ".. mod %s adding %s[%d] wire bit vpi_put_value driver to front\n",
3621     mdp->msym->synam, np->nsym->synam, bi);
3622   }
3623  /* --- */
3624 
3625  /* build the driver handle - always bith ndx form */
3626  hp2 = (struct h_t *) __mk_handle(vpiNetBitDriver, (void *) npp, hp->hin_itp,
3627   NULL);
3628  hp2->hrec->hi = bi;
3629  return(hp2);
3630 }
3631 
3632 /*
3633  * return T if instance itp of net np has vpi_ putv drivers for npp bits
3634  *
3635  * npp (NP VPIPUTV only) either entire wire or one bit
3636  * this needs instance to check to be on top of itree stack
3637  */
__has_vpi_driver(struct net_t * np,struct net_pin_t * npp)3638 extern int32 __has_vpi_driver(struct net_t *np, struct net_pin_t *npp)
3639 {
3640  int32 rv;
3641  word32 val;
3642  struct vpi_drv_t *vpidrvp;
3643  struct xstk_t *xsp;
3644 
3645  vpidrvp = np->vpi_ndrvs[npp->obnum];
3646  if ((vpidrvp = np->vpi_ndrvs[npp->obnum]) == NULL) return(FALSE);
3647  rv = FALSE;
3648  push_xstk_(xsp, np->nwid);
3649  __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_hasdrv, np->nwid);
3650  if (npp->npaux == NULL || npp->npaux->nbi1 == -1)
3651   {
3652    /* all bits must be one */
3653    if (__vval_is1(xsp->ap, np->nwid)) rv = TRUE;
3654    goto done;
3655   }
3656  /* bit select case */
3657  val = rhsbsel_(xsp->ap, npp->npaux->nbi1);
3658  if (val == 1) rv = TRUE;
3659 done:
3660  __pop_xstk();
3661  return(rv);
3662 }
3663 
3664 /*
3665  * reinitialize putvrec drivers for net
3666  * called when resetting from prep code
3667  *
3668  * there may be multiple so must loop thru until hitting ending fence
3669  *
3670  * leave the drivers (npps) and has drv bits sets but reset driving to z
3671  * and free vents
3672  */
__reinit_netdrvr_putvrec(struct net_t * np,struct mod_t * mdp)3673 extern void __reinit_netdrvr_putvrec(struct net_t *np, struct mod_t *mdp)
3674 {
3675  register int32 bi, di, ii;
3676  register struct dltevlst_t *dlp, *dlp2, *last_dlp;
3677  struct vpi_drv_t *vpidrvp;
3678 
3679  for (di = 0;; di++)
3680   {
3681    if ((vpidrvp = np->vpi_ndrvs[di]) == NULL) break;
3682 
3683    /* DBG remove -- */
3684    if (vpidrvp->vpi_drvwp.wp == NULL) __arg_terr(__FILE__, __LINE__);
3685    /* --- */
3686    putv_drvwp_allocinit(mdp, np, vpidrvp, FALSE);
3687 
3688    /* events will be in event queue and already freed */
3689    /* find last and link dlp's onto it */
3690    for (ii = 0; ii < mdp->flatinum; ii++)
3691     {
3692      /* ?? LOOKATME - this was low to high */
3693      for (bi = np->nwid - 1; bi >= 0; bi--)
3694       {
3695        if ((dlp = vpidrvp->putv_drv_tedlst[ii*np->nwid + bi]) == NULL)
3696         continue;
3697        last_dlp = NULL;
3698        for (dlp2 = dlp; dlp2 != NULL; dlp2 = dlp2->terp) last_dlp = dlp2;
3699        /* SJM 08/02/01 - add if too keep lint happy */
3700        if (last_dlp != NULL) last_dlp->terp = __dltevfreelst;
3701        __dltevfreelst = dlp;
3702        vpidrvp->putv_drv_tedlst[ii*np->nwid + bi] = NULL;
3703       }
3704     }
3705   }
3706 }
3707 
3708 /*
3709  * initialize and maybe allocate a a putv driver (only for wires)
3710  *
3711  * notice drivers are always one bit but need one per inst
3712  */
putv_drvwp_allocinit(struct mod_t * mdp,struct net_t * np,struct vpi_drv_t * vpidrvp,int32 nd_alloc)3713 static void putv_drvwp_allocinit(struct mod_t *mdp, struct net_t *np,
3714  struct vpi_drv_t *vpidrvp, int32 nd_alloc)
3715 {
3716  register int32 ii;
3717  int32 nbytes;
3718  byte *sbp;
3719  struct xstk_t *xsp;
3720 
3721  /* for wire need drivers */
3722  if (np->n_stren)
3723   {
3724    if (nd_alloc)
3725     sbp = vpidrvp->vpi_drvwp.bp = (byte *) __my_malloc(mdp->flatinum*np->nwid);
3726    else sbp = vpidrvp->vpi_drvwp.bp;
3727    set_byteval_(sbp, mdp->flatinum*np->nwid, ST_HIZ);
3728   }
3729  else
3730   {
3731    /* this is per inst. packed one bit non strength driver value */
3732    if (nd_alloc)
3733     {
3734      nbytes = __get_pcku_chars(np->nwid, mdp->flatinum);
3735      vpidrvp->vpi_drvwp.wp = (word32 *) __my_malloc(nbytes);
3736     }
3737    push_xstk_(xsp, np->nwid);
3738    zero_allbits_(xsp->ap, np->nwid);
3739    one_allbits_(xsp->bp, np->nwid);
3740    __push_wrkitstk(mdp, 0);
3741    for (ii = 0; ii < mdp->flatinum; ii++)
3742     {
3743      __inst_ptr->itinum = ii;
3744      __inum = ii;
3745      /* do not need mod con table here */
3746      __st_perinst_val(vpidrvp->vpi_drvwp, np->nwid, xsp->ap, xsp->bp);
3747     }
3748    __pop_wrkitstk();
3749    __pop_xstk();
3750   }
3751 }
3752 
3753 /*
3754  * change a wire from fi==1 to multi-fi - reorganize nl data structure
3755  *
3756  * find and set x_multfi bits on driving expressions
3757  * notice even if no drivers so really only 1 driver, vpi drivers always fi>1
3758  * i.e. will never see NP_VPIPUTV in old npp loop here
3759  */
chg_net_to_multfi(struct net_t * np,struct mod_t * mdp)3760 static void chg_net_to_multfi(struct net_t *np, struct mod_t *mdp)
3761 {
3762  register struct net_pin_t *npp;
3763  register int32 ii, bi;
3764  int32 lhslen;
3765  byte *sbp, *sbp2;
3766  struct gate_t *gp;
3767  struct conta_t *cap, *pbcap;
3768  struct mod_pin_t *mpp;
3769  struct xstk_t *xsp;
3770  struct inst_t *ip;
3771  struct expr_t *lhsxp;
3772  struct tfrec_t *tfrp;
3773  struct tfarg_t *tfap;
3774  struct mod_t *mdp2;
3775 
3776  np->n_multfi = TRUE;
3777  for (npp = np->ndrvs; npp != NULL; npp = npp->npnxt)
3778   {
3779    switch ((byte) npp->npntyp) {
3780     case NP_GATE:
3781      gp = npp->elnpp.egp;
3782      /* DBG remove ---
3783      if (gp->gpins[0]->x_multfi) __vpi_terr(__FILE__, __LINE__);
3784      --- */
3785      gp->gpins[0]->x_multfi = TRUE;
3786      /* set gchg assign routine to std unaccelerated since fi>1 now */
3787      __vpi_set_chg_proc(gp);
3788      /* must make sure all gate change events not yet processed use std */
3789      if (gp->schd_tevs != NULL)
3790       {
3791        for (ii = 0; ii < mdp->flatinum; ii++)
3792         {
3793          if (gp->schd_tevs[ii] != -1)
3794           __tevtab[gp->schd_tevs[ii]].gev_acc = FALSE;
3795         }
3796       }
3797      break;
3798     case NP_CONTA:
3799      cap = npp->elnpp.ecap;
3800      /* DBG remove ---
3801      if (cap->lhsx->x_multfi) __vpi_terr(__FILE__, __LINE__);
3802      --- */
3803      /* SJM 09/20/02 - per bit conta needs to process contained conta */
3804      /* and if any bits fi>1 all are */
3805      if (cap->ca_pb_sim)
3806       {
3807        /* must mark all per bit lhs expr, as per bit if any are */
3808        cap->lhsx->x_multfi = TRUE;
3809        for (bi = 0; bi < cap->lhsx->szu.xclen; bi++)
3810         {
3811          pbcap = &(cap->pbcau.pbcaps[npp->pbi]);
3812          pbcap->lhsx->x_multfi = TRUE;
3813          if (cap->ca_delrep != DT_NONE) break;
3814 
3815          /* DBG remove -- */
3816          if (pbcap->lhsx->szu.xclen != 1) __misc_terr(__FILE__, __LINE__);
3817          /* --- */
3818          __allocinit_perival(&pbcap->ca_drv_wp, mdp->flatinum, 1, TRUE);
3819          /* set value from rhs conta value - now fi>1 */
3820          for (ii = 0; ii < mdp->flatinum; ii++)
3821           {
3822            __push_itstk(mdp->moditps[ii]);
3823            xsp = __eval_xpr(pbcap->rhsx);
3824            __st_perinst_val(pbcap->ca_drv_wp, 1, xsp->ap, xsp->bp);
3825            __pop_xstk();
3826            __pop_itstk();
3827           }
3828         }
3829       }
3830      else
3831       {
3832        cap->lhsx->x_multfi = TRUE;
3833        /* if has delay, already using ca_drv_wp */
3834        if (cap->ca_delrep != DT_NONE) break;
3835 
3836        /* but if no delay must alloc and set schd/drv values */
3837        lhslen = cap->lhsx->szu.xclen;
3838        __allocinit_perival(&cap->ca_drv_wp, mdp->flatinum, lhslen, TRUE);
3839        /* set value from rhs conta value - now fi>1 */
3840        for (ii = 0; ii < mdp->flatinum; ii++)
3841         {
3842          __push_itstk(mdp->moditps[ii]);
3843          xsp = __eval_xpr(cap->rhsx);
3844          if (xsp->xslen != lhslen)
3845           {
3846            if (xsp->xslen < lhslen)
3847             {
3848              /* SJM 05/10/04 - if widening and signed, must sign extend */
3849              if (cap->rhsx->has_sign) __sgn_xtnd_widen(xsp, lhslen);
3850              else __sizchg_widen(xsp, lhslen);
3851             }
3852            else __sizchgxs(xsp, lhslen);
3853           }
3854 
3855          __st_perinst_val(cap->ca_drv_wp, lhslen, xsp->ap, xsp->bp);
3856          __pop_xstk();
3857          __pop_itstk();
3858         }
3859       }
3860      break;
3861     case NP_ICONN:
3862      /* SJM 04/21/00 - for non local drivers, must move use right itree loc */
3863      if (npp->npproctyp != NP_PROC_INMOD)
3864       {
3865        /* SJM 04/17/03 - if XMR path does not match do not change here */
3866        if (__move_to_npprefloc(npp))
3867         {
3868          mdp2 = __inst_ptr->itip->imsym->el.emdp;
3869          ip = &(mdp2->minsts[npp->elnpp.eii]);
3870          lhsxp = ip->ipins[npp->obnum];
3871          lhsxp->x_multfi = TRUE;
3872          /* need port for setting std assign routine */
3873          mpp = &(ip->imsym->el.emdp->mpins[npp->obnum]);
3874          __vpi_set_upiconnport_proc(mpp);
3875          __pop_itstk();
3876         }
3877        break;
3878       }
3879 
3880      /* assignment from down to up iconn - maybe >1 inst must no accelerate */
3881      /* LOOKATME - maybe could find some accelerating cases but xmr prob? */
3882      ip = &(mdp->minsts[npp->elnpp.eii]);
3883      lhsxp = ip->ipins[npp->obnum];
3884      /* DBG remove --- SJM 03/07/99
3885      if (lhsxp->x_multfi) __vpi_terr(__FILE__, __LINE__);
3886      --- */
3887      lhsxp->x_multfi = TRUE;
3888      /* need port for setting std assign routine */
3889      mpp = &(ip->imsym->el.emdp->mpins[npp->obnum]);
3890      __vpi_set_upiconnport_proc(mpp);
3891      break;
3892     case NP_MDPRT:
3893      /* the elnpp is module, but already have it */
3894      mpp = &(mdp->mpins[npp->obnum]);
3895      /* DBG remove --- SJM 10/18/99
3896      if (mpp->mpref->x_multfi) __vpi_terr(__FILE__, __LINE__);
3897      --- */
3898      mpp->mpref->x_multfi = TRUE;
3899      if (mpp->has_scalar_mpps)
3900       {
3901        for (bi = 0; bi < mpp->mpwide; bi++)
3902         {
3903          __vpi_set_downtomdport_proc(&(mpp->pbmpps[bi]), np);
3904         }
3905       }
3906      else __vpi_set_downtomdport_proc(mpp, np);
3907      break;
3908     case NP_TFRWARG:
3909      /* if this was previously fi==1, must change and alloc drv_wp */
3910      tfrp = npp->elnpp.etfrp;
3911      tfap = &(tfrp->tfargs[npp->obnum]);
3912      lhsxp = tfap->arg.axp;
3913      /* DBG remove ---
3914      if (lhsxp->x_multfi) __vpi_terr(__FILE__, __LINE__);
3915      --- */
3916      /* DBG remove --- */
3917      if (tfap->tfdrv_wp.wp != NULL) __vpi_terr(__FILE__, __LINE__);
3918      /* --- */
3919      lhslen = lhsxp->szu.xclen;
3920      lhsxp->x_multfi = TRUE;
3921      __alloc_tfdrv_wp(tfap, lhsxp, mdp);
3922      /* notice value from fi==1 case value of lhs expr - driver is hidden */
3923      /* must do this for every instance */
3924      for (ii = 0; ii < mdp->flatinum; ii++)
3925       {
3926        __push_itstk(mdp->moditps[ii]);
3927 
3928        xsp = __eval_xpr(lhsxp);
3929        /* here because lhs is width self determing should never differ */
3930        /* DBG remove */
3931        if (lhslen != xsp->xslen) __vpi_terr(__FILE__, __LINE__);
3932        /* -- */
3933        /* tf can drive strength */
3934        if (np->n_stren)
3935         __st_perinst_val(tfap->tfdrv_wp, lhslen, xsp->ap, xsp->bp);
3936        else
3937         {
3938          sbp = (byte *) xsp->ap;
3939          sbp2 = tfap->tfdrv_wp.bp;
3940          sbp2 = &(sbp2[lhslen*__inum]);
3941          memcpy(sbp2, sbp, lhslen);
3942         }
3943        __pop_xstk();
3944        __pop_itstk();
3945       }
3946      break;
3947     default: __vpi_terr(__FILE__, __LINE__);
3948    }
3949   }
3950 }
3951 
3952 /*
3953  * PUTV WORK ROUTINES
3954  */
3955 
3956 /*
3957  * get index for either net or bit of net
3958  */
__get_vpinet_index(struct net_t ** pnp,struct h_t * hp)3959 extern int32 __get_vpinet_index(struct net_t **pnp, struct h_t *hp)
3960 {
3961  register struct hrec_t *hrp;
3962  register int32 ndx;
3963 
3964  hrp = hp->hrec;
3965  /* can vpiVarSelect occur here? */
3966  switch (hrp->htyp) {
3967   case vpiRegBit: case vpiNetBit:
3968   case vpiMemoryWord: case vpiVarSelect:
3969    if (hrp->bith_ndx) { ndx = hrp->hi; *pnp = hrp->hu.hnp; }
3970    else
3971     {
3972      *pnp = hrp->hu.hxp->lu.x->lu.sy->el.enp;
3973      __push_itstk(hp->hin_itp);
3974      ndx = __comp_ndx(hrp->hu.hxp->lu.sy->el.enp, hrp->hu.hxp->ru.x);
3975      __pop_itstk();
3976      *pnp = hrp->hu.hxp->lu.x->lu.sy->el.enp;
3977     }
3978    return(ndx);
3979   default:
3980    ndx = -1;
3981    *pnp = hrp->hu.hnp;
3982  }
3983  return(ndx);
3984 }
3985 
3986 /*
3987  * get vpiNetBit or vpiRegBit index and net for cases where know Bit handle
3988  *
3989  * LOOKATME - maybe expr. form should be illegal here
3990  */
get_vpibit_index(struct net_t ** pnp,struct h_t * hp)3991 static int32 get_vpibit_index(struct net_t **pnp, struct h_t *hp)
3992 {
3993  register struct hrec_t *hrp;
3994  register int32 ndx;
3995 
3996  hrp = hp->hrec;
3997  if (hrp->bith_ndx)
3998   { ndx = hrp->hi; *pnp = hrp->hu.hnp; return(ndx); }
3999 
4000 
4001  __push_itstk(hp->hin_itp);
4002  ndx = __comp_ndx(hrp->hu.hxp->lu.sy->el.enp, hrp->hu.hxp->ru.x);
4003  __pop_itstk();
4004  *pnp = hrp->hu.hxp->lu.x->lu.sy->el.enp;
4005  return(ndx);
4006 }
4007 
4008 /*
4009  * convert a value_p value for a variable (handle) into an a/b value
4010  * on top of the expr stack
4011  * returns nil on bad value that can not be converted
4012  *
4013  * value on stack matches net (handle) in both type and width with zero fill
4014  * also matches strength with strong added if needed
4015  * this must run in itree location of handle in case value is time
4016  *
4017  * wnen strength need cast to byte ptr then assigns to low bit of it
4018  */
push_vpi_valuep(p_vpi_value value_p,int32 vwid,word32 vntyp,int32 vstren)4019 static struct xstk_t *push_vpi_valuep(p_vpi_value value_p, int32 vwid,
4020  word32 vntyp, int32 vstren)
4021 {
4022  register int32 wi;
4023  byte *sbp;
4024  word32 wval, wlen, ubits;
4025  int32 scanfmt, is_signed, s0val, s1val, i1;
4026  double d1;
4027  word64 timval;
4028  struct xstk_t *xsp;
4029 
4030  is_signed = FALSE;
4031  xsp = NULL;
4032  switch ((byte) value_p->format) {
4033    case vpiStringVal:
4034     /* SJM 07/11/01 - put value of c style string needs to be supported */
4035     xsp = __cstr_to_vval(value_p->value.str);
4036     /* SJM 07/30/01 - must change to vwid (net's width) - trunc or 0 fill */
4037     /* SJM 05/10/04 - vpi strings can't be signed */
4038     if (vwid != xsp->xslen) __sizchgxs(xsp, vwid);
4039     break;
4040    case vpiBinStrVal:
4041     scanfmt = 'b';
4042     strcpy(__wrks1, "vpiBinStrVal");
4043 do_xtract:
4044     /* extract value_p string into numeric value on tos */
4045     xsp = __putdstr_to_val(value_p->value.str, vwid, vwid, scanfmt);
4046     if (xsp == NULL)
4047      {
4048       __vpi_err(1917, vpiError,
4049        "vpi_put_value value_p record format %s value illegal", __wrks1);
4050       return(NULL);
4051      }
4052     /* if type of net is real must convert to double */
4053     if (vntyp == N_REAL)
4054      {
4055       d1 = __cnvt_stk_to_real(xsp, is_signed);
4056       __pop_xstk();
4057       push_xstk_(xsp, WBITS);
4058       memcpy(xsp->ap, &d1, sizeof(double));
4059       return(xsp);
4060      }
4061     break;
4062    case vpiOctStrVal:
4063     scanfmt = 'o';
4064     strcpy(__wrks1, "vpiOctStrVal");
4065     goto do_xtract;
4066    case vpiDecStrVal:
4067     scanfmt = 'd';
4068     strcpy(__wrks1, "vpiDecStrVal");
4069     if (vwid <= WBITS) is_signed = TRUE;
4070     goto do_xtract;
4071    case vpiHexStrVal:
4072     scanfmt = 'h';
4073     strcpy(__wrks1, "vpiHexStrVal");
4074     goto do_xtract;
4075 
4076    case vpiScalarVal:
4077     push_xstk_(xsp, vwid);
4078     zero_allbits_(xsp->ap, vwid);
4079     zero_allbits_(xsp->bp, vwid);
4080     wval = (word32) value_p->value.scalar;
4081     if (!chk_vpi_logicval(wval))
4082      {
4083       __vpi_err(1921, vpiError,
4084        "vpi_put_value vpiScalarVal passed illegal value %d", wval);
4085       __pop_xstk();
4086       return(NULL);
4087      }
4088     /* BEWARE this assume vpi[0,1,z,x] are 0, 1, 2, 3 as stored */
4089     xsp->ap[0] = (wval & 1L);
4090     xsp->bp[0] = (wval >> 1) & 1L;
4091     /* it is ok to convert scalar to real which is putved */
4092     if (vntyp == N_REAL)
4093      {
4094       d1 = __cnvt_stk_to_real(xsp, FALSE);
4095       __pop_xstk();
4096       push_xstk_(xsp, WBITS);
4097       memcpy(xsp->ap, &d1, sizeof(double));
4098       return(xsp);
4099      }
4100     break;
4101    case vpiIntVal:
4102     push_xstk_(xsp, vwid);
4103     zero_allbits_(xsp->ap, vwid);
4104     zero_allbits_(xsp->bp, vwid);
4105     /* know this must be good */
4106     xsp->ap[0] = (word32) value_p->value.integer;
4107     if (vntyp == N_REAL)
4108      {
4109       d1 = __cnvt_stk_to_real(xsp, is_signed);
4110       __pop_xstk();
4111       push_xstk_(xsp, WBITS);
4112       memcpy(xsp->ap, &d1, sizeof(double));
4113       return(xsp);
4114      }
4115     break;
4116    case vpiRealVal:
4117     /* destination not real */
4118     d1 = value_p->value.real;
4119     if (vntyp != N_REAL)
4120      {
4121       if (vntyp == N_INT)
4122        {
4123         i1 = (int32) d1;
4124         push_xstk_(xsp, vwid);
4125         xsp->ap[0] = (word32) i1;
4126         xsp->bp[0] = 0L;
4127         break;
4128        }
4129       if (!__real_to_v64tim(&timval, d1))
4130        {
4131         __vpi_err(2016, vpiWarning,
4132          "precision lost in converting real %g to 64 bit unsigned", d1);
4133        }
4134       push_xstk_(xsp, 64);
4135       xsp->ap[0] = (word32) (timval & WORDMASK_ULL);
4136       xsp->ap[1] = (word32) ((timval >> 32) & WORDMASK_ULL);
4137       xsp->bp[0] = xsp->bp[1] = 0L;
4138       /* SJM 05/10/04 - time can't be signed */
4139       if (vwid != 64) __sizchgxs(xsp, vwid);
4140       break;
4141      }
4142     /* value real and pushing real */
4143     push_xstk_(xsp, WBITS);
4144     memcpy(xsp->ap, &d1, sizeof(double));
4145     return(xsp);
4146    case vpiStrengthVal:
4147     /* know value_p is 1 bit strength and checked in chk putv already */
4148     wval = (word32) value_p->value.strength->logic;
4149     s0val = __map_frvpi_stren(value_p->value.strength->s0);
4150     s1val = __map_frvpi_stren(value_p->value.strength->s1);
4151     /* if value is strength, but putting to non strength use logic only */
4152     if (!vstren)
4153      {
4154       /* this forces 8 bytes */
4155       push_xstk_(xsp, 1);
4156       xsp->ap[0] = wval;
4157       xsp->bp[0] = 0L;
4158      }
4159     else
4160      {
4161       /* FIXME - should allow array of strengths here too */
4162       /* this forces 8 bytes */
4163       push_xstk_(xsp, 4);
4164       sbp = (byte *) xsp->ap;
4165       wval |= (((((byte) s0val) & 7L) << 5) | ((((byte) s1val) & 7L) << 2));
4166       sbp[0] = (byte) wval;
4167      }
4168     return(xsp);
4169    case vpiTimeVal:
4170     if (!__vpitime_to_ticks(&timval, value_p->value.time, __inst_mod)) break;
4171 
4172     push_xstk_(xsp, vwid);
4173     xsp->bp[0] = xsp->bp[1] = 0L;
4174     xsp->ap[0] = (word32) (timval & WORDMASK_ULL);
4175     xsp->ap[1] = (word32) ((timval >> 32) & WORDMASK_ULL);
4176     break;
4177    case vpiVectorVal:
4178     push_xstk_(xsp, vwid);
4179     wlen = wlen_(vwid);
4180     ubits = ubits_(vwid);
4181     for (wi = 0; wi < (int32) (wlen - 1); wi++)
4182      {
4183       xsp->ap[wi] = (word32) value_p->value.vector[wi].aval;
4184       xsp->bp[wi] = (word32) value_p->value.vector[wi].bval;
4185      }
4186     /* LOOKATME - P1364 problem since do not know width of vector here, */
4187     /* must 0 unused bits of high word32 from last used vector */
4188     /* if narrrowing works by accident but widening width change will */
4189     /* probably result in core dump - vector value_p should contain width */
4190     xsp->ap[wi] = ((word32) value_p->value.vector[wi].aval) & __masktab[ubits];
4191     xsp->bp[wi] = ((word32) value_p->value.vector[wi].bval) & __masktab[ubits];
4192 
4193     if (vntyp == N_REAL)
4194      {
4195       if (vwid > 64)
4196        {
4197         __vpi_err(1918, vpiError,
4198          "vpi_put_value value_p vpiVectorVal width %d too wide to convert to real",
4199          vwid);
4200         return(NULL);
4201        }
4202       d1 = __cnvt_stk_to_real(xsp, FALSE);
4203       __pop_xstk();
4204       push_xstk_(xsp, WBITS);
4205       memcpy(xsp->ap, &d1, sizeof(double));
4206       return(xsp);
4207      }
4208     return(xsp);
4209    default:
4210     __vpi_err(1925, vpiError,
4211      "vpi_put_value passed s_vpi_value format value %d illegal",
4212      value_p->format);
4213    return(NULL);
4214   }
4215  /* putting to strength value - must convert to 1 bid strength add strong */
4216  if (vstren)
4217   {
4218    /* convert only the one low bit */
4219    wval = (xsp->ap[0] & 1L) | ((xsp->bp[0] & 1L) << 1);
4220    __pop_xstk();
4221    push_xstk_(xsp, 4);
4222    sbp = (byte *) xsp->ap;
4223    s0val = s1val = __map_frvpi_stren(vpiStrongDrive);
4224    wval |= (((((byte) s0val) & 7L) << 5) | ((((byte) s1val) & 7L) << 2));
4225    sbp[0] = (byte) wval;
4226   }
4227  return(xsp);
4228 }
4229 
4230 /*
4231  * check a 0,1,x,z vpi logic value using vpi .h constants
4232  */
chk_vpi_logicval(word32 wval)4233 static int32 chk_vpi_logicval(word32 wval)
4234 {
4235  if (wval == vpi0 || wval == vpi1 || wval == vpiZ || wval == vpiX)
4236   return(TRUE);
4237  return(FALSE);
4238 }
4239 
4240 /*
4241  * PUTV FORCE AND RELEASE ROUTINES
4242  */
4243 
4244 /*
4245  * vpi_ force of entire register to constant value
4246  * force of entire reg only overrides possible active reg assign
4247  * (from statement, no vpi_ assign)
4248  *
4249  * SJM 06/19/02 - since vpi forces/assign only constant values never
4250  * have dces only unusual part is that qcval may need to be added at run
4251  * time - no run time dce changes needed
4252  */
reg_vpi_force(register struct net_t * np,word32 * ap,word32 * bp)4253 static void reg_vpi_force(register struct net_t *np, word32 *ap, word32 *bp)
4254 {
4255  register struct qcval_t *assgn_qcp, *frc_qcp;
4256  char s3[RECLEN], s4[RECLEN];
4257 
4258  strcpy(__wrks1, "");
4259  /* make sure force qcval allocated */
4260  if (!np->frc_assgn_allocated)
4261   {
4262    /* LOOKATME - since rhs value, any consequences of this at run time */
4263    /* SJM 12/23/02 - in src needed even when added from PLI */
4264    np->frc_assgn_allocated = TRUE;
4265    if (np->nu2.qcval == NULL) __alloc_qcval(np);
4266   }
4267  frc_qcp = &(np->nu2.qcval[2*__inum]);
4268  assgn_qcp = &(np->nu2.qcval[2*__inum + 1]);
4269  /* case 1, vpi_ force pending - must replace with new vpi form force */
4270  if (frc_qcp->qc_active)
4271   {
4272    frc_qcp->qcstp = NULL;
4273    frc_qcp->qcrhsbi = -1;
4274    frc_qcp->qclhsbi = -1;
4275    frc_qcp->lhsitp = NULL;
4276    strcat(__wrks1, " replace force");
4277   }
4278  /* if qc assign pending (both not possible), mark inactive but leave */
4279  /* body so can be reactivated on release */
4280  else if (assgn_qcp->qc_active)
4281   {
4282    assgn_qcp->qc_active = FALSE;
4283    strcat(__wrks1, " override assign");
4284   }
4285  else
4286   {
4287    /* LOOKATME - could avoid setting these since never used */
4288    frc_qcp->qcstp = NULL;
4289    frc_qcp->qcrhsbi = -1;
4290    frc_qcp->qclhsbi = -1;
4291    frc_qcp->lhsitp = NULL;
4292   }
4293  /* AIV 03/09/05 - inactive force was F must be T */
4294  frc_qcp->qc_active = TRUE;
4295  if (__debug_flg && __ev_tracing)
4296   {
4297    __tr_msg(":: vpi_put_value%s force of reg %s to %s in %s now %s\n",
4298     __wrks1, np->nsym->synam, __regab_tostr(s3, ap, bp, np->nwid, BHEX, FALSE),
4299     __msg2_blditree(s4, __inst_ptr), __to_timstr(__wrks2, &__simtime));
4300   }
4301  __chg_st_val(np, ap, bp);
4302  /* notice can have both many wire specific and many all cbs */
4303  if (__num_vpi_force_cbs > 0) __find_call_force_cbs(np, -1);
4304  if (__vpi_force_cb_always) __cb_all_rfs(np, -1, TRUE);
4305 }
4306 
4307 /*
4308  * implment vpi do release (caller handles getting value from original handle)
4309  * releasing reg with pending active assign re-establishes assign
4310  */
reg_vpi_release(register struct net_t * np)4311 static void reg_vpi_release(register struct net_t *np)
4312 {
4313  register struct qcval_t *assgn_qcp, *frc_qcp;
4314  char s3[RECLEN];
4315 
4316  strcpy(__wrks1, "");
4317  /* SJM 12/23/02 - logic was wrong if never allocated */
4318  /* if no force in src or added by PLI, nothing to do */
4319  if (np->frc_assgn_allocated) frc_qcp = &(np->nu2.qcval[2*__inum]);
4320  else frc_qcp = NULL;
4321 
4322  if (frc_qcp == NULL || !frc_qcp->qc_active)
4323   {
4324    __vpi_err(2101, vpiNotice,
4325    "attempted vpi_put_value release of reg %s in %s failed - never forced",
4326     np->nsym->synam, __msg2_blditree(__wrks2, __inst_ptr));
4327    goto done;
4328   }
4329  frc_qcp->qc_active = FALSE;
4330  __force_active = FALSE;
4331 
4332  /* if pending assign from statement - must reactivate it */
4333  assgn_qcp = &(np->nu2.qcval[2*__inum + 1]);
4334  if (assgn_qcp->qc_active)
4335   {
4336    /* do store and build dces in ref. itree loc. */
4337    /* this has assoc. stmt since assign only from Verilog statement */
4338    __do_qc_store(np, assgn_qcp, TRUE);
4339    __assign_active = TRUE;
4340    strcpy(__wrks1, " reactivating assign");
4341   }
4342  if (__debug_flg && __ev_tracing)
4343   {
4344    __tr_msg(":: vpi_put_value%s release of reg %s in %s now %s\n", __wrks1,
4345     np->nsym->synam, __msg2_blditree(s3, __inst_ptr),
4346     __to_timstr(__wrks2, &__simtime));
4347   }
4348  /* notice can have both many wire specific and many all cbs */
4349 done:
4350  if (__num_vpi_rel_cbs > 0) __find_call_rel_cbs(np, -1);
4351  if (__vpi_rel_cb_always) __cb_all_rfs(np, -1, FALSE);
4352 }
4353 
4354 /*
4355  * wire force is bit by bit unless vectored wire (when only entire wire)
4356  *
4357  * force which is for debugging overrides any wire delay assign
4358  * when wire change happens (wire event process) if force active, no assign
4359  */
wire_vpi_force(register struct net_t * np,word32 * ap,word32 * bp,register int32 ndx)4360 static void wire_vpi_force(register struct net_t *np, word32 *ap, word32 *bp,
4361  register int32 ndx)
4362 {
4363  register int32 bi, ibase;
4364  char s3[RECLEN];
4365 
4366  /* make sure assign/force table exists */
4367  if (!np->frc_assgn_allocated) __alloc_qcval(np);
4368 
4369  if (__debug_flg && __ev_tracing)
4370   {
4371    if (ndx == -1) strcpy(__wrks1, np->nsym->synam);
4372    else sprintf(__wrks1, "%s[%d]", np->nsym->synam,
4373     __unnormalize_ndx(np, ndx));
4374    __tr_msg(":: vpi_put_value force of wire %s in %s now %s\n", __wrks1,
4375     __msg2_blditree(__wrks2, __inst_ptr), __to_timstr(s3, &__simtime));
4376   }
4377 
4378  ibase = __inum*np->nwid;
4379  if (!np->n_isavec)
4380   {
4381    /* SJM 11/14/00 - must also check cbs for scalar case */
4382    __bit1_vpi_or_tran_wireforce(np, ap, bp, ibase, 0, 0, "vpi_put_value");
4383    ndx = -1;
4384    goto chk_cbs;
4385   }
4386 
4387  /* for vpi only 2 cases: one bit or entire wire */
4388  if (ndx == -1)
4389   {
4390    /* ?? LOOKATME - this was low to high */
4391    for (bi = np->nwid - 1; bi >= 0; bi--)
4392     {
4393      __bit1_vpi_or_tran_wireforce(np, ap, bp, ibase, bi, bi,
4394       "vpi_put_value");
4395     }
4396    ndx = -1;
4397   }
4398  else __bit1_vpi_or_tran_wireforce(np, ap, bp, ibase, ndx, 0, "vpi_put_value");
4399 
4400 chk_cbs:
4401  /* notice can have both many wire specific and many all cbs */
4402  if (__num_vpi_force_cbs > 0) __find_call_force_cbs(np, ndx);
4403  if (__vpi_force_cb_always) __cb_all_rfs(np, ndx, TRUE);
4404 }
4405 
4406 /*
4407  * do 1 bit vpi_ or switch channel form net/bit wire force
4408  * caller must insure qcval records exist
4409  *
4410  * select bit rhsbi from wp and force to value of lhsbi
4411  * must run in possible lhs xmr itree context
4412  *
4413  * 06/19/02 SJM - for new fixed for compilation dce algorithm these
4414  * same since no dces (vpi no dces because rhs value) and tran because
4415  * assigning to tran channel is what force is
4416  */
__bit1_vpi_or_tran_wireforce(struct net_t * np,word32 * ap,word32 * bp,int32 ibase,int32 lhsbi,int32 rhsbi,char * msg)4417 extern void __bit1_vpi_or_tran_wireforce(struct net_t *np, word32 *ap, word32 *bp,
4418  int32 ibase, int32 lhsbi, int32 rhsbi, char *msg)
4419 {
4420  register struct qcval_t *frc_qcp;
4421  register struct xstk_t *xsp, *xsp2;
4422  int32 bi;
4423  byte *sbp;
4424 
4425  /* even if currently forced indicate force active */
4426  bi = (lhsbi == -1) ? 0 : lhsbi;
4427  frc_qcp = &(np->nu2.qcval[ibase + bi]);
4428  frc_qcp->qc_active = TRUE;
4429 
4430  /* get the 1 bit onto stack */
4431  push_xstk_(xsp, 1);
4432  if (rhsbi != 0)
4433   {
4434    xsp->ap[0] = rhsbsel_(ap, rhsbi);
4435    xsp->bp[0] = rhsbsel_(bp, rhsbi);
4436   }
4437  else { xsp->ap[0] = ap[0] & 1L; xsp->bp[0] = bp[0] & 1L; }
4438 
4439  /* emit debug tracing message if needed */
4440  if (__debug_flg && __ev_tracing)
4441   {
4442    if (lhsbi == -1) strcpy(__wrks1, ""); else sprintf(__wrks1, "[%d]", lhsbi);
4443    __tr_msg("   %s force of %s into wire %s%s\n", msg,
4444     __regab_tostr(__wrks2, xsp->ap, xsp->bp, 1, BHEX, FALSE),
4445     np->nsym->synam, __wrks1);
4446   }
4447 
4448  /* quasi-continuous assign to strength wire always strong */
4449  if (np->n_stren)
4450   {
4451    push_xstk_(xsp2, 4);
4452    sbp = (byte *) xsp2->ap;
4453    __st_standval(sbp, xsp, ST_STRVAL);
4454    if (np->n_isavec) __chg_st_bit(np, lhsbi, (word32) sbp[0], 0L);
4455    else __chg_st_val(np, (word32 *) sbp, (word32 *) sbp);
4456    __pop_xstk();
4457   }
4458  else
4459   {
4460    if (np->n_isavec) __chg_st_bit(np, lhsbi, xsp->ap[0], xsp->bp[0]);
4461    else __chg_st_val(np, xsp->ap, xsp->bp);
4462   }
4463  __pop_xstk();
4464 }
4465 
4466 /*
4467  * after possible concat unwinding, exec the wire section release
4468  *
4469  * tricky part is need to force evaluation and store of all drivers
4470  *
4471  * LOOKATME - is there any reason can not just call multi driver eval
4472  * even for 1 or no driver case
4473  * LOOKATME - calling release vpi_ callbacks even if not forced
4474  */
wire_vpi_release(struct net_t * np,int32 ndx)4475 static void wire_vpi_release(struct net_t *np, int32 ndx)
4476 {
4477  register int32 bi, ibase;
4478  int32 biti, bitj, all_forced, none_forced;
4479  struct qcval_t *frc_qcp;
4480  char s3[RECLEN];
4481 
4482  if (!np->frc_assgn_allocated)
4483   {
4484    strcpy(__wrks1, " - no bits ever forced");
4485 no_force:
4486    if (ndx == -1) strcpy(__wrks2, np->nsym->synam);
4487    else sprintf(__wrks2, "%s[%d]", np->nsym->synam, __unnormalize_ndx(np, ndx));
4488    __vpi_err(2102, vpiNotice,
4489     "attempted vpi_put_value release of wire %s in %s failed%s", __wrks2,
4490     __msg2_blditree(s3, __inst_ptr), __wrks1);
4491    goto done;
4492   }
4493 
4494  if (__debug_flg && __ev_tracing)
4495   {
4496    if (ndx == -1) strcpy(__wrks2, np->nsym->synam);
4497    else sprintf(__wrks2, "%s[%d]", np->nsym->synam, __unnormalize_ndx(np, ndx));
4498    __tr_msg(":: vpi_put_value release of wire %s in %s now %s\n", __wrks2,
4499     __msg2_blditree(__wrks1, __inst_ptr), __to_timstr(s3, &__simtime));
4500   }
4501 
4502  /* possible for no active forces but still must check every bit */
4503  ibase = __inum*np->nwid;
4504  all_forced = TRUE;
4505  /* SJM 12/23/02 - must exec if frc qcp allocated but maybe none forced */
4506  none_forced = TRUE;
4507  if (ndx == -1) { biti = np->nwid - 1; bitj = 0; } else biti = bitj = ndx;
4508  for (bi = biti; bi >= bitj; bi--)
4509   {
4510    frc_qcp = &(np->nu2.qcval[ibase + bi]);
4511    if (!frc_qcp->qc_active) { all_forced = FALSE; continue; }
4512    /* notice this also turns off non vpi forces */
4513    frc_qcp->qc_active = FALSE;
4514    none_forced = FALSE;
4515   }
4516 
4517  if (none_forced)
4518   {
4519    strcpy(__wrks1, " - no bits currently forced");
4520    goto done;
4521   }
4522  /* release is immedate assign even if wire has delay no schedule */
4523  __assign_1mdrwire(np);
4524  if (!all_forced && ndx == -1)
4525   { strcpy(__wrks1, " - some bits forced"); goto no_force; }
4526 
4527 done:
4528  /* notice can have both many wire specific and many all cbs */
4529  if (__num_vpi_rel_cbs > 0) __find_call_rel_cbs(np, ndx);
4530  if (__vpi_rel_cb_always) __cb_all_rfs(np, ndx, FALSE);
4531 }
4532 
4533 /*
4534  * IMMEDIATE PUTV ASSIGN ROUTINES
4535  */
4536 
4537 /*
4538  * set return value for current user task or function only
4539  * must be called from current system function or error
4540  * this pushes and pops itree loc. from handle
4541  */
set_vpisfcall_retval(struct h_t * hp,p_vpi_value value_p)4542 static void set_vpisfcall_retval(struct h_t *hp, p_vpi_value value_p)
4543 {
4544  int32 sf_ind;
4545  p_vpi_systf_data tfdatp;
4546  struct sysfunc_t *sfbp;
4547  struct systftab_t *sfp;
4548  struct xstk_t *xsp;
4549  char s1[RECLEN];
4550 
4551  /* --- DBG remove --- */
4552  if (hp->hrec->hu.hxp == NULL) __vpi_terr(__FILE__, __LINE__);
4553  /* --- */
4554  if (hp->hrec->hu.hxp != __cur_sysf_expr)
4555   {
4556    if (__cur_sysf_expr == NULL)
4557     {
4558      sf_ind = __cur_sysf_expr->lu.x->lu.sy->el.esyftbp->syfnum;
4559      sf_ind -= (__last_veriusertf + 1);
4560      sfp = &(__systftab[sf_ind]);
4561      tfdatp = (p_vpi_systf_data) sfp->vpi_sytfdat;
4562      strcpy(s1, tfdatp->tfname);
4563     }
4564    else strcpy(s1, "**none called**");
4565 
4566    __vpi_err(1876, vpiError,
4567     "vpi_put_value of vpiSysFuncCall %s (return value) illegal - must use from calltf cb",
4568     s1);
4569    return;
4570   }
4571 
4572  sf_ind = __cur_sysf_expr->lu.x->lu.sy->el.esyftbp->syfnum;
4573  sf_ind -= (__last_veriusertf + 1);
4574  sfp = &(__systftab[sf_ind]);
4575  tfdatp = (p_vpi_systf_data) sfp->vpi_sytfdat;
4576  sfbp = sfp->sfu.sfbp;
4577  __push_itstk(hp->hin_itp);
4578  /* if error do not change global xsp */
4579  xsp = push_vpi_valuep(value_p, sfbp->retwid, sfbp->retntyp, FALSE);
4580  __pop_itstk();
4581  if (xsp == NULL) return;
4582  if (__cur_sysf_xsp->xslen != xsp->xslen) __vpi_terr(__FILE__, __LINE__);
4583  cp_walign_(__cur_sysf_xsp->ap, xsp->ap, xsp->xslen);
4584  cp_walign_(__cur_sysf_xsp->bp, xsp->bp, xsp->xslen);
4585  __pop_xstk();
4586 }
4587 
4588 /*
4589  * set either a def or specparam value - always per inst
4590  * not used for global params
4591  *
4592  * probably changes from PNUM to PISNUM rep
4593  * this never changes original param width and type (maybe real) so value
4594  * is converted to already determined type
4595  * user must define wide enough in source if used for delay annotation
4596  * or probably truncated with delay loss
4597  *
4598  * this pushes and pops itree loc. from handle
4599  */
set_vpiparam_val(struct h_t * hp,p_vpi_value value_p)4600 static void set_vpiparam_val(struct h_t *hp, p_vpi_value value_p)
4601 {
4602  register int32 wlen;
4603  register struct net_t *np;
4604  register word32 *wp;
4605  struct xstk_t *xsp;
4606  struct mod_t *mdp;
4607 
4608  np = hp->hrec->hu.hnp;
4609 
4610  __push_itstk(hp->hin_itp);
4611  mdp = hp->hin_itp->itip->imsym->el.emdp;
4612  /* DBG remove --- */
4613  if (!np->n_isaparam) __arg_terr(__FILE__, __LINE__);
4614  /* --- */
4615  /* if error nil, know xsp right width and type (i.e. maybe real) */
4616  xsp = push_vpi_valuep(value_p, np->nwid, np->ntyp, FALSE);
4617  if (xsp == NULL) goto done;
4618 
4619  /* DBG remove --- */
4620  if (np->nwid != xsp->xslen) __misc_terr(__FILE__, __LINE__);
4621  /* --- */
4622 
4623  /* change range rep to IS if needed */
4624  if (np->srep == SR_PNUM && mdp->flatinum > 1) __chg_param_tois(np, mdp);
4625  wlen = wlen_(np->nwid);
4626  wp = &(np->nva.wp[2*wlen*__inum]);
4627  memcpy(wp, xsp->ap, 2*WRDBYTES*wlen);
4628  __pop_xstk();
4629  /* final step is to re-compute (and prep) all delays param effects */
4630  /* if called after delay elaboration, param net pin d.s. will be nil */
4631  __re_prep_dels(np, hp->hin_itp, hp->hin_itp->itip->imsym->el.emdp, TRUE);
4632 
4633 done:
4634  __pop_itstk();
4635 }
4636 
4637 
4638 /*
4639  * set a vpi udp definition initial value
4640  * this pushes and pops itree loc. from handle
4641  *
4642  * this is per udp type
4643  * LOOKATME - LRM implies assign to vpiUdp primitive (i.e. per inst.)
4644  * this must be wrong
4645  */
set_vpiudpdef_ival(struct h_t * hp,p_vpi_value value_p)4646 static void set_vpiudpdef_ival(struct h_t *hp, p_vpi_value value_p)
4647 {
4648  word32 nival;
4649  struct udp_t *udpp;
4650  struct xstk_t *xsp;
4651 
4652  udpp = hp->hrec->hu.hudpp;
4653  /* if error nil, know xsp right width and type (i.e. maybe real) */
4654  xsp = push_vpi_valuep(value_p, 1, N_REG, FALSE);
4655  if (xsp == NULL) return;
4656 
4657  nival = xsp->ap[0] & ((xsp->bp[0] & 1L) << 1);
4658  __pop_xstk();
4659  if (nival == 2)
4660   {
4661    __vpi_err(1871, vpiError,
4662     "vpi_put_value of vpiUdpDefn initial value 1'bz illegal - value not changed");
4663    return;
4664   }
4665  udpp->ival = nival;
4666 }
4667 
4668 /*
4669  * immediate assign to vpi_ wire driver handle from value_p
4670  * assign one bit using npp's index
4671  *
4672  * this is entire net for immediate no delay case only but can be 1 bit scalar
4673  * know if net is strength ap will be sbp (push converts to stren if needed)
4674  */
immed_vpi_drv_assign(struct net_t * np,int32 di,word32 * ap,word32 * bp)4675 static void immed_vpi_drv_assign(struct net_t *np, int32 di, word32 *ap, word32 *bp)
4676 {
4677  byte *sbp, *sbp2;
4678  struct vpi_drv_t *vpidrvp;
4679 
4680  /* immedate assign to wire driver (handle is ptr to npp) */
4681  vpidrvp = np->vpi_ndrvs[di];
4682  /* update driver - for vpi_ strength always 1 bit (use low bit) */
4683  if (np->n_stren)
4684   {
4685    sbp = (byte *) ap;
4686    sbp2 = &(vpidrvp->vpi_drvwp.bp[__inum*np->nwid]);
4687    sbp2[0] = sbp[0];
4688   }
4689  /* assign entire vector */
4690  else __st_perinst_val(vpidrvp->vpi_drvwp, np->nwid, ap, bp);
4691 
4692  /* do fi>1 wire assign */
4693  /* handle fi>1 eval and store of bits - maybe in tran channel */
4694  /* LOOKATME - because of 1 bit only drivers this is inefficient because */
4695  /* muste re-eval all drivers of entire net */
4696  if (np->ntraux != NULL)
4697   {
4698    /* if hard drivers of np do not change, channel cannot change */
4699    /* SJM 12/18/00 - for tran/tranif switch channels may just add to list */
4700    if (__update_tran_harddrvs(np)) __eval_tran_bits(np);
4701   }
4702  else
4703   {
4704    if (np->nrngrep == NX_DWIR) __sched_1mdrwire(np);
4705    else __assign_1mdrwire(np);
4706   }
4707 }
4708 
4709 /*
4710  * immediate assign to vpi_ wire bit driver handle from value_p
4711  *
4712  * this is for vpi Net Bit Driver so can never be -1 (no bit for scalar)
4713  */
immed_vpibit_drv_assign(struct net_t * np,int32 di,int32 bi,word32 * ap,word32 * bp)4714 static void immed_vpibit_drv_assign(struct net_t *np, int32 di, int32 bi,
4715  word32 *ap, word32 *bp)
4716 {
4717  byte *sbp, *sbp2;
4718  struct vpi_drv_t *vpidrvp;
4719  struct xstk_t *xsp;
4720 
4721  vpidrvp = np->vpi_ndrvs[di];
4722  /* DBG remove --- */
4723  if (bi == -1) __vpi_terr(__FILE__, __LINE__);
4724  /* --- */
4725  /* update driver - for vpi_ strength always 1 bit (use low big) */
4726  if (np->n_stren)
4727   {
4728    sbp = (byte *) ap;
4729    sbp2 = &(vpidrvp->vpi_drvwp.bp[__inum*np->nwid + bi]);
4730    sbp2[0] = sbp[0];
4731   }
4732  /* low bit into 1 bit per inst. vector */
4733  else
4734   {
4735    push_xstk_(xsp, np->nwid);
4736    __ld_perinst_val(xsp->ap, xsp->bp, vpidrvp->vpi_drvwp, np->nwid);
4737    __lhsbsel(xsp->ap, bi, ap[0]);
4738    __lhsbsel(xsp->bp, bi, bp[0]);
4739    __st_perinst_val(vpidrvp->vpi_drvwp, np->nwid, xsp->ap, xsp->bp);
4740    __pop_xstk();
4741   }
4742  /* do fi>1 wire assign */
4743  /* handle fi>1 eval and store of bits - maybe in tran channel */
4744  /* LOOKATME - because of 1 bit only drivers this is inefficient because */
4745  /* muste re-eval all drivers of entire net */
4746  if (np->ntraux != NULL)
4747   {
4748    /* if hard drivers of np do not change, channel cannot change */
4749    /* SJM 12/18/00 - for tran/tranif switch channels may just add to list */
4750    if (__update_tran_harddrvs(np)) __eval_tran_bits(np);
4751   }
4752  else
4753   {
4754    if (np->nrngrep == NX_DWIR) __sched_1mdrwire(np);
4755    else __assign_1mdrwire(np);
4756   }
4757 }
4758 
4759 /*
4760  * VPI EVENT PROCESSING ROUTINES
4761  */
4762 
4763 /*
4764  * process a vpi put value handle assign event
4765  *
4766  * for regs (also variables) array words, and variable bits
4767  * and wires (here softforce is used)
4768  *
4769  * assigning either entire reg or reg bit but only one pending event allowed
4770  *
4771  * SJM 07/22/00 - although originally for regs also used for soft force
4772  * of wire
4773  * SJM 11/14/00 - now wire soft force is more like wire force except no
4774  * release
4775  */
__process_vpi_varputv_ev(i_tev_ndx tevpi)4776 extern void __process_vpi_varputv_ev(i_tev_ndx tevpi)
4777 {
4778  register struct net_t *np;
4779  register struct dltevlst_t *dlp;
4780  register word32 *ap, *bp;
4781  register struct h_t *hp;
4782  int32 wlen;
4783  struct teputv_t *tepvp;
4784 
4785  tepvp = __tevtab[tevpi].tu.teputvp;
4786  __tevtab[tevpi].tu.teputvp = NULL;
4787 
4788  np = tepvp->np;
4789  if (__ev_tracing) emit_vpiputv_evtrmsg(np, tepvp, tepvp->nbi);
4790 
4791  /* if putv scheduled event saved, turn on event happened flag in handle */
4792  /* because since user has handle later incorrect cancel might be tried */
4793  /* for registers only only event per inst allowed (i.e lhs bsel or assign) */
4794  if ((hp = tepvp->evnt_hp) != NULL) hp->hrec->evnt_done = TRUE;
4795  /* do the proc. assign, or driver change and fi>1 eval */
4796  wlen = wlen_(np->nwid);
4797  ap = tepvp->putv_wp;
4798  bp = &(ap[wlen]);
4799 
4800  if (np->ntyp < NONWIRE_ST)
4801   {
4802    /* following acc_ routines, no delay set ignored any pending assigns */
4803    /* SJM 11/14/00 - for soft force of in tran chan (inout), now soft */
4804    /* all wires in tran chan */
4805    /* SJM 03/15/01 - can't force all of tran channel - just soft force */
4806    /* this tran wire and re-eval tran channel */
4807    if (np->ntraux != NULL)
4808     {
4809       __tran_exec_putv_wire_softforce(np, ap, bp, tepvp->nbi);
4810       __eval_tran_1bit(np, tepvp->nbi);
4811      }
4812    else exec_putv_wire_softforce(np, ap, bp, tepvp->nbi);
4813   }
4814  /* reg assign event */
4815  else exec_putv_reg_assign(np, ap, bp, tepvp->nbi);
4816 
4817  /* free the the reg putv event auxiliary record - never strength*/
4818  __my_free((char *) ap, 2*wlen*WRDBYTES);
4819  dlp = np->regwir_putv_tedlst[__inum];
4820  np->regwir_putv_tedlst[__inum] = dlp->terp;
4821 
4822  /* link on putv event contents record free list */
4823  tepvp->np = (struct net_t *) __teputvfreelst;
4824  __teputvfreelst = tepvp;
4825 
4826  /* also link out dltevlst element - must be on front */
4827  /* DBGMAYBELEAVE */
4828  if (dlp == NULL || tevpi != dlp->tevpi) __vpi_terr(__FILE__, __LINE__);
4829  /* --- */
4830  dlp->telp = NULL;
4831  /* put this telst elemnt on free list */
4832  dlp->terp = __dltevfreelst;
4833  __dltevfreelst = dlp;
4834 }
4835 
4836 /*
4837  * emit a delayed scheduled vpi put_value trace message
4838  *
4839  * handled both reg proc. assign and driver assign of added vpi wire drvr
4840  */
emit_vpiputv_evtrmsg(struct net_t * np,struct teputv_t * tepvp,int32 nbi)4841 static void emit_vpiputv_evtrmsg(struct net_t *np, struct teputv_t *tepvp,
4842  int32 nbi)
4843 {
4844  int32 wid;
4845  word32 *ap, *bp;
4846  byte *sbp;
4847  char ts1[RECLEN], ts2[IDLEN], ts3[RECLEN], ts4[RECLEN];
4848 
4849  if (np->n_isarr)
4850   {
4851    sprintf(ts3, "array word32 %s[%d]", np->nsym->synam,
4852     __unnormalize_ndx(np, nbi));
4853    wid = np->nwid;
4854   }
4855  else if (nbi != -1)
4856   {
4857    sprintf(ts3, "%s %s[%d]", __to_wtnam(ts1, np), np->nsym->synam,
4858     __unnormalize_ndx(np, nbi));
4859    wid = 1;
4860   }
4861  else
4862   {
4863    sprintf(ts3, "%s %s", __to_wtnam(ts1, np), np->nsym->synam);
4864    wid = np->nwid;
4865   }
4866  if (np->ntyp >= NONWIRE_ST)
4867   {
4868    strcpy(ts1, "procedural");
4869    /* DBG remove --- */
4870    if (np->regwir_putv_tedlst == NULL) __vpi_terr(__FILE__, __LINE__);
4871    /* --- */
4872   }
4873  else
4874   {
4875    if (np->ntraux) strcpy(ts1, "vpi_ inout or tran channel driver");
4876    else if (np->n_multfi) strcpy(ts1, "vpi_ wire driver");
4877    /* SJM  11/25/0 - tracing also for soft force to wire - so fi==1 ok */
4878    /* and must leave wid as is */
4879    else strcpy(ts1, "wire");
4880   }
4881 
4882  /* strength must be driver - other can be one bit or reg width */
4883  if (np->n_stren)
4884   { sbp = (byte *) tepvp->putv_wp; __st_regab_tostr(ts2, sbp, 1); }
4885  else
4886   {
4887    ap = tepvp->putv_wp;
4888    bp = &(ap[wlen_(wid)]);
4889    __regab_tostr(ts2, ap, bp, wid, BHEX, FALSE);
4890   }
4891  __evtr_resume_msg();
4892  __tr_msg("== processing vpi_put_value %s event in %s value %s\n",
4893   ts3, __msg2_blditree(ts4, __inst_ptr), ts2);
4894 }
4895 
4896 /*
4897  * exec a vpi put value assign to reg - no delay or event processing
4898  */
exec_putv_reg_assign(register struct net_t * np,register word32 * ap,register word32 * bp,register int32 ndx)4899 static void exec_putv_reg_assign(register struct net_t *np, register word32 *ap,
4900  register word32 *bp, register int32 ndx)
4901 {
4902  int32 arrwid, bi;
4903 
4904  /* case 1: array */
4905  if (np->n_isarr)
4906   {
4907    /* array never forced or assigned */
4908    arrwid = __get_arrwide(np);
4909    if (np->nchg_nd_chgstore)
4910     {
4911      __chg_st_arr_val(np->nva, arrwid, np->nwid, ndx, ap, bp);
4912      if (__lhs_changed) record_sel_nchg_(np, ndx, ndx);
4913     }
4914    else __st_arr_val(np->nva, arrwid, np->nwid, ndx, ap, bp);
4915    return;
4916   }
4917  /* case 2: entire reg */
4918  if (ndx == -1)
4919   {
4920    if (np->nu2.qcval != NULL && reg_fr_inhibit_(np)) return;
4921    if (np->nchg_nd_chgstore) __chg_st_val(np, ap, bp);
4922    else __st_val(np, ap, bp);
4923    return;
4924   }
4925  /* case 3: reg bit select - if active force, no assign */
4926  /* know ndx never -1 here */
4927  bi = (ndx == -1) ? 0 : ndx;
4928  if (!np->frc_assgn_allocated
4929   || !np->nu2.qcval[np->nwid*__inum + bi].qc_active)
4930   {
4931    /* SJM - 07/24/00 - now do not use chg st bit unless needed */
4932    if (np->nchg_nd_chgstore) __chg_st_bit(np, ndx, ap[0], bp[0]);
4933    else __st_bit(np, ndx, ap[0], bp[0]);
4934   }
4935 }
4936 
4937 /*
4938  * exec a vpi tput value soft force procedural style assign to reg
4939  * no delay or event processing (may be called from delay assign ev handler)
4940  */
exec_putv_wire_softforce(register struct net_t * np,register word32 * ap,register word32 * bp,register int32 ndx)4941 static void exec_putv_wire_softforce(register struct net_t *np,
4942  register word32 *ap, register word32 *bp, register int32 ndx)
4943 {
4944  /* case 1: entire wire */
4945  if (ndx == -1)
4946   {
4947    /* this add the changed wire to nchglst if needed */
4948    if (np->nu2.qcval != NULL)
4949     {
4950      /* return F if all of wire forced, nothing to do */
4951      /* if T, this will correct bits in ap and bp so actual assign is right */
4952      if (!__correct_forced_newwireval(np, ap, bp)) return;
4953     }
4954    if (np->nchg_nd_chgstore) __chg_st_val(np, ap, bp);
4955    else __st_val(np, ap, bp);
4956    return;
4957   }
4958  /* case 2: wire bit select */
4959  /* if the 1 bit is forced nothing to do */
4960  /* know ndx never -1 since -1 case handled above */
4961  if (np->frc_assgn_allocated
4962   && np->nu2.qcval[np->nwid*__inum + ndx].qc_active) return;
4963 
4964  /* else simple bit assign */
4965  /* SJM 03/15/01 - change to fields in net record */
4966  if (np->nchg_nd_chgstore) __chg_st_bit(np, ndx, ap[0], bp[0]);
4967  else __st_bit(np, ndx, ap[0], bp[0]);
4968 }
4969 
4970 /*
4971  * process a vpi driver put value assign event
4972  *
4973  * for scheduled (delayed) assigns to drivers of wires (like contas)
4974  *
4975  * know a/b value always 1 bit and type known and called from ev itree loc
4976  * for added entire vectored wire driver each bit still has separate event
4977  */
__process_vpidrv_ev(i_tev_ndx tevpi)4978 extern void __process_vpidrv_ev(i_tev_ndx tevpi)
4979 {
4980  register struct net_t *np;
4981  register struct dltevlst_t *dlp;
4982  register word32 *ap, *bp;
4983  int32 ndx, evi;
4984  struct teputv_t *tepvp;
4985  i_tev_ndx *evtabi;
4986  struct h_t *hp;
4987  struct hrec_t *hrp;
4988 
4989  tepvp = __tevtab[tevpi].tu.teputvp;
4990  __tevtab[tevpi].tu.teputvp = NULL;
4991 
4992  np = tepvp->np;
4993  if (__ev_tracing) emit_vpiputv_evtrmsg(np, tepvp, tepvp->nbi);
4994 
4995  /* if putv scheduled event saved, turn on event happened flag in handle */
4996  /* because since user has handle later incorrect cancel might be tried */
4997  /* also at end of time slot canceled tev will be reused */
4998  if ((hp = tepvp->evnt_hp) != NULL)
4999   {
5000    hrp = hp->hrec;
5001    if (hrp->bith_ndx)
5002     {
5003      /* here hp is master entire vector scheduled object */
5004      evtabi = hrp->hu.hevrec->evndxtab;
5005      evtabi[tepvp->nbi] = -1;
5006     }
5007    else hrp->evnt_done = TRUE;
5008   }
5009  /* do the proc. assign, or driver change and fi>1 eval */
5010  ap = tepvp->putv_wp;
5011  /* for scalar bit is 0 for right index - else the vector's index */
5012  if (np->n_stren) bp = ap; else bp = &(ap[1]);
5013  if (tepvp->nbi == -1)
5014   {
5015    immed_vpi_drv_assign(np, tepvp->di, ap, bp);
5016    ndx = 0;
5017   }
5018  else
5019   {
5020    ndx = tepvp->nbi;
5021    immed_vpibit_drv_assign(np, tepvp->di, ndx, ap, bp);
5022   }
5023 
5024  /* free the the driver putv event auxiliary record */
5025  __my_free((char *) ap, 2*WRDBYTES);
5026  /* excise out first being processed event */
5027  evi = np->nwid*__inum + ndx;
5028  dlp = np->vpi_ndrvs[tepvp->di]->putv_drv_tedlst[evi];
5029  np->vpi_ndrvs[tepvp->di]->putv_drv_tedlst[evi] = dlp->terp;
5030 
5031  /* link on putv event contents record free list */
5032  tepvp->np = (struct net_t *) __teputvfreelst;
5033  __teputvfreelst = tepvp;
5034 
5035  /* also link out dltevlst element - must be on front */
5036  /* DBGMAYBELEAVE */
5037  if (dlp == NULL || tevpi != dlp->tevpi) __vpi_terr(__FILE__, __LINE__);
5038  /* --- */
5039  dlp->telp = NULL;
5040  /* put this telst elemnt on free list */
5041  dlp->terp = __dltevfreelst;
5042  __dltevfreelst = dlp;
5043 }
5044 
5045 /*
5046  * convert a passed delay time to internal ticks
5047  */
__vpitime_to_ticks(word64 * timp,p_vpi_time time_p,struct mod_t * mdp)5048 extern int32 __vpitime_to_ticks(word64 *timp, p_vpi_time time_p,
5049  struct mod_t *mdp)
5050 {
5051  word64 tim;
5052 
5053  if (time_p->type == vpiScaledRealTime)
5054   {
5055    if (!__real_to_v64tim(&tim, time_p->real))
5056     {
5057      __vpi_err(1926, vpiError,
5058       "vpiTimeVal type vpiScaledRealTime too large for 64 bit time - not converted");
5059      *timp = 0ULL;
5060      return(FALSE);
5061     }
5062    if (mdp != NULL && !mdp->mno_unitcnv) cnv_num64to_ticks_(*timp, tim, mdp);
5063    else *timp = tim;
5064   }
5065  else
5066   {
5067    if (time_p->type != vpiSimTime)
5068     {
5069      __vpi_err(2018, vpiWarning,
5070       "vpiTimeVal of type vpiSuppressTime meaningless here - using vpiSimTime");
5071     }
5072    /* sim time is internal ticks (lowest time precision in design) */
5073    /* SJM 02/03/00 since PLI time values int32 not word32 cast make 64 */
5074    /* bits of 1 for -1 not word32 32 bits value as needed */
5075    *timp = ((word64) ((word32) (time_p->low)))
5076      | (((word64) ((word32) time_p->high)) << 32);
5077   }
5078  return(TRUE);
5079 }
5080 
5081 /*
5082  * PUTV DELAY SCHEDULING ROUTINES
5083  */
5084 
5085 /*
5086  * implement delayed assign (usually scheduled) of value_p value to reg var
5087  * or bit select of reg var or soft force of wire or wire bit
5088  *
5089  * inertial replaces pending sched ev with later and removes earlier
5090  * but documentation says something else
5091  *
5092  * only for delays - * must run in itree loc. of handle
5093  *
5094  * SJM 07/25/00 - this routine used also for soft force to nets and net bits
5095  *                exactly same algorithm
5096  *
5097  * no driving values stored for registers or nets
5098  * LOOKATME - does this work with strengths - think so
5099  */
setschd_var_fromvaluep(p_vpi_value value_p,struct net_t * np,int32 ndx,word64 ticksdel,byte dtyp,int32 ret_event)5100 static struct h_t *setschd_var_fromvaluep(p_vpi_value value_p,
5101  struct net_t *np, int32 ndx, word64 ticksdel, byte dtyp, int32 ret_event)
5102 {
5103  register struct dltevlst_t *dlp, *dlp2, *ins_after_dlp;
5104  int32 wlen, ewid;
5105  i_tev_ndx tevpi;
5106  word64 schtim;
5107  struct xstk_t *xsp;
5108  struct teputv_t *tepvp;
5109  struct h_t *hp;
5110 
5111  if (ndx == -1) ewid = np->nwid; else ewid = 1;
5112  /* this can be strength if soft force to wire */
5113  if ((xsp = push_vpi_valuep(value_p, ewid, np->ntyp, np->n_stren)) == NULL)
5114   return(NULL);
5115 
5116  /* allocate per inst but not per bit pending event list if needed */
5117  /* SJM 07/24/00 - net putv tedlst also used for soft force of wires */
5118  if (np->regwir_putv_tedlst == NULL) bld_regwir_putvrec(np);
5119 
5120  schtim = __simtime + ticksdel;
5121  if (__ev_tracing)
5122   {
5123    char s1[RECLEN];
5124 
5125    dlp = np->regwir_putv_tedlst[__inum];
5126    if (np->ntyp >= NONWIRE_ST) strcpy(s1, "reg");
5127    else strcpy(s1, "wire soft force");
5128    emit_vpiputv_schd_trmsg(np, xsp, dlp, &schtim, dtyp, "reg");
5129   }
5130 
5131  ins_after_dlp = NULL;
5132  /* eliminate new and/or cancel any olds */
5133  if ((dlp = np->regwir_putv_tedlst[__inum]) != NULL)
5134   {
5135    /* case 1: inertial - remove all but one latest - return if no effect */
5136    /* inertial follows Verilog normal convention - keep only latest */
5137    /* and eliminate any earlier */
5138    if (dtyp == vpiInertialDelay)
5139     {
5140      /* start by removing all of list but last (if needed) - know >= 2 */
5141      if (dlp->terp != NULL)
5142       {
5143        dlp2 = __spliceout_last(dlp);
5144        cancel_vpievents_toend(np, dlp, ewid);
5145        dlp = dlp2;
5146        np->regwir_putv_tedlst[__inum] = dlp;
5147        dlp->telp = NULL;
5148       }
5149      /* by here list has exactly one element (last) */
5150      /* if new one earlier - do not schedule, same time, use new */
5151      if (__tevtab[dlp->tevpi].etime > schtim) { __pop_xstk(); return(NULL); }
5152 
5153      /* know new event time is later - cancel all of one element list */
5154      cancel_vpievents_toend(np, dlp, ewid);
5155      np->regwir_putv_tedlst[__inum] = NULL;
5156      ins_after_dlp = NULL;
5157      goto bld_tev;
5158     }
5159    /* case 2: modified transport - remove all delays >= than new */
5160    /* notice if same time delays must leave and insert this after all */
5161    /* currently scheduled for this time */
5162    if (dtyp == vpiTransportDelay)
5163     {
5164      /* SJM 09/05/99 - think elmination when scheduled wrong */
5165      /* nothing to remove, just put on end of active pnd0 queue */
5166      /* SJM - if (schtim == 0ULL) goto bld_tev; WRONG */
5167      /* AIV 03/09/05 - for 0 delay schedule time will not be 0 */
5168      if (ticksdel == 0ULL) goto bld_tev;
5169 
5170      /* know delay list in time order */
5171      /* dlp2 is one before first after (maybe last), nil is before all */
5172      if ((dlp2 = __find_last_bdltevp(dlp, schtim)) == NULL)
5173       {
5174        /* new delay is before all - empty list */
5175        dlp2 = np->regwir_putv_tedlst[__inum];
5176        cancel_vpievents_toend(np, dlp2, ewid);
5177        np->regwir_putv_tedlst[__inum] = NULL;
5178        ins_after_dlp = NULL;
5179        goto bld_tev;
5180       }
5181      /* new delay is after all - nothing to remove */
5182      if (dlp2->terp == NULL) { ins_after_dlp = dlp2; goto bld_tev; }
5183      /* new delay is after some and before some */
5184      ins_after_dlp = dlp2;
5185      if (dlp2->terp != NULL)
5186       { cancel_vpievents_toend(np, dlp2->terp, ewid); dlp2->terp = NULL; }
5187      goto bld_tev;
5188     }
5189    /* DBG remove --- */
5190    if (dtyp != vpiPureTransportDelay) __vpi_terr(__FILE__, __LINE__);
5191    /* --- */
5192    /* pure transport - insert in right place in list */
5193    /* if new delay is before all - insert at front */
5194    if ((dlp2 = __find_last_bdltevp(dlp, schtim)) == NULL)
5195     { ins_after_dlp = NULL; goto bld_tev; }
5196    /* if goes after list, end of list returned else place to ins after */
5197    ins_after_dlp = dlp2;
5198   }
5199 
5200 bld_tev:
5201  /* allocate and schedule event */
5202  alloc_tev_(tevpi, TE_VPIPUTVDEL, __inst_ptr, schtim);
5203  /* need to store scheduled driving value in event because can be many */
5204  if (__teputvfreelst != NULL)
5205   {
5206    tepvp = __teputvfreelst;
5207    __teputvfreelst = (struct teputv_t *) __teputvfreelst->np;
5208   }
5209  else tepvp = (struct teputv_t *) __my_malloc(sizeof(struct teputv_t));
5210  tepvp->nbi = ndx;
5211  tepvp->np = np;
5212  /* assume non handle returning mode */
5213  tepvp->evnt_hp = NULL;
5214  wlen = wlen_(ewid);
5215  tepvp->putv_wp = (word32 *) __my_malloc(2*WRDBYTES*wlen);
5216  memcpy(tepvp->putv_wp, xsp->ap, 2*WRDBYTES*wlen);
5217  __tevtab[tevpi].tu.teputvp = tepvp;
5218  __tevtab[tevpi].vpi_regwir_putv = TRUE;
5219  __pop_xstk();
5220  /* schedule event */
5221  /* case 1: schedule and add to list */
5222  /* SJM 09/05/99 - was only adding to pound 0 at time 0 - WRONG */
5223  if (ticksdel == 0ULL)
5224   {
5225    if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
5226    else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
5227   }
5228  else __insert_event(tevpi);
5229 
5230  /* build the dl tev lst */
5231  if (__dltevfreelst != NULL)
5232   { dlp = __dltevfreelst; __dltevfreelst = __dltevfreelst->terp; }
5233  else dlp = (struct dltevlst_t *) __my_malloc(sizeof(struct dltevlst_t));
5234  dlp->tevpi = tevpi;
5235 
5236  /* insert at front of list */
5237  if (ins_after_dlp == NULL)
5238   {
5239    dlp2 = np->regwir_putv_tedlst[__inum];
5240    dlp->terp = dlp2;
5241    if (dlp2 != NULL) dlp2->telp = dlp;
5242    dlp->telp = NULL;
5243    np->regwir_putv_tedlst[__inum] = dlp;
5244   }
5245  /* insert after */
5246  else
5247   {
5248    dlp->terp = ins_after_dlp->terp;
5249    if (dlp->terp != NULL) dlp->terp->telp = dlp;
5250    ins_after_dlp->terp = dlp;
5251    dlp->telp = ins_after_dlp;
5252   }
5253  if (ret_event)
5254   {
5255    /* need itree loc. so can get right pending event list */
5256    /* notice if bith ndx on handle is ev rec (table of tev's) else just ev */
5257    /* this is 1 bit using tev index not table because bith ndx off */
5258    hp = (struct h_t *) __mk_handle(vpiSchedEvent, (void *) tevpi,
5259     __inst_ptr, NULL);
5260    hp->hrec->evnt_done = FALSE;
5261    __tevtab[tevpi].tu.teputvp->evnt_hp = hp;
5262    return(hp);
5263   }
5264  return(NULL);
5265 }
5266 
5267 /*
5268  * emit a vpi_put_value scheduled assign part
5269  *
5270  * LOOKATME - no tracing currently for immediate assigns
5271  */
emit_vpiputv_schd_trmsg(struct net_t * np,struct xstk_t * xsp,struct dltevlst_t * dlp,word64 * schdtimp,int32 dtyp,char * putvnam)5272 static void emit_vpiputv_schd_trmsg(struct net_t *np, struct xstk_t *xsp,
5273  struct dltevlst_t *dlp, word64 *schdtimp, int32 dtyp, char *putvnam)
5274 {
5275  char ts1[RECLEN], ts2[RECLEN], ts3[RECLEN];
5276 
5277  if (np->n_stren) __st_regab_tostr(ts1, (byte *) xsp->ap, 1);
5278  else __regab_tostr(ts1, xsp->ap, xsp->bp, np->nwid, BHEX, FALSE);
5279 
5280  __evtr_resume_msg();
5281  __tr_msg("== schedule %s vpi_put_value to %s (in %s) value %s for %s:\n",
5282   putvnam, np->nsym->synam, __msg2_blditree(ts2, __inst_ptr), ts1,
5283   __to_timstr(ts3, schdtimp));
5284 
5285  if (dlp != NULL)
5286   {
5287    __tr_msg("   <%s update of scheduled events>\n",
5288     putv_flag_to_str(ts1, dtyp));
5289   }
5290  else __tr_msg("   <no scheduled events>\n");
5291 }
5292 
5293 /*
5294  * for first putv to reg allocate and zero per inst. scheduled list
5295  * must be called from right (on itstk) itree loc.
5296  */
bld_regwir_putvrec(struct net_t * np)5297 static void bld_regwir_putvrec(struct net_t *np)
5298 {
5299  int32 nbytes;
5300 
5301  nbytes = __inst_mod->flatinum*sizeof(struct dltevlst_t *);
5302  np->regwir_putv_tedlst = (struct dltevlst_t **) __my_malloc(nbytes);
5303  memset(np->regwir_putv_tedlst, 0, nbytes);
5304 }
5305 
5306 /*
5307  * reinitialize putvrec for reg or wire by freeing any pending events
5308  *
5309  * called when resetting from prep code
5310  * only called if putvrec non nil
5311  *
5312  * SJM 07/25/00 - also putv recs for soft force of regs and wires
5313  */
__reinit_regwir_putvrec(struct net_t * np,int32 insts)5314 extern void __reinit_regwir_putvrec(struct net_t *np, int32 insts)
5315 {
5316  register int32 ii;
5317  register struct dltevlst_t *dlp, *dlp2, *last_dlp;
5318 
5319  for (ii = 0; ii < insts; ii++)
5320   {
5321    /* notice events will be in event queue and already freed */
5322    if ((dlp = np->regwir_putv_tedlst[ii]) == NULL) continue;
5323    last_dlp = NULL;
5324    for (dlp2 = dlp; dlp2 != NULL; dlp2 = dlp2->terp) last_dlp = dlp2;
5325    last_dlp->terp = __dltevfreelst;
5326    __dltevfreelst = dlp;
5327   }
5328 }
5329 
5330 /*
5331  * for vpi delayed putv cancel all events starting at passed to end
5332  *
5333  * for change to inertial - free all but last and return last (latest)
5334  * this list for the one given parameter must be ordered by time
5335  * caller must set previous next field to nil or nil out list
5336  * differs from tf_ dputp only in removing either entire wire or bit
5337  */
cancel_vpievents_toend(struct net_t * np,struct dltevlst_t * frdlp,int32 ewid)5338 static void cancel_vpievents_toend(struct net_t *np, struct dltevlst_t *frdlp,
5339  int32 ewid)
5340 {
5341  register struct dltevlst_t *dlp, *last_dlp;
5342  register i_tev_ndx tevpi;
5343  struct teputv_t *tepvp;
5344  struct h_t *hp;
5345  struct hrec_t *hrp;
5346 
5347  for (last_dlp = NULL, dlp = frdlp; dlp != NULL; dlp = dlp->terp)
5348   {
5349    tevpi = dlp->tevpi;
5350    /* need to leave event, gets processed as cancelled and freed en masse */
5351    __tevtab[tevpi].te_cancel = TRUE;
5352    tepvp = __tevtab[tevpi].tu.teputvp;
5353    /* tricky part for tab form vector driver must fix table ptr */
5354    if ((hp = tepvp->evnt_hp) != NULL)
5355     {
5356      hrp = hp->hrec;
5357      if (hrp->bith_ndx)
5358       {
5359        i_tev_ndx *evtabi;
5360 
5361        /* DBG remove --- */
5362        if (np->nwid < 2) __vpi_terr(__FILE__, __LINE__);
5363        if (hrp->htyp != vpiSchedEvent) __vpi_terr(__FILE__, __LINE__);
5364        /* --- */
5365        /* only mark event done for non vectored entire wire schd. */
5366        evtabi = hrp->hu.hevrec->evndxtab;
5367        evtabi[tepvp->nbi] = -1;
5368        /* LOOKATME - could check entire table and mark event done here */
5369       }
5370      else hrp->evnt_done = TRUE;
5371     }
5372 
5373    /* free the value since te cancel implies guts never freed */
5374    __my_free((char *) tepvp->putv_wp, 2*wlen_(ewid)*WRDBYTES);
5375 
5376    /* free tevputv by linking on free list */
5377    tepvp->np = (struct net_t *) __teputvfreelst;
5378    __teputvfreelst = tepvp;
5379    last_dlp = dlp;
5380   }
5381  /* finally link all of dltevlst onto free list */
5382  /* SJM 08/02/01 - add if to keep lint happy */
5383  if (last_dlp != NULL) last_dlp->terp = __dltevfreelst;
5384  __dltevfreelst = frdlp;
5385 }
5386 
5387 /*
5388  * delayed schedule of wire driver either scalar, bit, or entire vector
5389  *
5390  * returns schedule event handle if ret event T else nil
5391  * handle type either vpi net or net bit driver
5392  */
setschd_drvr_fromvaluep(p_vpi_value value_p,struct h_t * hp,word64 ticksdel,byte dtyp,int32 ret_event)5393 static struct h_t *setschd_drvr_fromvaluep(p_vpi_value value_p,
5394  struct h_t *hp, word64 ticksdel, byte dtyp, int32 ret_event)
5395 {
5396  register int32 bi;
5397  register struct net_t *np;
5398  int32 some_sched;
5399  i_tev_ndx tevpi, *evtabi;
5400  struct h_t *hp2;
5401  struct net_pin_t *npp;
5402  struct xstk_t *xsp, *xsp2;
5403  struct schdev_t *schd_ev;
5404 
5405  npp = hp->hrec->hu.hnpp;
5406  np = npp->elnpp.enp;
5407  /* case 1: net bit */
5408  if (hp->hrec->htyp == vpiNetBitDriver)
5409   {
5410    if ((xsp = push_vpi_valuep(value_p, 1, np->ntyp, np->n_stren)) == NULL)
5411     return(NULL);
5412    /* DBG remove --- */
5413    if (!np->n_isavec) __vpi_terr(__FILE__, __LINE__);
5414    /* --- */
5415    tevpi = setschd_1bit_drvr(npp, npp->npaux->nbi1, xsp, ticksdel, dtyp);
5416 
5417    if (ret_event && tevpi != -1)
5418     {
5419      /* need itree loc. so can get right pending event list */
5420      /* notice if bith ndx on handle is ev rec (table of tev's) else just ev */
5421      hp2 = (struct h_t *) __mk_handle(vpiSchedBitEvent, (void *) tevpi,
5422       __inst_ptr, NULL);
5423      hp2->hrec->evnt_done = FALSE;
5424      __tevtab[tevpi].tu.teputvp->evnt_hp = hp2;
5425     }
5426    else hp2 = NULL;
5427    __pop_xstk();
5428    return(hp2);
5429   }
5430  /* case 2: entire net */
5431  /* case 2a: scalar net */
5432  if (!np->n_isavec)
5433   {
5434    if ((xsp = push_vpi_valuep(value_p, 1, np->ntyp, np->n_stren)) == NULL)
5435     return(NULL);
5436    tevpi = setschd_1bit_drvr(npp, 0, xsp, ticksdel, dtyp);
5437 
5438    if (ret_event && tevpi != -1)
5439     {
5440      /* need itree loc. so can get right pending event list */
5441      hp2 = (struct h_t *) __mk_handle(vpiSchedEvent, (void *) tevpi,
5442       __inst_ptr, NULL);
5443      hp2->hrec->evnt_done = FALSE;
5444      /* bith ndx not set indicates not ev tab table */
5445      __tevtab[tevpi].tu.teputvp->evnt_hp = hp2;
5446     }
5447    else hp2 = NULL;
5448    __pop_xstk();
5449    return(hp2);
5450   }
5451 
5452  /* case 2b: vector net */
5453  if ((xsp = push_vpi_valuep(value_p, np->nwid, np->ntyp, np->n_stren))
5454   == NULL) return(NULL);
5455 
5456  evtabi = (i_tev_ndx *) __my_malloc(np->nwid*sizeof(i_tev_ndx));
5457  /* ?? LOOKATME - this was low to high */
5458  for (bi = np->nwid - 1; bi >= 0; bi--) evtabi[bi] = -1;
5459  some_sched = FALSE;
5460  /* for strength vectors just assign to low bit - also warning */
5461  if (np->n_stren)
5462   {
5463    /* BEWARE big endian problem, works providing always pass and cast ptrs */
5464    /* i.e. can not pass word32 here on suns will get high not low */
5465    tevpi = setschd_1bit_drvr(npp, 0, xsp, ticksdel, dtyp);
5466    if (tevpi != -1) some_sched = TRUE;
5467    evtabi[0] = tevpi;
5468   }
5469  else
5470   {
5471    push_xstk_(xsp2, 1);
5472    /* ?? LOOKATME - this was low to high */
5473    for (some_sched = FALSE, bi = np->nwid - 1; bi >= 0; bi--)
5474     {
5475      /* this works because if net stren value will be always also be stren */
5476      /* conversion made in push vpi value if needed */
5477      /* also know all bits but low are 0 */
5478      xsp2->ap[0] = rhsbsel_(xsp->ap, bi);
5479      xsp2->bp[0] = rhsbsel_(xsp->bp, bi);
5480 
5481      /* may return -1 if no event scheduled */
5482      /* can pass address of stacked words since never strengths */
5483      tevpi = setschd_1bit_drvr(npp, bi, xsp2, ticksdel, dtyp);
5484      if (tevpi != -1) some_sched = TRUE;
5485      evtabi[bi] = tevpi;
5486     }
5487    __pop_xstk();
5488   }
5489  __pop_xstk();
5490  if (ret_event && some_sched)
5491   {
5492    /* need itree loc. so can get right pending event list */
5493    /* notice if bith ndx on handle is ev rec (table of tev's) else just ev */
5494    schd_ev = (struct schdev_t *) __my_malloc(sizeof(struct schdev_t));
5495    schd_ev->evnp = np;
5496    schd_ev->evndxtab = evtabi;
5497 
5498    hp2 = (struct h_t *) __mk_handle(vpiSchedEvent, (void *) schd_ev,
5499     __inst_ptr, NULL);
5500    hp2->hrec->evnt_done = FALSE;
5501    /* BEWARE - using 2 different form for vpiSched.. object this field */
5502    /* is used as special case (need evndxtab case) */
5503    hp2->hrec->bith_ndx = TRUE;
5504    for (bi = np->nwid - 1; bi >= 0; bi--)
5505     {
5506      tevpi = evtabi[bi];
5507      /* SJM 04/20/00 - possible for only some to have events */
5508      if (tevpi != -1) __tevtab[tevpi].tu.teputvp->evnt_hp = hp2;
5509     }
5510   }
5511  else
5512   {
5513    __my_free((char *) evtabi, np->nwid*sizeof(i_tev_ndx));
5514    hp2 = NULL;
5515   }
5516  return(hp2);
5517 }
5518 
5519 /*
5520  * implement assign (scheduled) of 1 bit on xstk to 1 wire driver bit
5521  * delayed assign to driver for either driver bit or 1 bit of scalar
5522  *
5523  * always returned scheduled event on sucess (caller creates handle if needed)
5524  * if no event scheduled returns nil (possible inertial not schedule)
5525  *
5526  * inertial replaces pending sched ev with later and removes earlier
5527  * but documentation says something else
5528  *
5529  * only for delays - no delay handled as special case above here
5530  * must run in itree loc. of handle
5531  */
setschd_1bit_drvr(struct net_pin_t * npp,int32 bi,struct xstk_t * xsp,word64 ticksdel,byte dtyp)5532 static i_tev_ndx setschd_1bit_drvr(struct net_pin_t *npp, int32 bi,
5533  struct xstk_t *xsp, word64 ticksdel, byte dtyp)
5534 {
5535  register struct dltevlst_t *dlp, *dlp2, *ins_after_dlp;
5536  int32 evi;
5537  i_tev_ndx tevpi;
5538  word64 schtim;
5539  struct net_t *np;
5540  struct vpi_drv_t *vpidrvp;
5541  struct tev_t *tevp;
5542  struct teputv_t *tepvp;
5543 
5544  np = npp->elnpp.enp;
5545  schtim = __simtime + ticksdel;
5546  ins_after_dlp = NULL;
5547  vpidrvp = np->vpi_ndrvs[npp->obnum];
5548  /* notice bit index 0 for scalar */
5549  /* table of scheduled events is one list for each net bit per inst. */
5550  evi = np->nwid*__inum + bi;
5551 
5552  if (__ev_tracing)
5553   {
5554    char ts1[RECLEN];
5555 
5556    if (np->n_isavec) sprintf(ts1, "bit %d driver", bi);
5557    else strcpy(ts1, "scalar driver");
5558    dlp = vpidrvp->putv_drv_tedlst[evi];
5559    emit_vpiputv_schd_trmsg(np, xsp, dlp, &schtim, (int32) dtyp, ts1);
5560   }
5561 
5562  /* eliminate new and/or cancel any olds */
5563  if ((dlp = vpidrvp->putv_drv_tedlst[evi]) != NULL)
5564   {
5565    /* case 1: inertial - remove all but one latest - return if no effect */
5566    /* inertial follows Verilog normal convention - keep only latest */
5567    /* and eliminate any earlier */
5568    if (dtyp == vpiInertialDelay)
5569     {
5570      /* start by removing all of list but last (if needed) - know >= 2 */
5571      if (dlp->terp != NULL)
5572       {
5573        dlp2 = __spliceout_last(dlp);
5574        cancel_vpievents_toend(np, dlp, 1);
5575        dlp = dlp2;
5576        vpidrvp->putv_drv_tedlst[evi] = dlp;
5577        dlp->telp = NULL;
5578       }
5579      /* by here list has exactly one element (last) */
5580      /* if new one earlier - do not schedule, same time, use new */
5581      tevp = &(__tevtab[dlp->tevpi]);
5582      if (tevp->etime > schtim) return(-1);
5583 
5584      /* know new event time is later - cancel all of one element list */
5585      cancel_vpievents_toend(np, dlp, 1);
5586      vpidrvp->putv_drv_tedlst[evi] = NULL;
5587      ins_after_dlp = NULL;
5588      goto bld_tev;
5589     }
5590    /* case 2: modified transport - remove all delays >= than new */
5591    /* notice if same time delays must leave and insert this after all */
5592    /* currently scheduled for this time */
5593    if (dtyp == vpiTransportDelay)
5594     {
5595      /* SJM 09/05/99 - think elmination when scheduled wrong */
5596      /* nothing to remove, just put on end of active pnd0 queue */
5597      /* SJM - if (schtim == 0ULL) goto bld_tev; WRONG */
5598 
5599      /* know delay list in time order */
5600      /* dlp2 is one before first after (maybe last), nil is before all */
5601      if ((dlp2 = __find_last_bdltevp(dlp, schtim)) == NULL)
5602       {
5603        /* new delay is before all - empty list */
5604        dlp2 = vpidrvp->putv_drv_tedlst[evi];
5605        cancel_vpievents_toend(np, dlp2, 1);
5606        vpidrvp->putv_drv_tedlst[evi] = NULL;
5607        ins_after_dlp = NULL;
5608        goto bld_tev;
5609       }
5610      /* new delay is after all - nothing to remove */
5611      if (dlp2->terp == NULL) { ins_after_dlp = dlp2; goto bld_tev; }
5612      /* new delay is after some and before some */
5613      ins_after_dlp = dlp2;
5614      if (dlp2->terp != NULL)
5615       { cancel_vpievents_toend(np, dlp2->terp, 1); dlp2->terp = NULL; }
5616      goto bld_tev;
5617     }
5618    /* DBG remove --- */
5619    if (dtyp != vpiPureTransportDelay) __vpi_terr(__FILE__, __LINE__);
5620    /* --- */
5621    /* pure transport - insert in right place in list */
5622    /* if new delay is before all - insert at front */
5623    if ((dlp2 = __find_last_bdltevp(dlp, schtim)) == NULL)
5624     { ins_after_dlp = NULL; goto bld_tev; }
5625    /* if goes after list, end of list returned else place to ins after */
5626    ins_after_dlp = dlp2;
5627   }
5628 
5629 bld_tev:
5630  /* allocate and schedule event */
5631  alloc_tev_(tevpi, TE_VPIDRVDEL, __inst_ptr, schtim);
5632  /* need to store scheduled driving value in event because can be many */
5633  if (__teputvfreelst != NULL)
5634   {
5635    tepvp = __teputvfreelst;
5636    __teputvfreelst = (struct teputv_t *) __teputvfreelst->np;
5637   }
5638  else tepvp = (struct teputv_t *) __my_malloc(sizeof(struct teputv_t));
5639  /* this will be -1 for scalar else bit index */
5640  tepvp->nbi = (!np->n_isavec) ? -1 : bi;
5641  tepvp->np = np;
5642  /* index from all vpi_ added drivers of the one being driven */
5643  tepvp->di = npp->obnum;
5644  /* assume non handle returning mode */
5645  tepvp->evnt_hp = NULL;
5646  /* drivers always 1 bit - i.e. for vector will only set low bit */
5647  /* always allocate 8 byte unpacked */
5648  tepvp->putv_wp = (word32 *) __my_malloc(2*WRDBYTES);
5649  if (np->n_stren)
5650   {
5651   /* copy the 1 low bit */
5652    memcpy(tepvp->putv_wp, xsp->ap, 1);
5653   }
5654  else
5655   {
5656    /* this is 1 bit but still need the 8 byte unpacked */
5657    /* need to access just the low bit */
5658    tepvp->putv_wp[0] = (xsp->ap[0] & 1L);
5659    tepvp->putv_wp[1] = (xsp->bp[0] & 1L);
5660   }
5661  __tevtab[tevpi].tu.teputvp = tepvp;
5662  /* schedule event */
5663  /* case 1: schedule and add to list */
5664  /* SJM 09/05/99 - was only adding to pound 0 at time 0 - WRONG */
5665  if (ticksdel == 0ULL)
5666   {
5667    if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
5668    else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
5669   }
5670  else __insert_event(tevpi);
5671 
5672  /* build the dl tev lst */
5673  if (__dltevfreelst != NULL)
5674   { dlp = __dltevfreelst; __dltevfreelst = __dltevfreelst->terp; }
5675  else dlp = (struct dltevlst_t *) __my_malloc(sizeof(struct dltevlst_t));
5676  dlp->tevpi = tevpi;
5677 
5678  /* insert at front of list */
5679  if (ins_after_dlp == NULL)
5680   {
5681    dlp2 = vpidrvp->putv_drv_tedlst[evi];
5682    dlp->terp = dlp2;
5683    if (dlp2 != NULL) dlp2->telp = dlp;
5684    dlp->telp = NULL;
5685    vpidrvp->putv_drv_tedlst[evi] = dlp;
5686   }
5687  /* insert after */
5688  else
5689   {
5690    dlp->terp = ins_after_dlp->terp;
5691    if (dlp->terp != NULL) dlp->terp->telp = dlp;
5692    ins_after_dlp->terp = dlp;
5693    dlp->telp = ins_after_dlp;
5694   }
5695  return(tevpi);
5696 }
5697 
5698 /*
5699  * TIME PROCESSING ROUTINES
5700  */
5701 
5702 /*
5703  * get current time
5704  */
vpi_get_time(vpiHandle object,p_vpi_time time_p)5705 extern void vpi_get_time(vpiHandle object, p_vpi_time time_p)
5706 {
5707  struct h_t *hp;
5708  struct mod_t *mdp;
5709 
5710  if (__run_state != SS_SIM) { __sim_notbegun_err("vpi_get_time"); return; }
5711  hp = (struct h_t *) object;
5712  if (hp != NULL) if (!__validate_handle("vpi_get_time", hp)) return;
5713  if (!__validate_time_type("vpi_get_time", time_p->type)) return;
5714 
5715  if (hp != NULL) mdp = hp->hin_itp->itip->imsym->el.emdp; else mdp = NULL;
5716  __set_vpi_time(time_p, &__simtime, time_p->type, mdp);
5717 }
5718 
5719 /*
5720  * VPI I/O ROUTINES
5721  */
5722 
5723 /*
5724  * open an mcd channel
5725  *
5726  * SJM 09/22/03 - LRM does not allow open file descriptor except in HDL
5727  * but can open mcd channel - if fd opened in HDL, PLI routines can use
5728  */
vpi_mcd_open(PLI_BYTE8 * filename)5729 extern PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filename)
5730 {
5731  char *chp;
5732 
5733  chp = __pv_stralloc(filename);
5734  return(__mc1_fopen(chp, strlen(chp), TRUE));
5735 }
5736 
5737 /*
5738  * close an mcd channel
5739  */
vpi_mcd_close(PLI_UINT32 mcd)5740 extern PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd)
5741 {
5742  if ((mcd & FIO_MSB) != 0)
5743   {
5744    return(__fd_do_fclose(mcd & ~FIO_FD));
5745   }
5746  return(__close_mcd(mcd, TRUE));
5747 }
5748 
5749 /*
5750  * get the name of a channel descriptor (use first if more on)
5751  */
vpi_mcd_name(PLI_UINT32 mcd)5752 extern PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd)
5753 {
5754  register int32 i;
5755  int32 fd;
5756 
5757  if ((mcd & FIO_MSB) != 0)
5758   {
5759    fd = mcd & ~(FIO_FD);
5760    /* AIV 06/27/05 - fd cannot be greater than max file size */
5761    if (fd >= MY_FOPEN_MAX || __fio_fdtab[fd] == NULL) return(NULL);
5762    else return(__fio_fdtab[fd]->fd_name);
5763   }
5764  for (i = 2; i < 31; i++)
5765   {
5766    if (((mcd >> i) & 1L) == 0L) continue;
5767    if (__mulchan_tab[i].mc_s == NULL)
5768     {
5769      __vpi_err(1894, vpiError,
5770       "vpi_mcd_name bit %d on for channel that is unused", i + 1);
5771      return(NULL);
5772     }
5773    return(__mulchan_tab[i].mc_fnam);
5774   }
5775  __vpi_err(1898, vpiError,
5776   "vpi_mcd_name passed empty (0) multi-channel descriptor");
5777  return(NULL);
5778 }
5779 
5780 /*
5781  * printf to multi-channel descriptor - modern VPI form
5782  *
5783  * notice here mcd is word32 in in tf_ routines it is int32 by standard
5784  * but functions almost same - returns value for last if many
5785  */
5786 /*VARARGS*/
vpi_mcd_printf(PLI_UINT32 mcd,PLI_BYTE8 * format,...)5787 extern PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *format, ...)
5788 {
5789  va_list va, va2;
5790  register int32 i;
5791  int32 fd;
5792  PLI_INT32 numch_prtfed = 0;
5793 
5794  if ((mcd & FIO_MSB) != 0)
5795   {
5796    fd = mcd & ~(FIO_FD);
5797    va_start(va, format);
5798    /* AIV 06/27/05 - fd cannot be greater than max file size */
5799    if (fd >= MY_FOPEN_MAX || __fio_fdtab[fd] == NULL)
5800     {
5801      numch_prtfed = -1;
5802     }
5803    else
5804     {
5805      numch_prtfed = vfprintf(__fio_fdtab[fd]->fd_s, format, va);
5806     }
5807    va_end(va);
5808    return(numch_prtfed);
5809   }
5810 
5811  /* SJM 03/26/00 - mcd 1 (bit 0) know both stdout and std log if open */
5812  /* may be other mcd bits on (files open) too */
5813  if ((mcd & 1) != 0)
5814   {
5815    va_start(va, format);
5816    va_start(va2, format);
5817    numch_prtfed = vprintf(format, va);
5818    if (__log_s != NULL) vfprintf(__log_s, format, va2);
5819    va_end(va);
5820    va_end(va2);
5821   }
5822 
5823  /* mcd's may require writing to lots of files */
5824  for (i = 1; i < 31; i++)
5825   {
5826    if (((mcd >> i) & 1L) != 0L)
5827     {
5828      if (__mulchan_tab[i].mc_s == NULL)
5829       {
5830        __vpi_err(2010, vpiWarning,
5831         "vpi_mcd_printf: multi-channel descriptor bit %d on, but file not open",
5832         i + 1);
5833        numch_prtfed = -1;
5834       }
5835      /* using last since will always be same */
5836      else
5837       {
5838        /* SJM 10/13/99 - ansii std says varargs not usable after vfprintf */
5839        va_start(va, format);
5840        numch_prtfed = vfprintf(__mulchan_tab[i].mc_s, format, va);
5841        va_end(va);
5842       }
5843     }
5844   }
5845  if (((mcd >> 31) & 1) != 0)
5846   {
5847    __vpi_err(2020, vpiWarning,
5848     "vpi_mcd_printf: multi-channel descriptor bit 31 on but file not open - unusable because reserved for new Verilog 2000 file I/O");
5849   }
5850  return(numch_prtfed);
5851 }
5852 
5853 /*
5854  * formatted print to both standard output and log file (if open)
5855  *
5856  * modern but almost same as io (tf_) form - code no larger to just duplicated
5857  * because of var args, return number of printed chars following ansi
5858  */
5859 /*VARARGS*/
vpi_printf(PLI_BYTE8 * format,...)5860 extern PLI_INT32 vpi_printf(PLI_BYTE8 *format, ...)
5861 {
5862  va_list va, va2;
5863  PLI_INT32 num_prtfed = 0;
5864 
5865  va_start(va, format);
5866  va_start(va2, format);
5867  num_prtfed = vprintf(format, va);
5868  if (__log_s != NULL) vfprintf(__log_s, format, va2);
5869  va_end(va);
5870  va_end(va2);
5871  return(num_prtfed);
5872 }
5873 
5874 /*
5875  * var args vpi_ printf routine
5876  *
5877  * this is vpi printf variant (goes to stdio and log file) where user
5878  * has called va_start(ap) before and must call va_end(ap) after
5879  *
5880  * this must format to string so use giant (16k for now) buffer because
5881  * can't effect varargs since caller started
5882  */
vpi_vprintf(char * format,va_list ap)5883 extern int32 vpi_vprintf(char *format, va_list ap)
5884 {
5885  int32 num_prtfed;
5886  char buf[RDBUFSIZ];
5887 
5888  num_prtfed = vsnprintf(buf, RDBUFSIZ, format, ap);
5889 
5890  fputs(buf, stdout);
5891  if (__log_s != NULL) fputs(buf, __log_s);
5892  return(num_prtfed);
5893 }
5894 
5895 /*
5896  * var args vpi_ mcd_printf routine (can handle either file desc or mcd)
5897  *
5898  * this is vpi printf variant (goes to stdio and log file) where user
5899  * has called va_start(ap) before and must call va_end(ap) after
5900  *
5901  * must print to string buffer since do not have
5902  */
vpi_mcd_vprintf(PLI_UINT32 mcd,PLI_BYTE8 * format,va_list ap)5903 extern PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format,
5904  va_list ap)
5905 {
5906  char buf[RDBUFSIZ];
5907  register int32 i;
5908  int32 fd;
5909  PLI_INT32 numch_prtfed = 0;
5910 
5911  if ((mcd & FIO_MSB) != 0)
5912   {
5913    fd = mcd & ~(FIO_FD);
5914    /* AIV 06/27/05 - fd cannot be greater than max file size */
5915    if (fd >= MY_FOPEN_MAX || __fio_fdtab[fd] == NULL)
5916     {
5917      numch_prtfed = -1;
5918     }
5919    else
5920     {
5921      numch_prtfed = vfprintf(__fio_fdtab[fd]->fd_s, format, ap);
5922     }
5923    return(numch_prtfed);
5924   }
5925 
5926  /* assume at least one mcd or fd open */
5927  numch_prtfed = vsnprintf(buf, RDBUFSIZ, format, ap);
5928 
5929  /* SJM 03/26/00 - mcd 1 (bit 0) know both stdout and std log if open */
5930  /* may be other mcd bits on (files open) too */
5931  if ((mcd & 1) != 0)
5932   {
5933    fputs(buf, stdout);
5934    if (__log_s != NULL) fputs(buf, __log_s);
5935   }
5936 
5937  /* mcd's may require writing to lots of files */
5938  for (i = 1; i < 31; i++)
5939   {
5940    if (((mcd >> i) & 1L) != 0L)
5941     {
5942      if (__mulchan_tab[i].mc_s == NULL)
5943       {
5944        __vpi_err(1896, vpiError,
5945         "vpi_mcd_printf: multi-channel descriptor bit %d on, but file not open",
5946         i + 1);
5947        numch_prtfed = -1;
5948       }
5949      /* using last since will always be same */
5950      else fputs(buf, __mulchan_tab[i].mc_s);
5951     }
5952   }
5953  if (((mcd >> 31) & 1) != 0)
5954   {
5955    __vpi_err(1896, vpiError,
5956     "vpi_mcd_vprintf: multi-channel descriptor bit 31 on but file not open - unusable because reserved for new Verilog 2000 file I/O");
5957   }
5958  return(numch_prtfed);
5959 }
5960 
5961 /*
5962  * flush std out and log file
5963  *
5964  * WRITEME
5965  */
vpi_flush(void)5966 extern PLI_INT32 vpi_flush(void)
5967 {
5968  fflush(stdout);
5969  if (__log_s != NULL) fflush(__log_s);
5970  return(0);
5971 }
5972 
vpi_mcd_flush(PLI_UINT32 mcd)5973 extern PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd)
5974 {
5975  register int32 i;
5976  int32 fd;
5977 
5978  if ((mcd & FIO_MSB) != 0)
5979   {
5980    fd = mcd & ~(FIO_FD);
5981    /* know fd in range but if not open error */
5982    /* AIV 06/27/05 - fd cannot be greater than max file size */
5983    if (fd >= MY_FOPEN_MAX || __fio_fdtab[fd] == NULL)
5984     {
5985      __vpi_err(1896, vpiError,
5986       "vpi_mcd_vprintf: new 2001 style file descriptor %d - file not open",
5987       fd);
5988      return(1);
5989     }
5990 
5991    fflush(__fio_fdtab[fd]->fd_s);
5992    return(0);
5993   }
5994 
5995  /* SJM 09/09/03 - bit 31 now not used for mcds */
5996  for (i = 1; i < 30; i++)
5997   {
5998    if (((mcd >> i) & 1L) != 0L)
5999     {
6000      if (__mulchan_tab[i].mc_s == NULL)
6001       {
6002        __vpi_err(2010, vpiWarning,
6003         "multi-channel descriptor bit %d on, but file not open", i);
6004       }
6005      else fflush(__mulchan_tab[i].mc_s);
6006     }
6007   }
6008  return(0);
6009 }
6010 
6011 /*
6012  * NEW 2001 ROUTINES TO GET AND PUT DATA
6013  */
6014 
6015 /*
6016  * get and put data for $save/$restart
6017  *
6018  * get/put user data for XL/NC save/restart but not supported since using
6019  * OS process image save mechanism much better and no need to explicitly
6020  * save anything
6021  */
vpi_get_data(PLI_INT32 id,PLI_BYTE8 * dataLoc,PLI_INT32 numOfBytes)6022 extern PLI_INT32 vpi_get_data(PLI_INT32 id, PLI_BYTE8 *dataLoc,
6023  PLI_INT32 numOfBytes)
6024 {
6025  __vpi_err(1801, vpiError,
6026   "new P1364 2001 vpi_get_data routine unsupported because $save/$restart not implemented - use OS save/restart");
6027  return(0);
6028 }
6029 
vpi_put_data(PLI_INT32 id,PLI_BYTE8 * dataLoc,PLI_INT32 numOfBytes)6030 extern PLI_INT32 vpi_put_data(PLI_INT32 id, PLI_BYTE8 *dataLoc,
6031  PLI_INT32 numOfBytes)
6032 {
6033  __vpi_err(1801, vpiError,
6034   "new P1364 2001 vpi_put_data routine unsupported because $save/$restart not implemented - use OS save/restart");
6035  return(0);
6036 }
6037 
6038 /*
6039  * get/put data associated with most recent user sys task or function call
6040  *
6041  * SJM 04/15/04 - add vpi save/get user data routines since PLI 1.0 deprecated
6042  */
vpi_get_userdata(vpiHandle obj)6043 extern void *vpi_get_userdata(vpiHandle obj)
6044 {
6045  register struct h_t *hp;
6046  register struct hrec_t *hrp;
6047  struct tskcall_t *tkcp;
6048 
6049  /* notice can't get or put user data in compile tf cb - need elab. n.l. */
6050  if (__run_state != SS_RESET && __run_state != SS_SIM)
6051   {
6052    __sim_notbegun_err("vpi_get_userdata");
6053    return(NULL);
6054   }
6055 
6056  hp = (struct h_t *) obj;
6057  hrp = hp->hrec;
6058  if (hrp->htyp == vpiSysFuncCall)
6059   {
6060    return(hrp->hu.hxp->lu.x->szu.vpi_sysf_datap);
6061   }
6062  else if (hrp->htyp == vpiSysTaskCall)
6063   {
6064    tkcp = &(hrp->hu.hstp->st.stkc);
6065    return(tkcp->tkcaux.vpi_syst_datap);
6066   }
6067  __vpi_err(1839, vpiError,
6068   "vpi_get_userdata argument %s illegal - must be vpiSysFuncCall or vpiSysTaskCall",
6069   __to_vpionam(__wrks1, hrp->htyp));
6070  return(NULL);
6071 }
6072 
vpi_put_userdata(vpiHandle obj,void * userdata)6073 extern PLI_INT32 vpi_put_userdata (vpiHandle obj, void *userdata)
6074 {
6075  register struct h_t *hp;
6076  register struct hrec_t *hrp;
6077  struct tskcall_t *tkcp;
6078 
6079  /* notice can't get or put user data in compile tf cb - need elab. n.l. */
6080  if (__run_state != SS_RESET && __run_state != SS_SIM)
6081   {
6082    __sim_notbegun_err("vpi_put_userdata");
6083    return(0);
6084   }
6085 
6086  hp = (struct h_t *) obj;
6087  hrp = hp->hrec;
6088  if (hrp->htyp == vpiSysFuncCall)
6089   {
6090    hrp->hu.hxp->lu.x->szu.vpi_sysf_datap = userdata;
6091    return(1);
6092   }
6093  else if (hrp->htyp == vpiSysTaskCall)
6094   {
6095    tkcp = &(hrp->hu.hstp->st.stkc);
6096    tkcp->tkcaux.vpi_syst_datap = userdata;
6097    return(1);
6098   }
6099  __vpi_err(1839, vpiError,
6100   "vpi_put_userdata first argument %s illegal - must be vpiSysFuncCall or vpiSysTaskCall",
6101   __to_vpionam(__wrks1, hrp->htyp));
6102  return(0);
6103 }
6104 
6105 /*
6106  * VPI UTLITY ROUTINES
6107  */
6108 
6109 /*
6110  * compare two handle to determine if same object
6111  * (i.e. same object in same itree instance)
6112  * maybe better way than to compare all fields except links for freeing
6113  */
vpi_compare_objects(vpiHandle object1,vpiHandle object2)6114 extern PLI_INT32 vpi_compare_objects(vpiHandle object1, vpiHandle object2)
6115 {
6116  register struct h_t *hp1, *hp2;
6117  register struct hrec_t *hrp1, *hrp2;
6118  int32 biti;
6119 
6120  hp1 = (struct h_t *) object1;
6121  if (!__validate_handle("vpi_compare_objects (first)", hp1)) return(0);
6122  hrp1 = hp1->hrec;
6123  hp2 = (struct h_t *) object2;
6124  if (!__validate_handle("vpi_compare_objects (second)", hp2)) return(0);
6125  hrp2 = hp2->hrec;
6126 
6127  /* types of handles must be same in same itre loc or can't compare equal */
6128  if (hrp1->htyp != hrp2->htyp || hrp1->htyp2 != hrp2->htyp2) return(0);
6129  if (hp1->hin_itp != hp2->hin_itp || hrp1->hin_tskp != hrp2->hin_tskp)
6130   return(0);
6131 
6132  /* only tricky part is for bit handles - bith ndx and expr can match */
6133  switch (hrp1->htyp) {
6134   case vpiNetBit: case vpiRegBit: case vpiVarSelect: case vpiMemoryWord:
6135   /* for param array words only bith ndx form */
6136    if (hrp1->bith_ndx && hrp2->bith_ndx)
6137     {
6138      if (hrp1->hu.hanyp != hrp2->hu.hanyp) return(0);
6139      if (hrp1->hi == hrp2->hi) return(1);
6140      return(0);
6141     }
6142    /* if both expressions must be identical */
6143    if (!hrp1->bith_ndx && !hrp2->bith_ndx)
6144     {
6145      if (hrp1->hu.hanyp != hrp2->hu.hanyp) return(0);
6146      if (hrp1->hu.hxp == hrp2->hu.hxp) return(1);
6147      return(0);
6148     }
6149    /* one expr. one not - only match if constant - can not compare hanyp */
6150    if (hrp1->bith_ndx)
6151     {
6152      if (hrp1->hu.hnp != hrp2->hu.hxp->lu.sy->el.enp) return(0L);
6153      /* if non constant mixed form never same */
6154      if (!__expr_is_vpiconst(hrp2->hu.hxp->ru.x)) return(0);
6155      __push_itstk(hp2->hin_itp);
6156      biti = __comp_ndx(hrp2->hu.hxp->lu.sy->el.enp, hrp2->hu.hxp->ru.x);
6157      __pop_itstk();
6158      /* out of range can never match bith ndx form */
6159      if (biti == -1) return(0);
6160      if (hrp1->hi == biti) return(1);
6161      return(0);
6162     }
6163    if (hrp2->bith_ndx)
6164     {
6165      if (hrp2->hu.hnp != hrp1->hu.hxp->lu.sy->el.enp) return(0);
6166      /* if non constant mixed form never same */
6167      if (!__expr_is_vpiconst(hrp1->hu.hxp->ru.x)) return(0);
6168      __push_itstk(hp1->hin_itp);
6169      biti = __comp_ndx(hrp1->hu.hxp->lu.sy->el.enp, hrp1->hu.hxp->ru.x);
6170      __pop_itstk();
6171      if (biti == -1) return(0);
6172      if (hrp1->hi == biti) return(1);
6173      return(0);
6174     }
6175  }
6176  if (hrp1->hu.hanyp != hrp2->hu.hanyp) return(0);
6177  if (hrp1->hi != hrp2->hi) return(0);
6178  return(1);
6179 }
6180 
6181 /*
6182  * check to see if last vpi routine returned an error
6183  *
6184  * always needs to be checked even if routine worked for warnings
6185  * returns T on error
6186  */
vpi_chk_error(p_vpi_error_info error_info_p)6187 extern int32 vpi_chk_error(p_vpi_error_info error_info_p)
6188 {
6189  if (__last_eip == NULL) return(FALSE);
6190  if (error_info_p == NULL) return(TRUE);
6191  *error_info_p = __wrk_einfo;
6192  return(TRUE);
6193 }
6194 
6195 /*
6196  * ROUTINES TO FREE HANDLES
6197  */
6198 
6199 /*
6200  * free a handle and associated storage - return F on no free else T
6201  *
6202  * for iterator frees entire handle table
6203  */
vpi_free_object(vpiHandle object)6204 extern PLI_INT32 vpi_free_object(vpiHandle object)
6205 {
6206  register struct h_t *hp;
6207  register struct hrec_t *hrp;
6208 
6209  hp = (struct h_t *) object;
6210  if (!__validate_handle("vpi_free_object", hp)) return(0);
6211  hrp = hp->hrec;
6212  if (hrp->in_iter)
6213   {
6214    __vpi_err(2019, vpiWarning,
6215     "component of iterator can not be freed - use vpi_copy_object to save if needed");
6216    return(FALSE);
6217   }
6218  if (hrp->htyp == vpiIterator) { __free_iterator(object); return(TRUE); }
6219  if (hrp->htyp == vpiCallback || hrp->htyp == vpiUserSystf)
6220   {
6221    __vpi_err(2020, vpiWarning, "unable to free %s object - can not be freed",
6222     __to_vpionam(__wrks1, hp->hrec->htyp));
6223    return(FALSE);
6224   }
6225  /* for tab form scheduled entire vector must free ev. ptr table */
6226  if (hrp->bith_ndx && hrp->htyp == vpiSchedEvent)
6227   {
6228    struct net_t *np;
6229 
6230    np = hrp->hu.hevrec->evnp;
6231    __my_free((char *) hrp->hu.hevrec->evndxtab, np->nwid*sizeof(i_tev_ndx));
6232    __my_free((char *) hrp->hu.hevrec, sizeof(struct schdev_t));
6233    hrp->hu.hevrec = NULL;
6234   }
6235  /* maybe free expr. */
6236  if (hrp->free_xpr) __free_xtree(hrp->hu.hxp);
6237  /* BEWARE - to free handle can only link on free list since may be in */
6238  /* large iterator table */
6239  __free_hp(hp);
6240  return(TRUE);
6241 }
6242 
6243 /*
6244  * free an iterator contents and handle
6245  *
6246  * only way to free in iterator handle and called automaticaly
6247  * when iterator done or error
6248  * internal routine always called with iterator handle
6249  *
6250  * FIXME - need to change to 8 bytes handle with rest in fixed type memory
6251  *
6252  * transitional algorithm - normally just turn off in_iter so user
6253  * can free later if wanted if auto free option free handles and iter
6254  * array (with real free)
6255  */
__free_iterator(vpiHandle ihref)6256 extern void __free_iterator(vpiHandle ihref)
6257 {
6258  register int32 hi;
6259  register struct h_t *hp, *hp2;
6260  register struct hrec_t *hrp;
6261  struct pviter_t *iterp;
6262 
6263  hp = (struct h_t *) ihref;
6264  hrp = hp->hrec;
6265  /* DBG remove --- */
6266  if (hrp->htyp != vpiIterator) __vpi_terr(__FILE__, __LINE__);
6267  /* --- */
6268  /* mark handles as separately freeable if user wants to later */
6269  iterp = hrp->hu.hiterp;
6270  /* must look for and free any expressions */
6271  for (hi = 0; hi < iterp->numhs; hi++)
6272   {
6273    hp2 = &(iterp->scanhtab[hi]);
6274    /* SJM 10/11/99 - must not free expr. since not freeing handle */
6275    /* *** if (hp2->hrec->free_xpr) __free_xtree(hp2->hrec->hu.hxp); *** */
6276    hp2->hrec->in_iter = FALSE;
6277   }
6278  /* SJM 03/16/00 - never free handles passed to user or does not match XL */
6279 
6280  /* but free the small iterator record - stops further accessing of iter */
6281  /* needed so handle magic number will fail */
6282  __my_free((char *) iterp, sizeof(struct pviter_t));
6283  __free_hp(hp);
6284 }
6285 
6286 /*
6287  * free handle contents hp
6288  *
6289  * caller must have validated hp before calling this routine
6290  * caller must also free hxp if needed
6291  *
6292  * notice this works because if freeing handle from iterator table puts
6293  * all or some on free list for reuse
6294  */
__free_hp(struct h_t * hp)6295 extern void __free_hp(struct h_t *hp)
6296 {
6297  register struct hrec_t *hrp;
6298 
6299  hrp = hp->hrec;
6300  /* zero so magic number test fails and link hrec onto hrec free list */
6301  memset(hrp, 0, sizeof(struct hrec_t));
6302  hrp->hu.hfreenxt = __vpi_hrecfree_hdr;
6303  __vpi_hrecfree_hdr = hrp;
6304 
6305  /* zero and link hrp onto hp free list */
6306  memset(hp, 0, sizeof(struct h_t));
6307  hp->hin_itp = (struct itree_t *) __vpi_hfree_hdr;
6308  __vpi_hfree_hdr = hp;
6309 }
6310 
6311 /*
6312  * copy a handle and associated storage
6313  * can not copy iterator (must recreate)
6314  */
vpi_copy_object(vpiHandle object)6315 extern vpiHandle vpi_copy_object(vpiHandle object)
6316 {
6317  register struct h_t *hp, *hp2;
6318  register struct hrec_t *hrp2;
6319 
6320  /* SJM 08/08/99 - vpi scan may return nil and free so copy of nil is nil */
6321  if (object == NULL) return(NULL);
6322 
6323  hp = (struct h_t *) object;
6324  if (!__validate_handle("vpi_copy_object", hp)) return(0);
6325  if (hp->hrec->htyp == vpiIterator)
6326   {
6327    __vpi_err(1842, vpiError,
6328     "iterator handle can not be copied - call vpi_iterate to create same contents handle");
6329    return(NULL);
6330   }
6331  hp2 = (struct h_t *) __mk_handle(hp->hrec->htyp, (void *) NULL, NULL, NULL);
6332  hp2->hin_itp = hp->hin_itp;
6333  hrp2 = hp2->hrec;
6334  *(hrp2) = *(hp->hrec);
6335  /* if copy from iterator, no longer in iterator */
6336  hrp2->in_iter = FALSE;
6337  if (hrp2->free_xpr)
6338   {
6339    hrp2->hu.hxp = __sim_copy_expr(hp->hrec->hu.hxp);
6340   }
6341  return((vpiHandle) hp2);
6342 }
6343 
6344 /*
6345  * ROUTINES TO IMPLEMENT SIM CONTROL MECHANISM
6346  */
6347 
6348 /*
6349  * send information from user application back to simulator
6350  *
6351  * main use is elminating need for tf_dofinish and tf_dostop but also for
6352  * cver specific extensions
6353  */
6354 /*VARARGS*/
vpi_control(PLI_INT32 operation,...)6355 extern PLI_INT32 vpi_control(PLI_INT32 operation, ...)
6356 {
6357  int32 sav_err_cnt;
6358  va_list va;
6359  PLI_INT32 retv;
6360  int32 diag_level, stop_val, reset_val;
6361  vpiHandle scopobj, cbobj;
6362  char *buf;
6363 
6364  /* assume success */
6365  retv = TRUE;
6366  va_start(va, operation);
6367  switch (operation) {
6368   case vpiStop:
6369    diag_level = va_arg(va, int32);
6370    retv = __do_vpi_stop(diag_level);
6371    break;
6372   case vpiFinish:
6373    diag_level = va_arg(va, int32);
6374    __pli_dofinish(diag_level, "vpi_control");
6375    break;
6376   case vpiReset:
6377    stop_val = va_arg(va, int32);
6378    reset_val = va_arg(va, int32);
6379    diag_level = va_arg(va, int32);
6380    /* this never returns */
6381    __do_vpi_reset(stop_val, reset_val, diag_level);
6382    break;
6383   case vpiSetInteractiveScope:
6384    scopobj = va_arg(va, vpiHandle);
6385    retv = do_vpi_iact_scopchg(scopobj);
6386    break;
6387   case vpiDumpVars:
6388    if (!__can_exec)
6389     {
6390      __vpi_err(1900, vpiError,
6391       "vpi_control vpiDumpVars operation illegal - only callable during simulation");
6392      retv = FALSE;
6393      break;
6394     }
6395    sav_err_cnt = __pv_err_cnt;
6396    __exec_dumpvars(NULL);
6397    if (__pv_err_cnt > sav_err_cnt) retv = FALSE; else retv = TRUE;
6398    break;
6399   case vpiInsertSource:
6400    /* this is only callable from `language when `endlanguage hit */
6401    if (__match_cdir(__langstr, "`endlanguage") == NULL)
6402     {
6403      __vpi_err(1888, vpiError,
6404       "vpi_control vpiInsertSource operation illegal - not called at end of `language section");
6405      retv = FALSE;
6406      break;
6407     }
6408    buf = va_arg(va, char *);
6409    /* since outside any module - this does module source reading */
6410    retv = __exec_rdinserted_src(buf);
6411    break;
6412   case vpiFlushLog:
6413    /* flush internal files */
6414    if (__dv_fd != -1) __my_dv_flush();
6415    if (__log_s != NULL) fflush(__log_s);
6416    if (__tr_s != NULL) fflush(__tr_s);
6417    break;
6418   case vpiDisableCb:
6419    cbobj = va_arg(va, vpiHandle);
6420    retv = do_vpi_cb_onoff(cbobj, FALSE);
6421    break;
6422   case vpiEnableCb:
6423    cbobj = va_arg(va, vpiHandle);
6424    retv = do_vpi_cb_onoff(cbobj, TRUE);
6425    break;
6426   default:
6427    __vpi_err(1888, vpiError,
6428     "vpi_control first operation argument value %d illegal", operation);
6429    retv = FALSE;
6430  }
6431  va_end(va);
6432  return(retv);
6433 }
6434 
6435 /*
6436  * change interactive scope from vpi_ user code
6437  *
6438  * notice need to call call back on scope change although may never
6439  * actually enter interactive code
6440  */
do_vpi_iact_scopchg(vpiHandle newscopobj)6441 static int32 do_vpi_iact_scopchg(vpiHandle newscopobj)
6442 {
6443  register struct h_t *hp;
6444 
6445  hp = (struct h_t *) newscopobj;
6446  if (!__validate_handle("vpi_control vpiSetInteractiveScope operation", hp))
6447   return(FALSE);
6448 
6449  switch (hp->hrec->htyp) {
6450   case vpiModule:
6451    __scope_ptr = hp->hin_itp;
6452    __scope_tskp = NULL;
6453    break;
6454   case vpiTask: case vpiFunction: case vpiNamedBegin: case vpiNamedFork:
6455    __scope_ptr = hp->hin_itp;
6456    __scope_tskp = hp->hrec->hin_tskp;
6457    break;
6458   default:
6459    __vpi_err(1870, vpiError,
6460     "vpi_control vpiSetInteractiveScope argument not scope handle - %s illegal",
6461     __to_vpionam(__wrks1, hp->hrec->htyp));
6462    return(FALSE);
6463   }
6464 
6465  /* because not really entering interactive mode no db line change */
6466  if (__tfrec_hdr != NULL) __call_misctfs_scope();
6467  if (__have_vpi_actions) __vpi_iactscopechg_trycall();
6468  return(TRUE);
6469 }
6470 
6471 /*
6472  * some error message output routines that need vpi_ mechanism
6473  */
__emit_vpi_noiact_warn(void)6474 extern void __emit_vpi_noiact_warn(void)
6475 {
6476  __vpi_err(2029, vpiWarning,
6477   "vpi_control vpiStop no effect - interactive environment disabled");
6478 }
6479 
__emit_vpi_iniact_warn(void)6480 extern void __emit_vpi_iniact_warn(void)
6481 {
6482  __vpi_err(2031, vpiWarning,
6483   "vpi_control vpiStop no effect - already in interactive debugger");
6484 }
6485 
6486 /*
6487  * turn on (enable) or off (disable) call back
6488  *
6489  * works for any call back except time related
6490  * LOOKATME - maybe should always re-enable on reset
6491  */
do_vpi_cb_onoff(vpiHandle cbobj,int32 turn_cb_on)6492 static int32 do_vpi_cb_onoff(vpiHandle cbobj, int32 turn_cb_on)
6493 {
6494  register struct dceauxlst_t *dceauxlp;
6495  struct h_t *hp;
6496  struct hrec_t *hrp;
6497  struct cbrec_t *cbp;
6498  char s1[RECLEN], s2[RECLEN];
6499 
6500  if (turn_cb_on) strcpy(s1, "vpiEnableCb"); else strcpy(s1, "vpiDisableCb");
6501  hp = (struct h_t *) cbobj;
6502  sprintf(s2, "vpi_control %s operation", s1);
6503  if (!__validate_handle(s2, hp)) return(FALSE);
6504  hrp = hp->hrec;
6505  cbp = hrp->hu.hcbp;
6506 
6507  if (hrp->htyp != vpiCallback)
6508   {
6509    __vpi_err(1832, vpiError,
6510     "vpi_control %s operation requires vpiCallback handle - %s illegal",
6511     s1,__to_vpionam(__wrks1, hrp->htyp));
6512    return(FALSE);
6513   }
6514 
6515  switch (cbp->cb_reason) {
6516   case cbAtStartOfSimTime: case cbReadWriteSynch: case cbReadOnlySynch:
6517   case cbNextSimTime: case cbAfterDelay: case cbLanguageLine:
6518    __vpi_err(1930, vpiError,
6519     "vpi_control %s illegal for time related %s call back",
6520     s1, __cb_reason_to_nam(__xs, cbp->cb_reason));
6521    return(FALSE);
6522   default: break;
6523  }
6524 
6525  if (turn_cb_on)
6526   {
6527    if (!cbp->cb_user_off)
6528     {
6529      /* SJM 07/26/00 - if call back run with reentry to itself turned off */
6530      /* allow enabling so can be re-entered */
6531      if (cbp->cb_reason == cbValueChange || cbp->cb_reason == cbForce
6532       || cbp->cb_reason == cbRelease)
6533       {
6534        /* turn on all dce's - temporarily off */
6535        for (dceauxlp = cbp->cbdcep; dceauxlp != NULL;
6536         dceauxlp = dceauxlp->dclnxt)
6537         {
6538          dceauxlp->ldcep->dce_off = FALSE;
6539         }
6540        return(TRUE);
6541       }
6542 
6543      __vpi_err(2033, vpiWarning,
6544       "vpi_control %s no effect - attempt to enable already enabled %s call back",
6545       s1, __cb_reason_to_nam(__xs, cbp->cb_reason));
6546      return(FALSE);
6547     }
6548   }
6549  else
6550   {
6551    if (cbp->cb_user_off)
6552     {
6553      __vpi_err(2033, vpiWarning,
6554       "vpi_control %s no effect - attempt to disable already disabled %s call back",
6555      s1, __cb_reason_to_nam(__xs, cbp->cb_reason));
6556      return(FALSE);
6557     }
6558   }
6559  cbp->cb_user_off = (turn_cb_on) ? FALSE : TRUE;
6560 
6561  /* change on/off state of each dc evetn */
6562  /* LOOKATME - what happen with all forms force/release */
6563  for (dceauxlp = cbp->cbdcep; dceauxlp != NULL; dceauxlp = dceauxlp->dclnxt)
6564   {
6565    dceauxlp->ldcep->dce_off = (turn_cb_on) ? FALSE : TRUE;
6566   }
6567  return(TRUE);
6568 }
6569 
6570 
6571 /*
6572  * ROUTINES TO FREE VPI_ OBJECTS FOR RESET
6573  */
6574 
6575 /*
6576  * reinitialize the vpi_ mechanism
6577  *
6578  * possible net's putv rec left but driver reinitialized to z elsewhere
6579  * do not free handles - DOCUMENT can be large source of memory drain
6580  */
__reinit_vpi(void)6581 extern void __reinit_vpi(void)
6582 {
6583  register struct cbrec_t *cbp, *cbp2;
6584  int32 save_simstate;
6585 
6586  /* free time related in lists that are not in event queues */
6587  __rosync_slot = FALSE;
6588 
6589  /* remove time related call backs only */
6590  for (cbp = __vpi_cbrec_hdr; cbp != NULL;)
6591   {
6592    cbp2 = cbp->cbnxt;
6593    /* only remove scheduled time related or value change related */
6594    switch (cbp->cb_reason) {
6595     /* remove all time and change cbs but leave all actions */
6596     case cbAtStartOfSimTime: case cbReadWriteSynch: case cbReadOnlySynch:
6597     case cbNextSimTime: case cbAfterDelay:
6598      /* this links out but works because nxt if present always remains */
6599      /* using user level routine but before sim has begun (fake sim) */
6600      save_simstate = __run_state;
6601      __run_state = SS_SIM;
6602      if (!vpi_remove_cb((vpiHandle) cbp->cb_cbhp))
6603        __vpi_terr(__FILE__, __LINE__);
6604      __run_state = save_simstate;
6605      break;
6606     default:
6607      break;
6608    }
6609    if (cbp2 == NULL) break;
6610    cbp = cbp2;
6611   }
6612 }
6613 
6614 /*
6615  * ROUTINES TO ACCESS INTERNAL INFO
6616  */
6617 
6618 /*
6619  * get version information and set pointers to argv/argc
6620  *
6621  * this is passed struct - routines fills in ptrs
6622  */
vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p)6623 extern PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p)
6624 {
6625  char s1[RECLEN];
6626 
6627  /* only build nested vpi format argv if first time */
6628  if (__vpi_argv == NULL) __bld_vpi_argv();
6629 
6630  vlog_info_p->argc = __vpi_argc;
6631  vlog_info_p->argv = __vpi_argv;
6632 
6633  sprintf(s1, "%s%s of %s (%s).\n", __vers, __vers2, __ofdt, __platform);
6634  vlog_info_p->product = __pv_stralloc("Cver Verilog Simulator");
6635  vlog_info_p->version = __pv_stralloc(s1);
6636  return(TRUE);
6637 }
6638 
6639 /*
6640  * undocumented (to users) debug routine for showing contents of handle
6641  *
6642  * LOOKATME - maybe should dump more information for some object types
6643  * LOOKATME - not portable because of addr cast
6644  */
__vpi_show_object(vpiHandle obj)6645 extern int32 __vpi_show_object(vpiHandle obj)
6646 {
6647  int32 bad_inst, bad_tsk, first_time, ttyp, tryget_name;
6648  struct h_t *hp;
6649  struct hrec_t *hrp;
6650  char *chp, s1[RECLEN], s2[RECLEN];
6651 
6652  __my_fprintf(stdout, ">>> showing vpi_ object:\n");
6653  hp = (struct h_t *) obj;
6654 
6655  if (!__chk_showobj(hp, &(bad_inst), &(bad_tsk))) return(0);
6656  hrp = hp->hrec;
6657 
6658  tryget_name = TRUE;
6659  if (!__validate_otyp(hrp->htyp))
6660   {
6661    __my_fprintf(stdout,
6662     "**object bad: object type %d illegal - showing anyway\n", hrp->htyp);
6663    tryget_name = FALSE;
6664   }
6665  else
6666   {
6667    __my_fprintf(stdout, "Object type: %s (addr %lx)",
6668     __to_vpionam(s1, hrp->htyp), (word32) hp);
6669   }
6670  if (hrp->htyp2 != 0)
6671   {
6672    if (!__validate_otyp(hrp->htyp2))
6673     {
6674      __my_fprintf(stdout,
6675       "\n**object bad: secondary type %d illegal\n", hrp->htyp2);
6676      tryget_name = FALSE;
6677     }
6678    else
6679     {
6680      __my_fprintf(stdout, " (secondary type: %s)",
6681       __to_vpionam(s1, hrp->htyp2));
6682     }
6683   }
6684  if (!bad_inst && !bad_tsk)
6685   {
6686    if (hp->hin_itp == NULL)
6687     {
6688      __my_fprintf(stdout, " **no associated instance**");
6689     }
6690    else
6691     {
6692      __my_fprintf(stdout, " in %s", __msg_blditree(s1, hp->hin_itp,
6693       hrp->hin_tskp));
6694      if (hrp->hin_tskp != NULL)
6695       {
6696        ttyp = __to_vpi_tasktyp(hrp->hin_tskp->tsktyp);
6697        __my_fprintf(stdout, " (%s)\n", __to_vpionam(s1, ttyp));
6698       }
6699     }
6700   }
6701  else if (!bad_inst && bad_tsk)
6702   {
6703    if (hp->hin_itp != NULL)
6704     {
6705      __my_fprintf(stdout, " in %s (**task/func bad**)",
6706       __msg2_blditree(s1, hp->hin_itp));
6707     }
6708    tryget_name = FALSE;
6709   }
6710  else if (bad_inst && !bad_tsk)
6711   {
6712    ttyp = __to_vpi_tasktyp(hrp->hin_tskp->tsktyp);
6713    __my_fprintf(stdout, " **bad instance** but in %s %s",
6714     __to_vpionam(s1, ttyp), hrp->hin_tskp->tsksyp->synam);
6715    tryget_name = FALSE;
6716   }
6717  else
6718   {
6719    __my_fprintf(stdout, " **bad instance and bad task**");
6720    tryget_name = FALSE;
6721   }
6722 
6723  /* LOOKATME - maybe should try to get def name if can */
6724  if (tryget_name)
6725   {
6726    __acc_vpi_erroff = TRUE;
6727    /* this access error vpi_ error info and turns off vpi error cbs */
6728    /* for objects without names, expect fail here */
6729    chp = vpi_get_str(vpiName, obj);
6730    if (chp != NULL && !__my_vpi_chk_error())
6731     {
6732      __my_fprintf(stdout, " name=%s", chp);
6733     }
6734   }
6735  __my_fprintf(stdout, "\n");
6736 
6737  /* build the telltales */
6738  strcpy(s2, "  [");
6739  first_time = TRUE;
6740  if (hrp->hi != -1)
6741   {
6742    sprintf(s1, "index=%d", hrp->hi);
6743    strcat(s2, s1);
6744    if (first_time) first_time = FALSE;
6745   }
6746  if (hrp->in_iter)
6747   {
6748    if (!first_time) strcat(s2, ", "); else first_time = FALSE;
6749    strcat(s2, "in interator");
6750   }
6751  if (hrp->free_xpr)
6752   {
6753    if (!first_time) strcat(s2, ", "); else first_time = FALSE;
6754    strcat(s2, "Created object");
6755   }
6756  if (hrp->htyp == vpiSchedEvent || hrp->htyp == vpiSchedBitEvent)
6757   {
6758    if (!first_time) strcat(s2, ", "); else first_time = FALSE;
6759    sprintf(s1, "Schedule event done=%d", hrp->evnt_done);
6760    strcat(s2, s1);
6761   }
6762  if (hrp->bith_ndx)
6763   {
6764    if (!first_time) strcat(s2, ", "); else first_time = FALSE;
6765    strcat(s2, "Variable index");
6766   }
6767 
6768  if (!first_time) __my_fprintf(stdout, "%s]\n", s2);
6769 
6770  /* set globals for user to look at in case debugging turned on */
6771  __cur_vpi_inst = hp;
6772  __cur_vpi_obj = hrp;
6773  return(1);
6774 }
6775 
6776 /*
6777  * show object check handle
6778  */
__chk_showobj(struct h_t * hp,int32 * bad_inst,int32 * bad_task)6779 extern int32 __chk_showobj(struct h_t *hp, int32 *bad_inst, int32 *bad_task)
6780 {
6781  struct hrec_t *hrp;
6782 
6783  /* if low value bad since ptr */
6784  /* SJM 07/08/01 - need to compare to uint32 not int32 since >2G high bit on */
6785  if (hp == NULL || ((word32) hp) < 256)
6786   {
6787    __my_fprintf(stdout,
6788     "**object bad: address (%p) null or illegal low address\n", hp);
6789    return(FALSE);
6790   }
6791  hrp = hp->hrec;
6792  /* SJM 07/08/01 - need to compare to uint32 not int32 since >2G high bit on */
6793  if (hrp == NULL || ((word32) hrp) < 256)
6794   {
6795    __my_fprintf(stdout,
6796     "**object bad: net list pointer (%p) null or illegal low address\n", hrp);
6797    return(FALSE);
6798   }
6799  if (hrp->h_magic != PVH_MAGIC)
6800   {
6801    __my_fprintf(stdout,
6802     "**object bad: illegal magic number (%x) - showing anyway\n",
6803     hrp->h_magic);
6804   }
6805  *bad_inst = FALSE;
6806  /* SJM 07/08/01 - need to compare to uint32 not int32 since >2G high bit on */
6807  if (hp->hin_itp != NULL && ((word32) hp->hin_itp) < 256)
6808   {
6809    __my_fprintf(stdout,
6810     "**object bad: instance address (%p) probably illegal\n", hp->hin_itp);
6811    *bad_inst = TRUE;
6812   }
6813  *bad_task = FALSE;
6814  /* SJM 07/08/01 - need to compare to uint32 not int32 since >2G high bit on */
6815  if (hrp->hin_tskp != NULL && ((word32) (hrp->hin_tskp)) < 256)
6816   {
6817    __my_fprintf(stdout,
6818     "**object bad: task/func address (%p) probably illegal\n",
6819     hrp->hin_tskp);
6820    *bad_task = TRUE;
6821   }
6822  return(TRUE);
6823 }
6824 
6825 /*
6826  * VPI CONSTANT TO NAME CONVERSION ROUTINES
6827  */
6828 
6829 /* dense table indexed by constant object value */
6830 /* fast indexing of dense table works because vpi object numbers */
6831 /* fixed for .o file interchangeabiliy */
6832 
6833 /* if vpi_user.h official LRM constant values change, must change this */
6834 /* constant in table so can use debugging code to check for dense order */
6835 static struct onamvpi_t onames_vpi[] = {
6836  /* notice object types can also sometimes be access methods */
6837  { "**unused-obj-const**", 0 },
6838  { "vpiAlways", vpiAlways },
6839  { "vpiAssignStmt", vpiAssignStmt },
6840  { "vpiAssignment", vpiAssignment },
6841  { "vpiBegin", vpiBegin },
6842  { "vpiCase", vpiCase },
6843  { "vpiCaseItem", vpiCaseItem },
6844  { "vpiConstant", vpiConstant },
6845  { "vpiContAssign", vpiContAssign },
6846  { "vpiDeassign", vpiDeassign },
6847  { "vpiDefParam", vpiDefParam },
6848  { "vpiDelayControl", vpiDelayControl },
6849  { "vpiDisable", vpiDisable },
6850  { "vpiEventControl", vpiEventControl },
6851  { "vpiEventStmt", vpiEventStmt },
6852  { "vpiFor", vpiFor },
6853  { "vpiForce", vpiForce },
6854  { "vpiForever", vpiForever },
6855  { "vpiFork", vpiFork },
6856  { "vpiFuncCall", vpiFuncCall },
6857  { "vpiFunction", vpiFunction },
6858  { "vpiGate", vpiGate },
6859  { "vpiIf", vpiIf },
6860  { "vpiIfElse", vpiIfElse },
6861  { "vpiInitial", vpiInitial },
6862  { "vpiIntegerVar", vpiIntegerVar },
6863  { "vpiInterModPath", vpiInterModPath },
6864  { "vpiIterator", vpiIterator },
6865  { "vpiIODecl", vpiIODecl },
6866  { "vpiMemory", vpiMemory },
6867  { "vpiMemoryWord", vpiMemoryWord },
6868  { "vpiModPath", vpiModPath },
6869  { "vpiModule", vpiModule },
6870  { "vpiNamedBegin", vpiNamedBegin },
6871  { "vpiNamedEvent", vpiNamedEvent },
6872  { "vpiNamedFork", vpiNamedFork },
6873  { "vpiNet", vpiNet },
6874  { "vpiNetBit", vpiNetBit },
6875  { "vpiNullStmt", vpiNullStmt },
6876  { "vpiOperation", vpiOperation },
6877  { "vpiParamAssign", vpiParamAssign },
6878  { "vpiParameter", vpiParameter },
6879  { "vpiPartSelect", vpiPartSelect },
6880  { "vpiPathTerm", vpiPathTerm },
6881  { "vpiPort", vpiPort },
6882  { "vpiPortBit", vpiPortBit },
6883  { "vpiPrimTerm", vpiPrimTerm },
6884  { "vpiRealVar", vpiRealVar },
6885  { "vpiReg", vpiReg },
6886  { "vpiRegBit", vpiRegBit },
6887  { "vpiRelease", vpiRelease },
6888  { "vpiRepeat", vpiRepeat },
6889  { "vpiRepeatControl", vpiRepeatControl },
6890  { "vpiSchedEvent", vpiSchedEvent },
6891  { "vpiSpecParam", vpiSpecParam },
6892  { "vpiSwitch", vpiSwitch },
6893  { "vpiSysFuncCall", vpiSysFuncCall },
6894  { "vpiSysTaskCall", vpiSysTaskCall },
6895  { "vpiTableEntry", vpiTableEntry },
6896  { "vpiTask", vpiTask },
6897  { "vpiTaskCall", vpiTaskCall },
6898  { "vpiTchk", vpiTchk },
6899  { "vpiTchkTerm", vpiTchkTerm },
6900  { "vpiTimeVar", vpiTimeVar },
6901  { "vpiTimeQueue", vpiTimeQueue },
6902  { "vpiUdp", vpiUdp },
6903  { "vpiUdpDefn", vpiUdpDefn },
6904  { "vpiUserSystf", vpiUserSystf },
6905  { "vpiVarSelect", vpiVarSelect },
6906  { "vpiWait", vpiWait },
6907  { "vpiWhile", vpiWhile },
6908  /* methods */
6909  { "vpiCondition", vpiCondition },
6910  { "vpiDelay", vpiDelay },
6911  { "vpiElseStmt", vpiElseStmt },
6912  { "vpiForIncStmt", vpiForIncStmt },
6913  { "vpiForInitStmt", vpiForInitStmt },
6914  { "vpiHighConn", vpiHighConn },
6915  { "vpiLhs", vpiLhs },
6916  { "vpiIndex", vpiIndex },
6917  { "vpiLeftRange", vpiLeftRange },
6918  { "vpiLowConn", vpiLowConn },
6919  { "vpiParent", vpiParent },
6920  { "vpiRhs", vpiRhs },
6921  { "vpiRightRange", vpiRightRange },
6922  { "vpiScope", vpiScope },
6923  /* notice this is only an iterator or 1-to-1 method */
6924  { "vpiSysTfCall", vpiSysTfCall },
6925  { "vpiTchkDataTerm", vpiTchkDataTerm },
6926  { "vpiTchkNotifier", vpiTchkNotifier },
6927  { "vpiTchkRefTerm", vpiTchkRefTerm },
6928  /* 1 to many methods */
6929  { "vpiArgument", vpiArgument },
6930  { "vpiBit", vpiBit },
6931  { "vpiDriver", vpiDriver },
6932  { "vpiInternalScope", vpiInternalScope },
6933  { "vpiLoad", vpiLoad },
6934  { "vpiModDataPathIn", vpiModDataPathIn },
6935  { "vpiModPathIn", vpiModPathIn },
6936  { "vpiModPathOut", vpiModPathOut },
6937  { "vpiOperand", vpiOperand },
6938  { "vpiPortInst", vpiPortInst },
6939  { "vpiProcess", vpiProcess },
6940  { "vpiVariables", vpiVariables  },
6941  { "vpiUse", vpiUse },
6942  /* 1-to-1 or 1 to many methods */
6943  { "vpiExpr", vpiExpr },
6944  { "vpiPrimitive", vpiPrimitive },
6945  { "vpiStmt", vpiStmt },
6946 
6947  /* object types added for Verilog 2000 - some moved from cv vpi inc file */
6948  { "vpiAttribute", vpiAttribute },
6949  { "vpiBitSelect", vpiBitSelect },
6950  { "vpiCallback", vpiCallback },
6951  { "vpiDelayTerm", vpiDelayTerm },
6952  { "vpiDelayDevice", vpiDelayDevice },
6953  { "vpiFrame", vpiFrame },
6954  { "vpiGateArray", vpiGateArray },
6955  { "vpiModuleArray", vpiModuleArray },
6956  { "vpiPrimitiveArray", vpiPrimitiveArray },
6957  { "vpiNetArray", vpiNetArray },
6958  { "vpiRange", vpiRange },
6959  { "vpiRegArray", vpiRegArray },
6960  { "vpiSwitchArray", vpiSwitchArray },
6961  { "vpiUdpArray", vpiUdpArray },
6962  /* methods added for Verilog 2000 - some moved from cv vpi inc file */
6963  { "vpiActiveTimeFormat", vpiActiveTimeFormat },
6964  { "vpiInTerm", vpiInTerm },
6965  { "vpiInstanceArray", vpiInstanceArray },
6966  { "vpiLocalDriver", vpiLocalDriver },
6967  { "vpiLocalLoad", vpiLocalLoad },
6968  { "vpiOutTerm", vpiOutTerm },
6969  { "vpiPorts", vpiPorts },
6970  { "vpiSimNet", vpiSimNet },
6971  { "vpiTaskFunc", vpiTaskFunc },
6972  { "vpiContAssignBit", vpiContAssignBit },
6973  { "vpiNamedEventArray", vpiNamedEventArray }
6974 };
6975 #define NVOTYPS (sizeof(onames_vpi) / sizeof(struct onamvpi_t))
6976 
6977 /* added for Cver handles in separate range */
6978 /* Cver added handles - pending to be added to P1364 */
6979 /* position must match offset constant in .h file (not alphabetical) */
6980 static struct onamvpi_t cv_onames_vpi[] = {
6981  { "vpiNetDriver", vpiNetDriver },
6982  { "vpiNetBitDriver", vpiNetBitDriver },
6983  { "vpiSchedBitEvent", vpiSchedBitEvent },
6984  { "vpiPoundParam", vpiPoundParam },
6985  { "vpiOneOfEachMod", vpiOneOfEachMod }
6986 };
6987 #define CV_NVOTYPS (sizeof(cv_onames_vpi) / sizeof(struct onamvpi_t))
6988 
6989 
6990 /*
6991  * convert the vpi object constant value to a name
6992  * if out of range returns nil
6993  * table dense and starting at 0
6994  */
__to_vpionam(char * s,word32 vpioval)6995 extern char *__to_vpionam(char *s, word32 vpioval)
6996 {
6997  if (vpioval < 1) goto outofrng;
6998  if (vpioval < NVOTYPS)
6999   {
7000    strcpy(s, onames_vpi[vpioval].vpiobjnam);
7001    return(s);
7002   }
7003  if (vpioval >= CV_START_ONUMS && vpioval < (CV_START_ONUMS + CV_NVOTYPS))
7004   {
7005    strcpy(s, cv_onames_vpi[vpioval - CV_START_ONUMS].vpiobjnam);
7006    return(s);
7007   }
7008 
7009 outofrng:
7010  sprintf(s, "**out of range (%lu)", vpioval);
7011  return(s);
7012 }
7013 
7014 /*
7015  * return T if object type legal
7016  * if out of range returns nil
7017  * table dense and starting at 0
7018  */
__validate_otyp(word32 vpioval)7019 extern int32 __validate_otyp(word32 vpioval)
7020 {
7021  if (vpioval < 1) return(FALSE);
7022  if (vpioval < NVOTYPS) return(TRUE);
7023  if (vpioval >= CV_START_ONUMS && vpioval < (CV_START_ONUMS + CV_NVOTYPS))
7024   return(TRUE);
7025 
7026  return(FALSE);
7027 }
7028 
7029 /* dense array of vpi properties */
7030 /* position must match offset constant in .h file */
7031 static struct pnamvpi_t pnames_vpi[] = {
7032  { "**unused-prop-const**", 0 },
7033  { "vpiType", vpiType },
7034  { "vpiName", vpiName },
7035  { "vpiFullName", vpiFullName },
7036  { "vpiSize", vpiSize },
7037  { "vpiFile", vpiFile },
7038  { "vpiLineNo", vpiLineNo },
7039  /* module properties */
7040  { "vpiTopModule", vpiTopModule },
7041  { "vpiCellInstance", vpiCellInstance },
7042  { "vpiDefName", vpiDefName },
7043  { "vpiProtected", vpiProtected },
7044  { "vpiTimeUnit", vpiTimeUnit },
7045  { "vpiTimePrecision", vpiTimePrecision },
7046  { "vpiDefNetType", vpiDefNetType },
7047  { "vpiUnconnDrive", vpiUnconnDrive },
7048  { "vpiDefFile", vpiDefFile },
7049  { "vpiDefLineNo", vpiDefLineNo },
7050  /* port and net properties */
7051  { "vpiScalar", vpiScalar },
7052  { "vpiVector", vpiVector },
7053  { "vpiExplictName", vpiExplicitName },
7054  { "vpiDirection", vpiDirection },
7055  { "vpiConnByName", vpiConnByName },
7056  { "vpiNetType", vpiNetType },
7057  { "vpiExplicitScalared", vpiExplicitScalared },
7058  { "vpiExplicitVectored", vpiExplicitVectored },
7059  { "vpiExpanded", vpiExpanded },
7060  { "vpiImplicitDecl", vpiImplicitDecl },
7061  { "vpiChargeStrength", vpiChargeStrength  },
7062  { "vpiArray", vpiArray },
7063  { "vpiPortIndex", vpiPortIndex },
7064  /* gate and terminal properties */
7065  { "vpiTermIndex", vpiTermIndex },
7066  { "vpiStrength0", vpiStrength0 },
7067  { "vpiStrength1", vpiStrength1 },
7068  { "vpiPrimType", vpiPrimType },
7069  /* path, path terminal, timing check properties */
7070  { "vpiPolarity", vpiPolarity },
7071  { "vpiDataPolarity", vpiDataPolarity },
7072  { "vpiEdge", vpiEdge },
7073  { "vpiPathType", vpiPathType },
7074  { "vpiTchkType", vpiTchkType },
7075  /* expression properties */
7076  { "vpiOpType", vpiOpType },
7077  { "vpiConstType", vpiConstType },
7078  { "vpiBlocking", vpiBlocking },
7079  { "vpiCaseType", vpiCaseType },
7080  { "vpiNetDeclAssign", vpiNetDeclAssign },
7081  /* system taskfunc properties */
7082  { "vpiFuncType", vpiFuncType },
7083  { "vpiUserDefn", vpiUserDefn },
7084  { "vpiScheduled", vpiScheduled },
7085  { "vpiDefDelayMode", vpiDefDelayMode },
7086  { "vpiDefDecayTime", vpiDefDecayTime },
7087  { "vpiActive", vpiActive },
7088  { "vpiAutomatic", vpiAutomatic },
7089  { "vpiCell", vpiCell },
7090  { "vpiConfig", vpiConfig },
7091  { "vpiConstantSelect", vpiConstantSelect },
7092  { "vpiDecompile", vpiDecompile },
7093  { "vpiDefAttribute", vpiDefAttribute },
7094  { "vpiDelayType", vpiDelayType },
7095  { "vpiIteratorType", vpiIteratorType },
7096  { "vpiLibrary", vpiLibrary },
7097  { "vpiMultiArray", vpiMultiArray },
7098  { "vpiOffset", vpiOffset },
7099  { "vpiResolvedNetType", vpiResolvedNetType },
7100  { "vpiSaveRestartID", vpiSaveRestartID },
7101  { "vpiSaveRestartLocation", vpiSaveRestartLocation },
7102  { "vpiValid", vpiValid },
7103  { "vpiSigned", vpiSigned },
7104  { "vpiStop", vpiStop },
7105  { "vpiFinish", vpiFinish },
7106  { "vpiReset", vpiReset },
7107  { "vpiSetInteractiveScope", vpiSetInteractiveScope },
7108  { "vpiLocalParam", vpiLocalParam },
7109  { "vpiModPathHasIfNone", vpiModPathHasIfNone },
7110 };
7111 #define NVPTYPS (sizeof(pnames_vpi) / sizeof(struct pnamvpi_t))
7112 
7113 
7114 /* LOOKATME - is it true there are no Cver added properties? */
7115 
7116 
7117 /*
7118  * routine to acess vpi property name given constant value
7119  * could index but would not catch inconsistencies after standard changes
7120  */
__to_vpipnam(char * s,int32 pval)7121 extern char *__to_vpipnam(char *s, int32 pval)
7122 {
7123  if (pval == vpiUndefined) { strcpy(s, "vpiUndefined"); return(s); }
7124 
7125  if (pval >= 1 && pval < NVPTYPS)
7126   {
7127    strcpy(s, pnames_vpi[pval].vpipropnam);
7128    return(s);
7129   }
7130  sprintf(s, "**property out of range (%d)", pval);
7131  return(s);
7132 }
7133 
7134 /* table of vpi_ operator names */
7135 static struct opnamvpi_t opnames_vpi[] = {
7136  { "**unused-operator-const**", 0, "UNUSED" },
7137  { "vpiMinusOp", vpiMinusOp, "-" },
7138  { "vpiPlusOp", vpiPlusOp, "+" },
7139  { "vpiNotOp", vpiNotOp, "!" },
7140  { "vpiBitNegOp", vpiBitNegOp, "~" },
7141  { "vpiUnaryAndOp", vpiUnaryAndOp, "&" },
7142  { "vpiUnaryNandOp", vpiUnaryNandOp, "&~" },
7143  { "vpiUnaryOrOp", vpiUnaryOrOp, "|" },
7144  { "vpiUnaryNorOp", vpiUnaryNorOp, "^~" },
7145  { "vpiUnaryXorOp", vpiUnaryXorOp, "^" },
7146  { "vpiUnaryXNorOp", vpiUnaryXNorOp, "^~" },
7147  { "vpiSubOp", vpiSubOp, "-" },
7148  { "vpiDivOp", vpiDivOp, "/"  },
7149  { "vpiModOp", vpiModOp, "%"  },
7150  { "vpiEqOp", vpiEqOp, "==" },
7151  { "vpiNeqOp", vpiNeqOp, "!=" },
7152  { "vpiCaseEqOp", vpiCaseEqOp, "==="  },
7153  { "vpiCaseNeqOp", vpiCaseNeqOp, "!=="  },
7154  { "vpiGtOp", vpiGtOp, ">" },
7155  { "vpiGeOp", vpiGeOp, ">=" },
7156  { "vpiLtOp", vpiLtOp, "<" },
7157  { "vpiLeOp", vpiLeOp, "<=" },
7158  { "vpiLShiftOp", vpiLShiftOp, "<<" },
7159  { "vpiRShiftOp", vpiRShiftOp, ">>" },
7160  { "vpiAddOp", vpiAddOp, "+" },
7161  { "vpiMultOp", vpiMultOp, "*" },
7162  { "vpiLogAndOp", vpiLogAndOp, "&" },
7163  { "vpiLogOrOp", vpiLogOrOp, "||" },
7164  { "vpiBitAndOp", vpiBitAndOp, "&" },
7165  { "vpiBitOrOp", vpiBitOrOp, "|" },
7166  { "vpiBitXorOp", vpiBitXorOp, "^" },
7167  { "vpiBitXNorOp", vpiBitXNorOp, "^~" },
7168  { "vpiConditionOp", vpiConditionOp, "?" },
7169  { "vpiConcatOp", vpiConcatOp, "{" },
7170  { "vpiMultiConcatOp", vpiMultiConcatOp, "{" },
7171  { "vpiEventOrOp", vpiEventOrOp, "OR" },
7172  { "vpiNullOp", vpiNullOp, "" },
7173  { "vpiListOp", vpiListOp, "," },
7174  { "vpiMinTypMaxOp", vpiMinTypMaxOp, "(::)" },
7175  { "vpiPosedgeOp", vpiPosedgeOp, "posedge" },
7176  { "vpiNegedgeOp", vpiNegedgeOp, "negedge" }
7177 };
7178 #define NVOPTYPS (sizeof(opnames_vpi) / sizeof(struct opnamvpi_t))
7179 
7180 /*
7181  * routine to acess vpi expression operator name given constant value
7182  * could index but would not catch inconsistencies after standard changes
7183  */
__to_vpiopnam(char * s,int32 opval)7184 extern char *__to_vpiopnam(char *s, int32 opval)
7185 {
7186  if (opval == vpiUndefined) { strcpy(s, "vpiUndefined"); return(s); }
7187  if (opval < 1 || opval >= NVOPTYPS)
7188   { sprintf(s, "**operator out of range (%d)", opval); return(s); }
7189  strcpy(s, opnames_vpi[opval].vpiopnam);
7190  return(s);
7191 }
7192 
7193 /*
7194  * routine to acess vpi expression operator name given constant value
7195  * could index but would not catch inconsistencies after standard changes
7196  */
__to_vpiopchar(char * s,int32 opval)7197 extern char *__to_vpiopchar(char *s, int32 opval)
7198 {
7199  if (opval == vpiUndefined) { strcpy(s, "<UNDEF>"); return(s); }
7200  if (opval < 1 || opval >= NVOPTYPS)
7201   { sprintf(s, "**operator out of range (%d)", opval); return(s); }
7202  strcpy(s, opnames_vpi[opval].vpiopchar);
7203  return(s);
7204 }
7205 
7206 /*
7207  * emit common simulation has not begun (or reset in progress) error
7208  */
__sim_notbegun_err(char * rnam)7209 extern void __sim_notbegun_err(char *rnam)
7210 {
7211  __vpi_err(1927, vpiError,
7212   "%s - routine not callable - simulation not started (or reset in progress)",
7213   rnam);
7214 }
7215 
7216 /*
7217  * emit common compilation in progress (no n.l to traverse) message
7218  */
__still_comp_err(char * rnam)7219 extern void __still_comp_err(char *rnam)
7220 {
7221  __vpi_err(1923, vpiError,
7222   "%s routine not callable - design translation not completed", rnam);
7223 }
7224 
7225 /*
7226  * emit common write or schedule during ro_synch section
7227  */
__bad_rosync_err(char * rnam)7228 extern void __bad_rosync_err(char *rnam)
7229 {
7230  __vpi_err(1922, vpiError,
7231   "%s routine not callable during ro sync - schedule for current time or write", rnam);
7232 }
7233 
7234 /*
7235  * validate a non iterator handle
7236  */
__validate_nonit_handle(char * rnam,struct h_t * hp)7237 extern int32 __validate_nonit_handle(char *rnam, struct h_t *hp)
7238 {
7239  if (!__validate_handle(rnam, hp)) return(FALSE);
7240  if (hp->hrec->htyp != vpiIterator) return(TRUE);
7241  __vpi_err(1815, vpiError,
7242   "%s: iterator handle illegal in this context", rnam);
7243  return(FALSE);
7244 }
7245 
7246 /*
7247  * validate a handle - returns F on error
7248  *
7249  * LOOKATME - acc_ handle passed to here may work and not checked for
7250  * FIXME - need compile -D switch than turns off most checking
7251  */
__validate_handle(char * rnam,register struct h_t * hp)7252 extern int32 __validate_handle(char *rnam, register struct h_t *hp)
7253 {
7254  register struct hrec_t *hrp;
7255 
7256  /* if low value bad since ptr */
7257  /* SJM 07/08/01 - need to compare to uint32 not int32 since >2G high bit on */
7258  if (hp == NULL || ((word32) hp) < 256)
7259   {
7260    strcpy(__wrks1, "** NULL OR LOW NUMBER **");
7261    goto bad_handle;
7262   }
7263  hrp = hp->hrec;
7264  /* SJM 07/08/01 - need to compare to uint32 not int32 since >2G high bit on */
7265  if (hrp == NULL || ((word32) hrp) < 256 || hrp->h_magic != PVH_MAGIC)
7266   {
7267    strcpy(__wrks1, "** PTR INTO DATA BASE ILLEGAL **");
7268    goto bad_handle;
7269   }
7270  if (!__validate_otyp(hrp->htyp))
7271   {
7272    sprintf(__wrks1, "%d", hrp->htyp);
7273    goto bad_handle;
7274   }
7275  return(TRUE);
7276 
7277 bad_handle:
7278  __vpi_err(1818, vpiError,
7279   "%s: handle illegal magic number or type %s illegal", rnam, __wrks1);
7280  return(FALSE);
7281 }
7282 
7283 /*
7284  * validate access method handle
7285  * returns F on error
7286  */
__validate_accessm(char * rnam,int32 otype,char * accessm)7287 extern int32 __validate_accessm(char *rnam, int32 otype, char *accessm)
7288 {
7289  if (!__validate_otyp(otype))
7290   {
7291    __vpi_err(1819, vpiError,
7292     "%s: access method type (can be handle type) %d for %s illegal or out of range",
7293     rnam, otype, accessm);
7294    return(FALSE);
7295   }
7296  return(TRUE);
7297 }
7298 
7299 /*
7300  * validate a vpi time type field
7301  */
__validate_time_type(char * rnam,int32 timtyp)7302 extern int32 __validate_time_type(char *rnam, int32 timtyp)
7303 {
7304  if (timtyp == vpiScaledRealTime || timtyp == vpiSimTime
7305   || timtyp == vpiSuppressTime) return(TRUE);
7306  __vpi_err(1820, vpiError,
7307   "%s: vpi time type value (%d) illegal", rnam, timtyp);
7308  return(FALSE);
7309 }
7310 
7311 /*
7312  * validate a vpi value format field
7313  */
__validate_value_fmt(char * rnam,int32 fmt)7314 extern int32 __validate_value_fmt(char *rnam, int32 fmt)
7315 {
7316  switch (fmt) {
7317   case vpiBinStrVal: case vpiOctStrVal: case vpiHexStrVal:
7318   case vpiDecStrVal: case vpiScalarVal: case vpiIntVal:
7319   case vpiRealVal: case vpiStringVal: case vpiVectorVal:
7320   case vpiStrengthVal: case vpiSuppressVal: case vpiTimeVal:
7321   case vpiObjTypeVal:
7322    return(TRUE);
7323   default:
7324    __vpi_err(1822, vpiError,
7325    "%s: vpi value format value (%d) illegal", rnam, fmt);
7326  }
7327  return(FALSE);
7328 }
7329 
7330 /*
7331  * vpi internal fatal error
7332  */
__vpi_terr(char * fnam,int32 lno)7333 extern void __vpi_terr(char *fnam, int32 lno)
7334 {
7335  __vpi_err(303, vpiInternal,
7336   "VPI INTERNAL ERROR** - source line **%s(%d) - maybe at **%s(%d) or **%s(%d)",
7337   fnam, lno, __in_fils[__vpifnam_ind], __vpilin_cnt, __in_fils[__sfnam_ind],
7338   __slin_cnt);
7339 }
7340 
7341 /*VARARGS*/
__vpi_err(int32 id_num,int32 level,char * s,...)7342 extern void __vpi_err(int32 id_num, int32 level, char *s, ...)
7343 {
7344  va_list va;
7345 
7346  /* update error counts */
7347  if (level == vpiNotice) __inform_cnt++;
7348  else if (level == vpiWarning) __pv_warn_cnt++;
7349  else if (level == vpiError) __pv_err_cnt++;
7350 
7351  /* by line number suppression means inform or warring never seen */
7352  /* command line opions ignored here since can be controlled by error */
7353  /* handler */
7354  if (level == vpiNotice || level == vpiWarning)
7355   {
7356    if (__em_suppr(id_num)) return;
7357   }
7358 
7359  init_pli_einfo(&__wrk_einfo, level, id_num);
7360  va_start(va, s);
7361  vsprintf(__wrk_vpiemsg, s, va);
7362  va_end(va);
7363  __wrk_einfo.message = __wrk_vpiemsg;
7364  __last_eip = &(__wrk_einfo);
7365  if (__have_vpi_actions) __vpi_plierror_trycall();
7366 }
7367 
7368 /*
7369  * for cbError (called from Cver error routine) fill einfo record
7370  *
7371  * in cbError callback user must call vpi chk error to get error info
7372  */
__cberror_fill_einfo(int32 esev,int32 ernum,char * emsg,char * efnam,int32 elcnt)7373 extern void __cberror_fill_einfo(int32 esev, int32 ernum, char *emsg,
7374  char *efnam, int32 elcnt)
7375 {
7376  struct t_vpi_error_info *einfop;
7377 
7378  einfop = &(__wrk_einfo);
7379  __last_eip = einfop;
7380 
7381  if (__run_state == SS_SIM) einfop->state = vpiRun;
7382  else einfop->state = vpiCompile;
7383 
7384  einfop->level = to_vpierr_level(esev);
7385  einfop->message = emsg;
7386  /* FIXME - move to initialize routine */
7387  sprintf(__wrk_vpi_product, "%s%s", __vers, __vers2);
7388 
7389  einfop->product = __wrk_vpi_product;
7390  einfop->code = __wrk_vpi_errcode;
7391  sprintf(__wrk_vpi_errcode, "%d", ernum);
7392 
7393  einfop->file = efnam;
7394  einfop->line = elcnt;
7395 }
7396 
7397 
7398 /*
7399  * convert error message severity to vpi_ error message level
7400  */
to_vpierr_level(int32 esev)7401 static int32 to_vpierr_level(int32 esev)
7402 {
7403  switch (esev) {
7404   case INFORM: return(vpiNotice);
7405   case WARN: return(vpiWarning);
7406   case ERROR: return(vpiError);
7407   case FATAL: return(vpiInternal);
7408   default:  __vpi_terr(__FILE__, __LINE__);
7409  }
7410  return(vpiInternal);
7411 }
7412 
7413 /*
7414  * initialize constant for Cver and set else values for vpi error info rec
7415  * when have more types, can pass args here
7416  */
init_pli_einfo(struct t_vpi_error_info * einfop,int32 elev,int32 ernum)7417 static void init_pli_einfo(struct t_vpi_error_info *einfop, int32 elev, int32 ernum)
7418 {
7419  einfop->state = vpiPLI;
7420  einfop->level = elev;
7421  einfop->message = __wrk_vpiemsg;
7422 
7423  /* FIXME - move to initialize routine */
7424  sprintf(__wrk_vpi_product, "%s%s", __vers, __vers2);
7425 
7426  einfop->product = __wrk_vpi_product;
7427  einfop->code = __wrk_vpi_errcode;
7428  sprintf(__wrk_vpi_errcode, "%d", ernum);
7429  einfop->file = __in_fils[__vpifnam_ind];
7430  einfop->line = __vpilin_cnt;
7431 }
7432 
7433 /*
7434  * clear wrk einfo record - can only call after user callback returns
7435  */
__clear_wrk_einfo(void)7436 extern void __clear_wrk_einfo(void)
7437 {
7438  __wrk_einfo.level = 0;
7439  __wrk_einfo.message = NULL;
7440  __wrk_einfo.file = NULL;
7441  __wrk_vpi_timedbl = 0;
7442 }
7443