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