1 /* Copyright (c) 1992-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 tf_ routines
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <ctype.h>
37
38 #include <stdarg.h>
39
40 #ifdef __DBMALLOC__
41 #include "../malloc.h"
42 #endif
43
44 #include "v.h"
45 #include "cvmacros.h"
46 #include "veriuser.h"
47 #include "cv_veriuser.h"
48 #include "acc_user.h"
49
50 /* local prototypes */
51 static void check_veriusertf_table(p_tfcell);
52 static void add_veriusertf_task(struct t_tfcell *);
53 static void add_veriusertf_func(struct t_tfcell *);
54 static int32 chk_idnam_veriusertf(char *);
55 static void pli_func_checktf(struct expr_t *);
56 static void pli_task_checktf(struct st_t *);
57 static void call_allinsts_misctfs(int32);
58 static void misc_call_misctf(struct tfrec_t *, int32);
59 static struct t_tfcell *get_tfcell(struct tfrec_t *);
60 static void allocset_vecval(struct t_tfnodeinfo *, struct xstk_t *, int32);
61 static int32 bad_nosimtf_err(char *);
62 static int32 bad_notfcontext_err(char *);
63 static int32 bad_rosync_err(char *);
64 static void init_nodeinfo(struct t_tfnodeinfo *);
65 static void init_exprinfo(struct t_tfexprinfo *);
66 static int32 get_xinfo_typ(struct expr_t *);
67 static struct xstk_t *tf_pushconvfromreal(double, int32);
68 static int32 delayed_str_putp(int32, int32, int32, char *, word64, int32);
69 static int32 chk_putdstr(char *, int32, int32 *);
70 static struct xstk_t *tftostrenval(char *, int32 *);
71 static int32 to_stval(char *);
72 static void cancel_dputp_toend(struct tfarg_t *, struct dltevlst_t *);
73 static int32 delayed_misctf_schd(word64);
74 static void bld_pvc_dces(struct expr_t *, int32);
75 static void linkon_pvc_dce(struct net_t *, int32, int32, struct gref_t *, int32);
76 static void rosync_call_misctf(i_tev_ndx);
77 static void exec_tfarg_assign(struct tfarg_t *, struct expr_t *,
78 register word32 *, register word32 *);
79 static void emit_tputd_trmsg(struct tedputp_t *, struct tfarg_t *);
80 static void reinit_1tfrec(struct tfrec_t *);
81 static void vprt_tferr_msg(char *, va_list, va_list);
82 static void vprt_tfwarn_msg(char *, va_list, va_list);
83
84 /* tf_ P1364 prototypes from veriuser.h file */
85 extern void io_mcdprintf(int32 mcd, char *format, ...);
86 extern void io_printf(char *format, ...);
87 extern char *mc_scan_plusargs(char *plusarg);
88 extern void tf_add_long(int32 *aof_lowtime1, int32 *aof_hightime1, int32 lowtime2,
89 int32 hightime2);
90 extern int32 tf_asynchoff(void);
91 extern int32 tf_asynchon(void);
92 extern int32 tf_clearalldelays(void);
93 extern int tf_compare_long(unsigned int low1, unsigned int high1,
94 unsigned int low2, unsigned int high2);
95 extern int32 tf_copypvc_flag(int32 nparam);
96 extern void tf_divide_long(int32 *aof_low1, int32 *aof_high1, int32 low2, int32 high2);
97 extern int32 tf_dofinish(void);
98 extern int32 tf_dostop(void);
99 extern int32 tf_error(char *fmt, ...);
100 extern int32 tf_evaluatep(int32 pnum);
101 extern p_tfexprinfo tf_exprinfo(int32 pnum, p_tfexprinfo pinfo);
102 extern char *tf_getcstringp(int32 nparam);
103 extern char *tf_getinstance(void);
104 extern int32 tf_getlongp(int32 *aof_highvalue, int32 pnum);
105 extern int32 tf_getlongsimtime(int32 *aof_hightime);
106 extern int32 tf_getlongtime(int32 *aof_hightime);
107 extern int32 tf_getnextlongtime(int32 *aof_lowtime, int32 *aof_hightime);
108 extern int32 tf_getp(int32 pnum);
109 extern int32 tf_getpchange(int32 nparam);
110 extern double tf_getrealp(int32 pnum);
111 extern double tf_getrealtime(void);
112 extern int32 tf_getsimtime(void);
113 extern int32 tf_gettime(void);
114 extern char *tf_getworkarea(void);
115 extern int32 tf_iasynchoff(char *inst);
116 extern int32 tf_iasynchon(char *inst);
117 extern int32 tf_iclearalldelays(char *inst);
118 extern int32 tf_icopypvc_flag(int32 nparam, char *inst);
119 extern int32 tf_ievaluatep(int32 pnum, char *inst);
120 extern p_tfexprinfo tf_iexprinfo(int32 pnum, p_tfexprinfo pinfo, char *inst);
121 extern char *tf_igetcstringp(int32 nparam, char *inst);
122 extern int32 tf_igetlongp(int32 *aof_highvalue, int32 pnum, char *inst);
123 extern int32 tf_igetlongsimtime(int32 *aof_hightime);
124 extern int32 tf_igetlongtime(int32 *aof_hightime, char *inst);
125 extern int32 tf_igetp(int32 pnum, char *inst);
126 extern int32 tf_igetpchange(int32 nparam, char *inst);
127 extern double tf_igetrealp(int32 pnum, char *inst);
128 extern double tf_igetrealtime(char *inst);
129 extern int32 tf_igettime(char *inst);
130 extern int32 tf_igettimeprecision(char *inst);
131 extern int32 tf_igettimeunit(char *inst);
132 extern char *tf_igetworkarea(char *inst);
133 extern char *tf_imipname(char *cell);
134 extern int32 tf_imovepvc_flag(int32 nparam, char *inst);
135 extern p_tfnodeinfo tf_inodeinfo(int32 pnum, p_tfnodeinfo pinfo, char *inst);
136 extern int32 tf_inump(char *inst);
137 extern int32 tf_ipropagatep(int32 pnum, char *inst);
138 extern int32 tf_iputlongp(int32 pnum, int32 lowvalue, int32 highvalue, char *inst);
139 extern int32 tf_iputp(int32 pnum, int32 value, char *inst);
140 extern int32 tf_iputrealp(int32 pnum, double value, char *inst);
141 extern int32 tf_irosynchronize(char *inst);
142 extern int32 tf_isetdelay(int32 delay, char *inst);
143 extern int32 tf_isetlongdelay(int32 lowdelay, int32 highdelay, char *inst);
144 extern int32 tf_isetrealdelay(double realdelay, char *inst);
145 extern int32 tf_isizep(int32 pnum, char *inst);
146 extern char *tf_ispname(char *cell);
147 extern int32 tf_istrdelputp(int32 nparam, int32 bitlength, int32 format_char,
148 char *value_p, int32 delay, int32 delaytype, char *inst);
149 extern char *tf_istrgetp(int32 pnum, int32 format_char, char *inst);
150 extern int32 tf_istrlongdelputp(int32 nparam, int32 bitlength, int32 format_char,
151 char *value_p, int32 lowdelay, int32 highdelay, int32 delaytype, char *inst);
152 extern int32 tf_istrrealdelputp(int32 nparam, int32 bitlength, int32 format_char,
153 char *value_p, double realdelay, int32 delaytype, char *inst);
154 extern int32 tf_isynchronize(char *inst);
155 extern int32 tf_itestpvc_flag(int32 nparam, char *inst);
156 extern int32 tf_itypep(int32 pnum, char *inst);
157 extern void tf_long_to_real(int32 int_lo, int32 int_hi, double *aof_real);
158 extern char *tf_longtime_tostr(int32 lowtime, int32 hightime);
159 extern int32 tf_message(int32 level, char *facility, char *messno,
160 char *message, ...);
161 extern char *tf_mipname(void);
162 extern int32 tf_movepvc_flag(int32 nparam);
163 extern void tf_multiply_long(int32 *aof_low1, int32 *aof_high1, int32 low2,
164 int32 high2);
165 extern p_tfnodeinfo tf_nodeinfo(int32 pnum, p_tfnodeinfo pinfo);
166 extern int32 tf_nump(void);
167 extern int32 tf_propagatep(int32 pnum);
168 extern int32 tf_putlongp(int32 pnum, int32 lowvalue, int32 highvalue);
169 extern int32 tf_putp(int32 pnum, int32 value);
170 extern int32 tf_putrealp(int32 pnum, double value);
171 extern int32 tf_read_restart(char *blockptr, int32 blocklen);
172 extern void tf_real_to_long(double real, int32 *aof_int_lo, int32 *aof_int_hi);
173 extern int32 tf_rosynchronize(void);
174 extern void tf_scale_longdelay(char *cell, int32 delay_lo, int32 delay_hi,
175 int32 *aof_delay_lo, int32 *aof_delay_hi);
176 extern void tf_scale_realdelay(char *cell, double realdelay,
177 double *aof_realdelay);
178 extern int32 tf_setdelay(int32 delay);
179 extern int32 tf_setlongdelay(int32 lowdelay, int32 highdelay);
180 extern int32 tf_setrealdelay(double realdelay);
181 extern int32 tf_setworkarea(char *workarea);
182 extern int32 tf_sizep(int32 pnum);
183 extern char *tf_spname(void);
184 extern int32 tf_strdelputp(int32 nparam, int32 bitlength, int32 format_char,
185 char *value_p, int32 delay, int32 delaytype);
186 extern char *tf_strgetp(int32 pnum, int32 format_char);
187 extern char *tf_strgettime(void);
188 extern int32 tf_strlongdelputp(int32 nparam, int32 bitlength, int32 format_char,
189 char *value_p, int32 lowdelay, int32 highdelay, int32 delaytype);
190 extern int32 tf_strrealdelputp(int32 nparam, int32 bitlength, int32 format_char,
191 char *value_p, double realdelay, int32 delaytype);
192 extern void tf_subtract_long(int32 *aof_lowtime1, int32 *aof_hightime1,
193 int32 lowtime2, int32 hightime2);
194 extern int32 tf_synchronize(void);
195 extern int32 tf_testpvc_flag(int32 nparam);
196 extern int32 tf_text(char *fmt, ...);
197 extern int32 tf_typep(int32 pnum);
198 extern void tf_unscale_longdelay(char *cell, int32 delay_lo, int32 delay_hi,
199 int32 *aof_delay_lo, int32 *aof_delay_hi);
200 extern void tf_unscale_realdelay(char *cell, double realdelay,
201 double *aof_realdelay);
202 extern int32 tf_warning(char *fmt, ...);
203 extern int32 tf_write_save(char *blockptr, int32 blocklen);
204 extern void __dce_turn_chg_store_on(struct mod_t *, struct dcevnt_t *, int32);
205 extern int32 __is_lnegative(word32 *, int32);
206
207 /* extern prototypes (maybe defined in this module) */
208 extern struct systsk_t *__alloc_systsk(void);
209 extern struct sysfunc_t *__alloc_sysfunc(void);
210 extern void __pli_func_sizetf(struct expr_t *);
211 extern void __call_all_checktfs(void);
212 extern void __call_misctfs_streset(void);
213 extern void __call_misctfs_endreset(void);
214 extern void __call_misctfs_simstart(void);
215 extern void __call_misctfs_iact(void);
216 extern void __call_misctfs_finish(void);
217 extern void __call_misctfs_scope(void);
218 extern char *__get_tfcellnam(struct tfrec_t *);
219 extern void __pli_func_calltf(struct expr_t *);
220 extern void __pli_task_calltf(struct st_t *);
221 extern char *__alloc_vval_to_cstr(word32 *, int32, int32, int32);
222 extern int32 __wide_vval_is0(register word32 *, int32);
223 extern struct xstk_t *__putdstr_to_val(char *, int32, int32, int32);
224 extern struct dltevlst_t *__spliceout_last(register struct dltevlst_t *);
225 extern struct dltevlst_t *__find_last_bdltevp(register struct dltevlst_t *, word64);
226 extern void __pli_dofinish(int32, char *);
227 extern void __pvc_call_misctf(struct dcevnt_t *);
228 extern void __exec_rosync_misctf(void);
229 extern void __sync_call_misctf(struct tev_t *);
230 extern void __setdel_call_misctf(i_tev_ndx);
231 extern void __process_putpdel_ev(i_tev_ndx);
232 extern void __reinit_tfrecs(void);
233 extern char *__mytf_malloc(int32);
234
235 extern struct tnode_t *__vtfind(char *, struct symtab_t *);
236 extern void __add_sym(char *, struct tnode_t *);
237 extern void __grow_xstk(void);
238 extern void __grow_tevtab(void);
239 extern void __chg_xstk_width(struct xstk_t *, int32);
240 extern struct xstk_t *__eval2_xpr(register struct expr_t *);
241 extern int32 __get_arrwide(struct net_t *);
242 extern int32 __unnormalize_ndx(struct net_t *, int32);
243 extern void __xline_vval_to_cstr(word32 *, int32, int32, int32, int32);
244 extern int32 __v64_to_real(double *, word64 *);
245 extern void __cnv_stk_fromreg_toreal(struct xstk_t *, int32);
246 extern void __cnv_stk_fromreal_toreg32(struct xstk_t *);
247 extern void __sizchgxs(register struct xstk_t *, int32);
248 extern char *__alloc_getasfmt(struct expr_t *, struct tfrec_t *, int32);
249 extern void __lmult(register word32 *, register word32 *, register word32 *, int32);
250 extern void __insert_event(register i_tev_ndx);
251 extern void __strenwiden_sizchg(struct xstk_t *, int32);
252 extern int32 __to_base(int32);
253 extern void __to_dhboval(int32, int32);
254 extern int32 __is_vdigit(int32, int32);
255 extern void __my_free(char *, int32);
256 extern char *__my_malloc(int32);
257 extern int32 __real_to_v64tim(word64 *, double);
258 extern char *__st_regab_tostr(char *, byte *, int32);
259 extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
260 extern void __evtr_resume_msg(void);
261 extern char *__bld_lineloc(char *, word32, int32);
262 extern char *__msg2_blditree(char *, struct itree_t *);
263 extern void __free_dceauxlst(struct dceauxlst_t *, int32);
264 extern void __cnv_ticks_tonum64(word64 *, word64, struct mod_t *);
265 extern char *__to_timstr(char *, word64 *);
266 extern void __disp_itree_path(register struct itree_t *, struct task_t *);
267 extern void __emit_stsk_endmsg(void);
268 extern void __vpi_endsim_trycall(void);
269 extern void __ldivmod2(word32 *, word32 *, word32 *, word32 *, int32);
270 extern void __my_vfprintf(FILE *, char *, va_list, va_list);
271 extern int32 __em_suppr(int32);
272 extern void __xmrpush_refgrp_to_targ(struct gref_t *);
273 extern struct dcevnt_t *__alloc_dcevnt(struct net_t *);
274 extern void __alloc_1instdce_prevval(struct dcevnt_t *);
275 extern void __init_1instdce_prevval(struct dcevnt_t *);
276 extern void __exec2_proc_assign(struct expr_t *, register word32 *, register word32 *);
277 extern void __st_perinst_val(union pck_u, int32, register word32 *, register word32 *);
278 extern void __mdr_assign_or_sched(register struct expr_t *);
279 extern void __exec_conta_assign(struct expr_t *, register word32 *, register word32 *, int32);
280 extern void __init_tfdrv(struct tfarg_t *, struct expr_t *, struct mod_t *);
281 extern int32 __trim1_0val(word32 *, int32);
282 extern void __process_pli_dynamic_libs(struct loadpli_t *);
283 extern void __dcelst_off(struct dceauxlst_t *);
284 extern double __cnvt_signed64_to_real(word32 *, int32);
285
286 extern void __tr_msg(char *, ...);
287 extern void __crit_msg(char *, ...);
288 extern void __cv_msg(char *, ...);
289 extern void __my_fprintf(FILE *, char *, ...);
290 extern void __pv_err(int32, char *, ...);
291 extern void __pv_warn(int32, char *,...);
292 extern void __sgfwarn(int32, char *, ...);
293 extern void __sgferr(int32, char *, ...);
294 extern void __dbg_msg(char *, ...);
295 extern void __sgfinform(int32, char *, ...);
296 extern void __pv_terr(int32, char *, ...);
297 extern void __arg_terr(char *, int32);
298 extern void __case_terr(char *, int32);
299 extern void __misc_terr(char *, int32);
300 extern void __my_exit(int32, int32);
301 extern void __inform(int32, char *, ...);
302
303 /* needed here since causes compiler error in veriuser.h */
304 #ifdef __STATIC_PLI__
305 extern struct t_tfcell veriusertfs[];
306 #endif
307
308 extern double __dbl_toticks_tab[];
309 extern word32 __masktab[];
310
311 /*
312 * ROUTINES TO PROCESS VERIUSERTFS D.S. BEFORE PVER STARTS
313 */
314
315 /*
316 * setup both the static veriuser tfs and/or the +loadpli1 returned tables
317 */
__setup_veriusertf_systfs(void)318 extern void __setup_veriusertf_systfs(void)
319 {
320 register int32 i;
321 register struct dynboot_t *dnbp;
322 register struct loadpli_t *ldp;
323 struct t_tfcell *veriusertf_ptr, *tfcp;
324 int32 sav_last_veriusertf, num_pli1_systfs;
325
326 sav_last_veriusertf = __last_veriusertf;
327
328 /* SJM 07/08/02 - handle all +loadpli1 option dynamic lib loading first */
329 /* this just load the dynamic libraries and finds boot strap routines */
330 if (__pli1_dynlib_hd != NULL) __process_pli_dynamic_libs(__pli1_dynlib_hd);
331
332 /* always add P1364 old built in table - empty unless old static cverobj.o */
333 #ifdef __STATIC_PLI__
334 check_veriusertf_table(veriusertfs);
335 #else
336 for (ldp = __pli1_dynlib_hd; ldp != NULL; ldp = ldp->load_plinxt)
337 {
338 for (dnbp = ldp->dynblst; dnbp != NULL; dnbp = dnbp->dynbootnxt)
339 {
340 /* bootstrap routine can be nil */
341 if (dnbp->dynu.tf_rout == NULL) continue;
342
343 /* vpi boostrap routines are assume to return void - if not ret ignored */
344 /* notice user must insure if pli1 bootstrap routine returns val, that */
345 /* it is pointer to p tfcell table */
346 veriusertf_ptr = (struct t_tfcell *) (dnbp->dynu.tf_rout)();
347 dnbp->ret_veriusertf = veriusertf_ptr;
348 if (dnbp->ret_veriusertf != NULL)
349 {
350 check_veriusertf_table(dnbp->ret_veriusertf);
351 }
352 }
353 #endif
354 }
355
356 num_pli1_systfs = __last_veriusertf - sav_last_veriusertf;
357 if (num_pli1_systfs != 0 && __verbose)
358 {
359 __cv_msg(" %d veriusertfs PLI 1.0 user tasks and functions defined.\n",
360 num_pli1_systfs);
361 }
362
363 /* SJM 07/16/02 - need internal shadow veriuser tfs table that is copy */
364 /* of legacy user filled veriuser tfs for old static cverobj.o pli1 scheme */
365 /* and contains copy of all returned tables for new +load_pli1 mechanism */
366 __shadow_veriusertfs = (struct t_tfcell *)
367 __my_malloc((num_pli1_systfs + 1)*sizeof(struct t_tfcell));
368 #ifdef __STATIC_PLI__
369 for (i = 0;; i++)
370 {
371 tfcp = &(veriusertfs[i]);
372 __shadow_veriusertfs[i] = *tfcp;
373 /* copy ending fence before break; */
374 if (tfcp->type == 0) break;
375 }
376 #else
377 for (i = 0, ldp = __pli1_dynlib_hd; ldp != NULL; ldp = ldp->load_plinxt)
378 {
379
380 for (dnbp = ldp->dynblst; dnbp != NULL; dnbp = dnbp->dynbootnxt)
381 {
382 int32 j;
383
384 /* bootstrap routine can be nil */
385 if (dnbp->ret_veriusertf == NULL) continue;
386
387 for (j = 0;; j++)
388 {
389 tfcp = &(dnbp->ret_veriusertf[j]);
390 if (tfcp->type == 0) break;
391 __shadow_veriusertfs[i++] = *tfcp;
392 }
393 }
394 }
395 __shadow_veriusertfs[i].type = 0;
396 #endif
397 }
398
399 /*
400 * during initialization routine to process and check tf_cell table entries
401 *
402 * put in normal system task or function table (possibly replacing built-in)
403 * some execution mechanism same
404 */
check_veriusertf_table(struct t_tfcell * boot_veriusertf)405 static void check_veriusertf_table(struct t_tfcell *boot_veriusertf)
406 {
407 register int32 i;
408 struct t_tfcell *tfcp;
409
410 /* notice, must be at least one entry or will crash */
411 for (i = 0;; i++)
412 {
413 tfcp = &(boot_veriusertf[i]);
414 switch (tfcp->type) {
415 case 0:
416 /* need to start processing vpi systfs by move last systf one past end */
417 /* each table ends by updating last */
418 __last_systf = __last_veriusertf;
419 return;
420 case USERTASK: case USERFUNCTION: case USERREALFUNCTION:
421 if (!chk_idnam_veriusertf(tfcp->tfname)) break;
422 if (++__last_veriusertf - BASE_VERIUSERTFS >= MAXVERIUSERTFS)
423 __pv_terr(320,
424 "too many tasks and functions in veriusertfs (%d) and +loadpli1 bootstrap returned ptfcell tables",
425 MAXVERIUSERTFS);
426 if (tfcp->calltf == NULL)
427 {
428 __pv_warn(578,
429 "PLI1 veriusertfs user function or task %s no Verilog execution routine",
430 tfcp->tfname);
431 }
432 if (tfcp->type == USERTASK) add_veriusertf_task(tfcp);
433 else add_veriusertf_func(tfcp);
434 break;
435 default: __case_terr(__FILE__, __LINE__);
436 }
437 }
438 }
439
440 /*
441 * add a veriuser table pli system task
442 */
add_veriusertf_task(struct t_tfcell * tfcp)443 static void add_veriusertf_task(struct t_tfcell *tfcp)
444 {
445 struct systsk_t *stbp;
446 struct tnode_t *tnp;
447 struct sy_t *syp;
448
449 if (tfcp->sizetf != NULL)
450 {
451 __inform(425,
452 "PLI1 veriusertfs task %s - sizetf function ignored but should not be in table",
453 tfcp->tfname);
454 tfcp->sizetf = NULL;
455 }
456 /* allocate a systsk_t entry - needed because splicing pli on and */
457 /* need to be able to compile version without */
458 stbp = __alloc_systsk();
459 stbp->stsknam = tfcp->tfname;
460 stbp->stsknum = __last_veriusertf;
461 tnp = __vtfind(tfcp->tfname, __syssyms);
462 if (!__sym_is_new)
463 {
464 syp = tnp->ndp;
465 __inform(459,
466 "PLI1 veriusertfs task %s replaces predefined system task or function with same name",
467 syp->synam);
468 }
469 else
470 {
471 __add_sym(tfcp->tfname, tnp);
472 (__syssyms->numsyms)++;
473 syp = tnp->ndp;
474 }
475 syp->sytyp = SYM_STSK;
476 syp->sydecl = TRUE;
477 syp->el.esytbp = stbp;
478 }
479
480 /*
481 * add a veriuser table pli system function (normal or real)
482 */
add_veriusertf_func(struct t_tfcell * tfcp)483 static void add_veriusertf_func(struct t_tfcell *tfcp)
484 {
485 struct tnode_t *tnp;
486 struct sy_t *syp;
487 struct sysfunc_t *sfbp;
488
489 /* function tfcell must have sizetf or cannot execute */
490 /* for real function know size */
491 if (tfcp->type == USERFUNCTION && tfcp->sizetf == NULL)
492 {
493 __pv_warn(578,
494 "PLI1 veriusertfs function %s sizetf function missing - assuming size 1",
495 tfcp->tfname);
496 }
497 else if (tfcp->type == userrealfunction && tfcp->sizetf != NULL)
498 {
499 __inform(425,
500 "PLI1 veriusertfs userrealfunction %s - sizetf function ignored but should not be in table",
501 tfcp->tfname);
502 tfcp->sizetf = NULL;
503 }
504
505 /* allocate a sysfunc_t entry - needed because splicing pli on and */
506 /* need to be able to compile version without */
507 sfbp = __alloc_sysfunc();
508 sfbp->syfnum = __last_veriusertf;
509 sfbp->tftyp = SYSF_TF;
510 sfbp->syfnam = tfcp->tfname;
511 tnp = __vtfind(tfcp->tfname, __syssyms);
512 if (!__sym_is_new)
513 {
514 syp = tnp->ndp;
515 __inform(459,
516 "PLI1 veriusertfs function %s replaces predefined system task or function with same name",
517 syp->synam);
518 }
519 else
520 {
521 __add_sym(tfcp->tfname, tnp);
522 (__syssyms->numsyms)++;
523 syp = tnp->ndp;
524 }
525 syp->sytyp = SYM_SF;
526 syp->sydecl = TRUE;
527 syp->el.esyftbp = sfbp;
528 }
529
530 /*
531 * check for legal user tf task or function name
532 */
chk_idnam_veriusertf(char * tfnam)533 static int32 chk_idnam_veriusertf(char *tfnam)
534 {
535 register char *chp;
536 int32 len;
537
538 chp = tfnam;
539 if (*chp++ != '$')
540 {
541 __pv_err(1302,
542 "PLI1 - veriusertfs task or function %s must begin with '$'", tfnam);
543 bad_end:
544 return(FALSE);
545 }
546 for (len = 1; *chp != '\0'; chp++)
547 {
548 /* notice no escaped names here */
549 if (!isalnum(*chp) && *chp != '_' && *chp != '$')
550 {
551 __pv_err(1303,
552 "PLI1 veriusertfs task or function %s contains illegal char %c",
553 tfnam, *chp);
554 goto bad_end;
555 }
556 if (++len >= IDLEN)
557 {
558 /* notice cannot truncate since in user memory */
559 __pv_err(1304,
560 "PLI1 veriusertfs task or function %s name too long (%d)",
561 tfnam, IDLEN);
562 goto bad_end;
563 }
564 }
565 return(TRUE);
566 }
567
568 /*
569 * allocate and initialize a system task struct for pli task
570 * built-in system tasks are predefined in table
571 */
__alloc_systsk(void)572 extern struct systsk_t *__alloc_systsk(void)
573 {
574 struct systsk_t *stbp;
575
576 stbp = (struct systsk_t *) __my_malloc(sizeof(struct systsk_t));
577 stbp->stsknam = NULL;
578 stbp->stsknum = 0;
579 return(stbp);
580 }
581
582 /*
583 * allocate and initialize a system function struct for pli function
584 * built-in system functions are predefined in table
585 */
__alloc_sysfunc(void)586 extern struct sysfunc_t *__alloc_sysfunc(void)
587 {
588 struct sysfunc_t *sfbp;
589
590 sfbp = (struct sysfunc_t *) __my_malloc(sizeof(struct sysfunc_t));
591 sfbp->syfnam = NULL;
592 /* these all all unused */
593 sfbp->syfnum = 0;
594 sfbp->retntyp = 0;
595 sfbp->retsigned = FALSE;
596 sfbp->retwid = 0;
597 sfbp->tftyp = SYSF_UNKNOWN;
598 return(sfbp);
599 }
600
601 /*
602 * WRAPPERS THAT CALL THE USER'S TF FUNCTIONS FROM VERIUSERTFS TABLE
603 */
604
605 /*
606 * FUNCTION SIZETF ROUTINES CALL DURING FIXUP
607 */
608
609 /*
610 * call pli system function sizetf routine
611 * for function sizetf must exist or will not get here
612 * for userrealfunction just set to expected width (never seen by user)
613 *
614 * here if user calls routine that needs variable just crashes
615 */
__pli_func_sizetf(struct expr_t * fcallx)616 extern void __pli_func_sizetf(struct expr_t *fcallx)
617 {
618 int32 siz, nbytes;
619 word32 *wp;
620 double d1;
621 struct sysfunc_t *sfbp;
622 struct t_tfcell *tfcp;
623 struct tfinst_t tfiwrk;
624 int32 (*sizetf_func)();
625
626 sfbp = fcallx->lu.x->lu.sy->el.esyftbp;
627 tfcp = &(__shadow_veriusertfs[sfbp->syfnum - BASE_VERIUSERTFS]);
628 __tfrec = fcallx->lu.x->szu.xfrec;
629
630 /* for real function, set size and return no sizetf for real func. */
631 if (tfcp->type == userrealfunction)
632 {
633 __tfrec->fretsiz = REALBITS;
634 __tfrec->fretreal = TRUE;
635 fcallx->is_real = TRUE;
636 fcallx->has_sign = TRUE;
637 /* since not checked need to set width for real */
638 fcallx->szu.xclen = REALBITS;
639
640 /* set the 0th expression for tf userrealfunction */
641 /* points to value not expr. that is initialzed to 0.0 */
642 nbytes = 2*wlen_(__tfrec->fretsiz)*WRDBYTES;
643 wp = __tfrec->tfargs[0].arg.awp = (word32 *) __my_malloc(nbytes);
644 /* initialize to 0.0 since no internals for pli func and double */
645 d1 = 0.0;
646 memcpy(wp, &d1, nbytes);
647 return;
648 }
649 sizetf_func = tfcp->sizetf;
650
651 if (sizetf_func == NULL)
652 {
653 siz = 1;
654 goto have_size;
655 }
656
657 /* run in first inst. itree loc. - know moditps built by here */
658 __push_itstk(__inst_mod->moditps[0]);
659 /* notice assignment of addr. to static works since niled in this rout. */
660 __tfinst = &tfiwrk;
661 __tfinst->callx = fcallx;
662 __tfinst->tfstp = NULL;
663 __tfinst->tfitp = __inst_ptr;
664
665 /* FIXME ??? - not 64 bit clean */
666 siz = (*sizetf_func)((int32) tfcp->data, REASON_SIZETF);
667 __pop_itstk();
668 if (siz < 1 || siz > MAXNUMBITS)
669 {
670 __sgferr(1277,
671 "tf_ function %s sizetf routine returned illegal size value %d",
672 tfcp->tfname, siz);
673 __tfinst = NULL;
674 __tfrec = NULL;
675 return;
676 }
677
678 have_size:
679 __tfrec->fretsiz = siz;
680 /* SJM 04/07/03 - this is needed by compiler so much be also set */
681 /* worked for vpi becausxe no tf rec alternative size location */
682 sfbp->retwid = siz;
683
684 /* set the 0th expression for tf function */
685 /* points to value not expr. that is initialized to x */
686 nbytes = 2*wlen_(__tfrec->fretsiz)*WRDBYTES;
687 wp = __tfrec->tfargs[0].arg.awp = (word32 *) __my_malloc(nbytes);
688 /* initialize to x since no internals for pli functions */
689 one_allbits_(wp, 2*__tfrec->fretsiz);
690 fcallx->szu.xclen = __tfrec->fretsiz;
691 __tfinst = NULL;
692 __tfrec = NULL;
693 }
694
695 /*
696 * CHECKTF ROUTINES CALLED NEAR END OF PREP
697 */
698
699 /*
700 * go through list of all task and function tf_ calls
701 */
__call_all_checktfs(void)702 extern void __call_all_checktfs(void)
703 {
704 register struct tfrec_t *tfrp;
705
706 for (tfrp = __tfrec_hdr; tfrp != NULL; tfrp = tfrp->tfrnxt)
707 {
708 if (tfrp->tf_func) pli_func_checktf(tfrp->tfu.callx);
709 else pli_task_checktf(tfrp->tfu.tfstp);
710 }
711 }
712
713 /*
714 * call pli system function checktf
715 *
716 * must be called after call tf record built
717 * this needs to be left in .a file since locates problem
718 * LOOKATME if user tries to make sim tf_ calls will crash
719 */
pli_func_checktf(struct expr_t * fcallx)720 static void pli_func_checktf(struct expr_t *fcallx)
721 {
722 struct t_tfcell *tfcp;
723 struct sysfunc_t *sfbp;
724 struct tfinst_t tfiwrk;
725 int32 (*checktf_func)();
726
727 sfbp = fcallx->lu.x->lu.sy->el.esyftbp;
728 tfcp = &(__shadow_veriusertfs[sfbp->syfnum - BASE_VERIUSERTFS]);
729
730 checktf_func = tfcp->checktf;
731 if (checktf_func == NULL) return;
732
733 __tfrec = fcallx->lu.x->szu.xfrec;
734 /* run in first inst. itree loc. - know moditps built by here */
735 /* if interactive just run in current itree loc. */
736 /* DBG remove --- */
737 if (__tfrec->tf_inmdp == NULL) __misc_terr(__FILE__, __LINE__);
738 /* ---*/
739 __push_itstk(__tfrec->tf_inmdp->moditps[0]);
740
741 /* notice assignment of addr. to static works since niled in this rout. */
742 __tfinst = &tfiwrk;
743 __tfinst->callx = fcallx;
744 __tfinst->tfstp = NULL;
745 __tfinst->tfitp = __inst_ptr;
746
747 /* FIXME ??? - not 64 bit clean */
748 (*checktf_func)((int32) tfcp->data, REASON_CHECKTF);
749
750 __tfinst = NULL;
751 __tfrec = NULL;
752 __pop_itstk();
753 }
754
755 /*
756 * call checktf for task
757 * runs in first instance tree location
758 * this routine must stay in .a lib
759 */
pli_task_checktf(struct st_t * stp)760 static void pli_task_checktf(struct st_t *stp)
761 {
762 int32 sav_fnam_ind, sav_slin_cnt;
763 struct tskcall_t *tkcp;
764 struct t_tfcell *tfcp;
765 struct systsk_t *stbp;
766 struct tfinst_t tfiwrk;
767 int32 (*checktf_func)();
768
769 /* statement is task call not task definition */
770 tkcp = &(stp->st.stkc);
771 stbp = tkcp->tsksyx->lu.sy->el.esytbp;
772 tfcp = &(__shadow_veriusertfs[stbp->stsknum - BASE_VERIUSERTFS]);
773
774 checktf_func = tfcp->checktf;
775 if (checktf_func == NULL) return;
776
777 __tfrec = tkcp->tkcaux.trec;
778 sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt;
779 __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
780 __vpifnam_ind = __sfnam_ind;
781 __vpilin_cnt = __slin_cnt;
782
783 /* if interactive just run in current itree loc. */
784 /* DBG remove --- */
785 if (__tfrec->tf_inmdp == NULL) __misc_terr(__FILE__, __LINE__);
786 /* ---*/
787 __push_itstk(__tfrec->tf_inmdp->moditps[0]);
788 /* notice assignment of addr. to static works since niled in this rout. */
789 __tfinst = &tfiwrk;
790 __tfinst->callx = NULL;
791 __tfinst->tfstp = stp;
792 __tfinst->tfitp = __inst_ptr;
793
794 /* FIXME ??? - not 64 bit clean */
795 (*checktf_func)((int32) tfcp->data, REASON_CHECKTF);
796
797 __pop_itstk();
798 __tfrec = NULL;
799 __tfinst = NULL;
800 __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
801 __vpifnam_ind = 0;
802 __vpilin_cnt = 0;
803 }
804
805 /*
806 * ROUTINES FOR CALLING ALL MISCTF ROUTINES AT CHANGES
807 */
808
809 /*
810 * calling misctfs need to be here so can use REASON constants
811 */
__call_misctfs_streset(void)812 extern void __call_misctfs_streset(void)
813 {
814 call_allinsts_misctfs(REASON_RESET);
815 }
816
__call_misctfs_endreset(void)817 extern void __call_misctfs_endreset(void)
818 {
819 call_allinsts_misctfs(REASON_ENDOFRESET);
820 }
821
__call_misctfs_simstart(void)822 extern void __call_misctfs_simstart(void)
823 {
824 call_allinsts_misctfs(REASON_ENDOFCOMPILE);
825 }
826
__call_misctfs_iact(void)827 extern void __call_misctfs_iact(void)
828 {
829 call_allinsts_misctfs(REASON_INTERACTIVE);
830 }
831
__call_misctfs_finish(void)832 extern void __call_misctfs_finish(void)
833 {
834 call_allinsts_misctfs(REASON_FINISH);
835 }
836
__call_misctfs_scope(void)837 extern void __call_misctfs_scope(void)
838 {
839 call_allinsts_misctfs(REASON_SCOPE);
840 }
841
842 /*
843 * go through list of all task and function tf_ calls
844 * and call misctf for every instance of every call
845 */
call_allinsts_misctfs(int32 reason)846 static void call_allinsts_misctfs(int32 reason)
847 {
848 register struct tfrec_t *tfrp;
849
850 for (tfrp = __tfrec_hdr; tfrp != NULL; tfrp = tfrp->tfrnxt)
851 misc_call_misctf(tfrp, reason);
852 }
853
854 /*
855 * call the misctf routine for misceallaneous reason
856 */
misc_call_misctf(struct tfrec_t * tfrp,int32 reason)857 static void misc_call_misctf(struct tfrec_t *tfrp, int32 reason)
858 {
859 register int32 ii;
860 int32 sav_fnam_ind, sav_slin_cnt;
861 struct t_tfcell *tfcp;
862 struct tfinst_t tfiwrk;
863 struct mod_t *mdp;
864 int32 (*misctf)(int32, int32, int32);
865
866 __tfrec = tfrp;
867 /* if no misc. tf routine just turn off, nothing to do */
868 tfcp = get_tfcell(__tfrec);
869 if ((misctf = tfcp->misctf) == NULL) return;
870
871 sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt;
872 __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
873 __vpifnam_ind = __sfnam_ind;
874 __vpilin_cnt = __slin_cnt;
875
876 /* notice assignment of addr. to static works since niled in this rout. */
877 __tfinst = &tfiwrk;
878 __tfinst->callx = NULL;
879 __tfinst->tfstp = NULL;
880 if (__tfrec->tf_func) __tfinst->callx = __tfrec->tfu.callx;
881 else __tfinst->tfstp = __tfrec->tfu.tfstp;
882 mdp = __tfrec->tf_inmdp;
883
884 /* DBG remove --- */
885 if (mdp == NULL) __misc_terr(__FILE__, __LINE__);
886 /* ---*/
887 for (ii = 0; ii < mdp->flatinum; ii++)
888 {
889 __push_itstk(mdp->moditps[ii]);
890 __tfinst->tfitp = __inst_ptr;
891
892 /* SJM 06/13/1999 - misctf always requires 3rd argument although */
893 /* ignored except for syncon callbacks ?? */
894 /* FIXME ??? - not 64 bit clean */
895 (*misctf)((int32) tfcp->data, reason, 0);
896 __pop_itstk();
897 }
898 __tfrec = NULL;
899 __tfinst = NULL;
900 __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
901 __vpifnam_ind = 0;
902 __vpilin_cnt = 0;
903 }
904
905 /*
906 * get a tfcell name
907 */
__get_tfcellnam(struct tfrec_t * tfrp)908 extern char *__get_tfcellnam(struct tfrec_t *tfrp)
909 {
910 struct t_tfcell *tfcp;
911
912 tfcp = get_tfcell(tfrp);
913 return(tfcp->tfname);
914 }
915
916 /*
917 * get a tfcell record from a tfrec
918 */
get_tfcell(struct tfrec_t * tfrp)919 static struct t_tfcell *get_tfcell(struct tfrec_t *tfrp)
920 {
921 struct t_tfcell *tfcp;
922 struct systsk_t *stbp;
923 struct sysfunc_t *sfbp;
924
925 if (tfrp->tf_func)
926 {
927 sfbp = tfrp->tfu.callx->lu.x->lu.sy->el.esyftbp;
928 tfcp = &(__shadow_veriusertfs[sfbp->syfnum - BASE_VERIUSERTFS]);
929 return(tfcp);
930 }
931 stbp = tfrp->tfu.tfstp->st.stkc.tsksyx->lu.sy->el.esytbp;
932 tfcp = &(__shadow_veriusertfs[stbp->stsknum - BASE_VERIUSERTFS]);
933 return(tfcp);
934 }
935
936 /*
937 * WRAPPERS THAT CALL THE USER'S TF TASKS FROM VERIUSERTFS TABLE
938 */
939
940 /*
941 * execute the pli system function calltf routine
942 * this pushes return value on top of expr. stack but does not return it
943 * this uses the instance tree loc. called from
944 */
__pli_func_calltf(struct expr_t * fcallx)945 extern void __pli_func_calltf(struct expr_t *fcallx)
946 {
947 int32 nbytes, sav_fnam_ind, sav_slin_cnt;
948 struct t_tfcell *tfcp;
949 struct sysfunc_t *sfbp;
950 struct xstk_t *xsp;
951 struct tfinst_t tfiwrk;
952 int32 (*calltf_func)();
953
954 sfbp = fcallx->lu.x->lu.sy->el.esyftbp;
955 tfcp = &(__shadow_veriusertfs[sfbp->syfnum - BASE_VERIUSERTFS]);
956 __tfrec = fcallx->lu.x->szu.xfrec;
957
958 if ((calltf_func = tfcp->calltf) == NULL)
959 {
960 push_xstk_(xsp, __tfrec->fretsiz);
961 one_allbits_(xsp->ap, xsp->xslen);
962 one_allbits_(xsp->bp, xsp->xslen);
963 __tfrec = NULL;
964 return;
965 }
966
967 sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt;
968 __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
969 __vpifnam_ind = __sfnam_ind;
970 __vpilin_cnt = __slin_cnt;
971
972 /* set up environment that is current implied tf instance */
973 /* notice assignment of addr. to static works since niled in this rout. */
974 __tfinst = &tfiwrk;
975 __tfinst->callx = fcallx;
976 __tfinst->tfstp = NULL;
977 __tfinst->tfitp = __inst_ptr;
978
979 /* FIXME ??? - not 64 bit clean */
980 (*calltf_func)((int32) tfcp->data, REASON_CALLTF);
981
982 /* must store return value from caller's itree loc. */
983 nbytes = 2*wlen_(__tfrec->fretsiz)*WRDBYTES;
984 push_xstk_(xsp, __tfrec->fretsiz);
985 /* this requires contiguous a and b stack values */
986 memcpy(xsp->ap, __tfrec->tfargs[0].arg.awp, nbytes);
987
988 __sfnam_ind = sav_fnam_ind;
989 __slin_cnt = sav_slin_cnt;
990 __vpifnam_ind = 0;
991 __vpilin_cnt = 0;
992 __tfrec = NULL;
993 __tfinst = NULL;
994 }
995
996 /*
997 * call the pli tf system task calltf routine
998 */
__pli_task_calltf(struct st_t * stp)999 extern void __pli_task_calltf(struct st_t *stp)
1000 {
1001 int32 sav_fnam_ind, sav_slin_cnt;
1002 struct tskcall_t *tkcp;
1003 struct t_tfcell *tfcp;
1004 struct systsk_t *stbp;
1005 struct tfinst_t tfiwrk;
1006 int32 (*calltf_tsk)();
1007
1008 tkcp = &(stp->st.stkc);
1009 stbp = tkcp->tsksyx->lu.sy->el.esytbp;
1010 tfcp = &(__shadow_veriusertfs[stbp->stsknum - BASE_VERIUSERTFS]);
1011
1012 if ((calltf_tsk = tfcp->calltf) == NULL) return;
1013
1014 __tfrec = tkcp->tkcaux.trec;
1015 sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt;
1016 __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
1017 __vpifnam_ind = __sfnam_ind;
1018 __vpilin_cnt = __slin_cnt;
1019
1020 /* set up environment that is current implied tf instance */
1021 /* notice assignment of addr. to static works since niled in this rout. */
1022 __tfinst = &tfiwrk;
1023 __tfinst->callx = NULL;
1024 __tfinst->tfstp = stp;
1025 __tfinst->tfitp = __inst_ptr;
1026
1027 /* FIXME ??? - not 64 bit clean */
1028 (*calltf_tsk)((int32) tfcp->data, REASON_CALLTF);
1029
1030 __tfrec = NULL;
1031 __tfinst = NULL;
1032 __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
1033 __vpifnam_ind = 0;
1034 __vpilin_cnt = 0;
1035 }
1036
1037 /*
1038 * USER CALLABLE TF_ ROUTINES GROUPED BY TYPE - UTILITY TOWARD BOTTOM
1039 */
1040
1041 /*
1042 * EXPRESSION AND VALUE INFORMATION ROUTINES
1043 */
1044
1045 /*
1046 * get number of parameters (user pli tasks are variable arg. no.) that
1047 * if checked done by user routine
1048 * LOOKATME - does this really need to be other inst?
1049 */
tf_inump(char * inst)1050 extern int32 tf_inump(char *inst)
1051 {
1052 struct tfinst_t *tfip;
1053 struct tfrec_t *tfrp;
1054
1055 tfip = (struct tfinst_t *) inst;
1056 if (tfip->callx != NULL) tfrp = tfip->callx->lu.x->szu.xfrec;
1057 else tfrp = tfip->tfstp->st.stkc.tkcaux.trec;
1058 return(tfrp->tfanump1 - 1);
1059 }
1060
1061 /*
1062 * number of params from saved system task call
1063 */
tf_nump(void)1064 extern int32 tf_nump(void)
1065 {
1066 if (__tfrec == NULL) return(bad_notfcontext_err("tf_nump"));
1067 return(__tfrec->tfanump1 - 1);
1068 }
1069
1070 /*
1071 * get parameter type
1072 */
tf_itypep(int32 pnum,char * inst)1073 extern int32 tf_itypep(int32 pnum, char *inst)
1074 {
1075 int32 rv;
1076 struct tfinst_t *tfip;
1077 struct tfrec_t *sav_tfrp;
1078
1079 sav_tfrp = __tfrec;
1080 tfip = (struct tfinst_t *) inst;
1081 if (tfip->callx != NULL) __tfrec = tfip->callx->lu.x->szu.xfrec;
1082 else __tfrec = tfip->tfstp->st.stkc.tkcaux.trec;
1083
1084 rv = tf_typep(pnum);
1085 __tfrec = sav_tfrp;
1086 return(rv);
1087 }
1088
tf_typep(int32 pnum)1089 extern int32 tf_typep(int32 pnum)
1090 {
1091 struct expr_t *xp;
1092
1093 if (__tfrec == NULL) return(bad_notfcontext_err("tf_typep"));
1094 if (pnum < 0 || pnum >= __tfrec->tfanump1) return(TF_NULLPARAM);
1095 if (pnum == 0)
1096 {
1097 if (!__tfrec->tf_func) return(TF_NULLPARAM);
1098 if (__tfrec->fretreal) return(TF_READWRITEREAL);
1099 return(TF_READWRITE);
1100 }
1101 xp = __tfrec->tfargs[pnum].arg.axp;
1102
1103 if (xp->tf_isrw)
1104 {
1105 if (xp->is_real) return(TF_READWRITEREAL);
1106 return(TF_READWRITE);
1107 }
1108 if (xp->optyp == NUMBER && xp->is_string) return(TF_STRING);
1109 if (xp->optyp == OPEMPTY) return(TF_NULLPARAM);
1110 if (xp->is_real) return(TF_READONLYREAL);
1111 return(TF_READONLY);
1112 }
1113
1114 /*
1115 * return bit length of parameter
1116 * return size of parameter in bits - 0 for real
1117 */
tf_isizep(int32 pnum,char * inst)1118 extern int32 tf_isizep(int32 pnum, char *inst)
1119 {
1120 int32 rv;
1121 struct tfinst_t *tfip;
1122 struct tfrec_t *sav_tfrp;
1123
1124 sav_tfrp = __tfrec;
1125 tfip = (struct tfinst_t *) inst;
1126 if (tfip->callx != NULL) __tfrec = tfip->callx->lu.x->szu.xfrec;
1127 else __tfrec = tfip->tfstp->st.stkc.tkcaux.trec;
1128 rv = tf_sizep(pnum);
1129
1130 __tfrec = sav_tfrp;
1131 return(rv);
1132 }
1133
tf_sizep(int32 pnum)1134 extern int32 tf_sizep(int32 pnum)
1135 {
1136 struct expr_t *xp;
1137
1138 if (__tfrec == NULL) return(bad_notfcontext_err("tf_sizep"));
1139 if (pnum < 0 || pnum >= __tfrec->tfanump1) return(TF_NULLPARAM);
1140 if (pnum == 0)
1141 {
1142 if (__tfrec->fretreal) return(TF_NULLPARAM);
1143 return(__tfrec->fretsiz);
1144 }
1145 xp = __tfrec->tfargs[pnum].arg.axp;
1146 if (xp->is_real) return(TF_NULLPARAM);
1147 return(xp->szu.xclen);
1148 }
1149
1150 /*
1151 * EXPRINFO AND NODINFO ROUTINES
1152 */
1153
1154 /* macro to saves and sets inst form environment */
1155 /* need to be in normal code not part of block or if */
1156 #define set_tfinst_(inst, stfip, stfrp) \
1157 stfip = __tfinst; \
1158 stfrp = __tfrec; \
1159 __tfinst = (struct tfinst_t *) inst; \
1160 if (__tfinst->callx != NULL) __tfrec = __tfinst->callx->lu.x->szu.xfrec; \
1161 else __tfrec = __tfinst->tfstp->st.stkc.tkcaux.trec;
1162
1163
1164
1165 /*
1166 * return node info struct from nparam for read-write (lhs) expr. only
1167 * node info if for underlying object in case select or index
1168 * cannot access pli func. return values here (no nodes)
1169 *
1170 * LOOKATME - need to find out 1 bit representation (always stren)
1171 * for now strength illegal since standard document method for storing
1172 * strength impossible (provided by 2.0 so leave)
1173 */
tf_inodeinfo(int32 pnum,p_tfnodeinfo pinfo,char * inst)1174 extern p_tfnodeinfo tf_inodeinfo(int32 pnum, p_tfnodeinfo pinfo, char *inst)
1175 {
1176 struct t_tfnodeinfo *pinfo2;
1177 struct tfinst_t *sav_tfip;
1178 struct tfrec_t *sav_tfrp;
1179
1180 set_tfinst_(inst, sav_tfip, sav_tfrp);
1181 __push_itstk(__tfinst->tfitp);
1182 pinfo2 = tf_nodeinfo(pnum, pinfo);
1183 __pop_itstk();
1184 __tfinst = sav_tfip;
1185 __tfrec = sav_tfrp;
1186 return(pinfo2);
1187 }
1188
tf_nodeinfo(int32 pnum,p_tfnodeinfo pinfo)1189 extern p_tfnodeinfo tf_nodeinfo(int32 pnum, p_tfnodeinfo pinfo)
1190 {
1191 register struct xstk_t *xsp;
1192 register struct net_t *np;
1193 int32 wlen, mwid, r1, r2, biti, bitj;
1194 double d1;
1195 struct tfarg_t *tfap;
1196 struct expr_t *xp;
1197
1198 if (__tfrec == NULL) { bad_notfcontext_err("tf_nodeinfo"); return(NULL); }
1199 if (pnum < 1 || pnum >= __tfrec->tfanump1) return(NULL);
1200 tfap = &(__tfrec->tfargs[pnum]);
1201 xp = tfap->arg.axp;
1202 init_nodeinfo(pinfo);
1203 /* if not rw (concat not rw), return null */
1204 if (!xp->tf_isrw) return(NULL);
1205
1206 /* cannot handle strength since as documented no way to store value */
1207 np = tfap->anp;
1208 if (np->n_stren)
1209 __sgfinform(489,
1210 "tf_nodeinfo of strength wire %s node_value set to value part only",
1211 np->nsym->synam);
1212
1213 /* SJM 10/30/99 - now using tf exprinfo for propagatep following new LRM */
1214
1215 /* notice node_lhs_element and node_rhs_element unused */
1216 /* set the symbol name field */
1217 /* not my malloc can only call malloc (no other alloc scheme possible) */
1218 pinfo->node_symbol = __mytf_malloc(strlen(np->nsym->synam) + 1);
1219 strcpy(pinfo->node_symbol, np->nsym->synam);
1220
1221 xsp = __eval_xpr(xp);
1222 /* real is special case - no range */
1223 /* real array select work handled in xpr eval */
1224 if (np->ntyp == N_REAL)
1225 {
1226 pinfo->node_type = TF_REAL_NODE;
1227 /* eval of expr. always gets underlying value and handles xmr */
1228 /* notice for xmr, this will acess from right place - cannot push grp */
1229 memcpy(&d1, xsp->ap, sizeof(double));
1230
1231 pinfo->node_value.real_val_p =
1232 (double *) __mytf_malloc(sizeof(double));
1233 *(pinfo->node_value.real_val_p) = d1;
1234 __pop_xstk();
1235 return(pinfo);
1236 }
1237
1238 /* set the vector size (component element for array) */
1239 pinfo->node_sign = np->n_signed;
1240
1241 /* select of array (not entire) array special case */
1242 if (np->n_isarr)
1243 {
1244 pinfo->node_vec_size = np->nwid;
1245 pinfo->node_type = TF_MEMORY_NODE;
1246 mwid = __get_arrwide(np);
1247 pinfo->node_mem_size = mwid;
1248 /* DBG remove */
1249 if (np->nrngrep != NX_ARR) __misc_terr(__FILE__, __LINE__);
1250 /* --- */
1251 /* get range not size */
1252 pinfo->node_ms_index = np->nu.rngarr->ai1;
1253 pinfo->node_ls_index = np->nu.rngarr->ai2;
1254 /* each group is both 32 bits of a part and 32 bits of b */
1255 /* notice memory expression are always entire variable */
1256 wlen = wlen_(np->nwid);
1257 pinfo->node_ngroups = wlen;
1258 allocset_vecval(pinfo, xsp, wlen);
1259 __pop_xstk();
1260 return(pinfo);
1261 }
1262
1263 pinfo->node_vec_size = xp->szu.xclen;
1264 /* set the ranges of the node - always just var not mem decl. range */
1265 if (np->nrngrep == NX_WIR)
1266 { r1 = np->nu.rngwir->ni1; r2 = np->nu.rngwir->ni2; }
1267 else if (np->nrngrep == NX_DWIR)
1268 { r1 = np->nu.rngdwir->ni1; r2 = np->nu.rngdwir->ni2; }
1269 else r1 = r2 = -1;
1270
1271 /* assume entire range */
1272 pinfo->node_ms_index = r1;
1273 pinfo->node_ls_index = r2;
1274 /* for non scalar, non memory and non real, this is expression range */
1275 /* if non constant index (for reg) - use entire range */
1276
1277 biti = -1;
1278 if (xp->optyp == LSB)
1279 {
1280 /* if anything but simple number, range is entire - per change op rules */
1281 if (xp->ru.x->optyp == NUMBER)
1282 {
1283 biti = __contab[xp->ru.x->ru.xvi];
1284 pinfo->node_ms_index = pinfo->node_ls_index = __unnormalize_ndx(np, biti);
1285 }
1286 }
1287 else if (xp->optyp == PARTSEL)
1288 {
1289 biti = __contab[xp->ru.x->lu.x->ru.xvi];
1290 bitj = __contab[xp->ru.x->ru.x->ru.xvi];
1291 pinfo->node_ms_index = __unnormalize_ndx(np, biti);
1292 pinfo->node_ls_index = __unnormalize_ndx(np, bitj);
1293 }
1294
1295 /* set node type field */
1296 if (!np->n_isavec)
1297 {
1298 if (np->ntyp < NONWIRE_ST) pinfo->node_type = TF_NETSCALAR_NODE;
1299 else pinfo->node_type = TF_REG_NODE;
1300 }
1301 else
1302 {
1303 if (np->ntyp == N_REG) pinfo->node_type = TF_REG_NODE;
1304 else if (np->ntyp == N_INT) pinfo->node_type = TF_INTEGER_NODE;
1305 else if (np->ntyp == N_TIME) pinfo->node_type = TF_TIME_NODE;
1306 else pinfo->node_type = TF_NETVECTOR_NODE;
1307 }
1308 /* correct for bit select from scalared wire to TF_NETSCALAR */
1309 /* must be constant bit select from scalared wire vector */
1310 if (pinfo->node_type == TF_NETVECTOR_NODE)
1311 {
1312 if (np->vec_scalared && biti != -1) pinfo->node_type = TF_NETSCALAR_NODE;
1313 }
1314
1315 wlen = wlen_(xp->szu.xclen);
1316 pinfo->node_ngroups = wlen;
1317 /* know strength here impossible */
1318 allocset_vecval(pinfo, xsp, wlen);
1319 __pop_xstk();
1320 return(pinfo);
1321 }
1322
1323 /*
1324 * allocate and set the vecval_p field
1325 */
allocset_vecval(struct t_tfnodeinfo * pinfo,struct xstk_t * xsp,int32 wlen)1326 static void allocset_vecval(struct t_tfnodeinfo *pinfo, struct xstk_t *xsp,
1327 int32 wlen)
1328 {
1329 register int32 wi;
1330 struct t_vecval *vecp;
1331
1332 pinfo->node_value.vecval_p = (struct t_vecval *)
1333 __mytf_malloc(wlen*sizeof(struct t_vecval));
1334 vecp = pinfo->node_value.vecval_p;
1335 for (wi = 0; wi < wlen; wi++)
1336 {
1337 vecp[wi].avalbits = (int32) xsp->ap[wi];
1338 vecp[wi].bvalbits = (int32) xsp->bp[wi];
1339 }
1340 }
1341
1342 /*
1343 * emit error for illegal routine called from checktf or sizetf
1344 * or before start of ims
1345 */
bad_nosimtf_err(char * rnam)1346 static int32 bad_nosimtf_err(char *rnam)
1347 {
1348 __sgferr(1289,
1349 "%s routine not callable before start of sim, during reset, or from checktf or sizetf because sets value or delay",
1350 rnam);
1351 return(TF_NULLPARAM);
1352 }
1353
1354 /*
1355 * emit error for tf calls when there is no tf context
1356 */
bad_notfcontext_err(char * rnam)1357 static int32 bad_notfcontext_err(char *rnam)
1358 {
1359 __sgferr(1289,
1360 "%s routine not callable because user code not invoked by PLI 1.0 - was systf registered using vpi_?",
1361 rnam);
1362 return(TF_NULLPARAM);
1363 }
1364
1365 /*
1366 * emit error for illegal routine called from checktf or sizetf
1367 */
bad_rosync_err(char * rnam)1368 static int32 bad_rosync_err(char *rnam)
1369 {
1370 __sgferr(1299,
1371 "%s routine not callable during ro sync - it schedules or writes", rnam);
1372 return(TF_NULLPARAM);
1373 }
1374
1375 /*
1376 * initialize an node info struct
1377 */
init_nodeinfo(struct t_tfnodeinfo * ninfop)1378 static void init_nodeinfo(struct t_tfnodeinfo *ninfop)
1379 {
1380 ninfop->node_type = TF_NULL_NODE;
1381 ninfop->node_value.vecval_p = NULL;
1382 ninfop->node_symbol = NULL;
1383 ninfop->node_ngroups = 0;
1384 ninfop->node_vec_size = 0;
1385 ninfop->node_sign = FALSE;
1386 ninfop->node_ms_index = 0;
1387 ninfop->node_ls_index = 0;
1388 ninfop->node_mem_size = 0;
1389 ninfop->node_lhs_element = 0;
1390 ninfop->node_rhs_element = 0;
1391 ninfop->node_handle = NULL;
1392 }
1393
1394 /*
1395 * fill passed exprinfo struct from nparam
1396 */
tf_iexprinfo(int32 pnum,p_tfexprinfo pinfo,char * inst)1397 extern p_tfexprinfo tf_iexprinfo(int32 pnum, p_tfexprinfo pinfo, char *inst)
1398 {
1399 struct t_tfexprinfo *pinfo2;
1400 struct tfinst_t *sav_tfip;
1401 struct tfrec_t *sav_tfrp;
1402
1403 set_tfinst_(inst, sav_tfip, sav_tfrp);
1404 __push_itstk(__tfinst->tfitp);
1405 pinfo2 = tf_exprinfo(pnum, pinfo);
1406 __pop_itstk();
1407 __tfinst = sav_tfip;
1408 __tfrec = sav_tfrp;
1409 return(pinfo2);
1410 }
1411
tf_exprinfo(int32 pnum,p_tfexprinfo pinfo)1412 extern p_tfexprinfo tf_exprinfo(int32 pnum, p_tfexprinfo pinfo)
1413 {
1414 register int32 wi;
1415 int32 wlen, slen;
1416 word32 *wp;
1417 double d1;
1418 struct expr_t *xp;
1419 struct xstk_t *xsp;
1420 struct tfarg_t *tfap;
1421 struct net_t *np;
1422 char *chp;
1423
1424 if (__tfrec == NULL)
1425 {
1426 bad_notfcontext_err("tf_exprinfo");
1427 return(NULL);
1428 }
1429 if (pnum < 1 || pnum >= __tfrec->tfanump1) return(NULL);
1430 tfap = &(__tfrec->tfargs[pnum]);
1431 xp = tfap->arg.axp;
1432 /* save for possible use by tf_evaluatep */
1433 /* SJM 11/29/99 - also following new LRM and XL used by tf_propagatep */
1434 tfap->sav_xinfos[__inum] = (char *) pinfo;
1435
1436 init_exprinfo(pinfo);
1437 pinfo->expr_type = (short) get_xinfo_typ(xp);
1438 if (xp->optyp == LSB || xp->optyp == PARTSEL)
1439 {
1440 if (xp->tf_isrw) pinfo->expr_lhs_select = 1;
1441 else pinfo->expr_rhs_select = 1;
1442 }
1443 if (xp->optyp == NUMBER && xp->is_string)
1444 {
1445 wp = &(__contab[xp->ru.xvi]);
1446 chp = __alloc_vval_to_cstr(wp, xp->szu.xclen, FALSE, FALSE);
1447 pinfo->expr_string = chp;
1448 slen = strlen(chp);
1449 pinfo->expr_vec_size = 8*slen;
1450 return(pinfo);
1451 }
1452 /* here this always handles any gref itree pushing and popping */
1453 xsp = __eval_xpr(xp);
1454 if (xp->is_real)
1455 {
1456 memcpy(&d1, xsp->ap, sizeof(double));
1457
1458 pinfo->real_value = d1;
1459 /* SJM 09/07/99 - previous problem with signedness of reals */
1460 /* reals always signed */
1461 pinfo->expr_sign = TRUE;
1462 goto done;
1463 }
1464 /* AIV 02/03/03 - if expr is ID, signed for systf arg comes from net */
1465 if(xp->optyp == ID || xp->optyp == GLBREF)
1466 {
1467 np = xp->lu.sy->el.enp;
1468 if (np->n_signed) pinfo->expr_sign = TRUE;
1469 }
1470 /* only other possibility is number or param where there is no ID */
1471 /* so has sign will be correctly set */
1472 else if (xp->has_sign) pinfo->expr_sign = TRUE;
1473
1474 pinfo->expr_vec_size = (int32) xp->szu.xclen;
1475 wlen = wlen_(xp->szu.xclen);
1476 pinfo->expr_ngroups = (int32) wlen;
1477 pinfo->expr_value_p = (struct t_vecval *)
1478 __mytf_malloc(wlen*sizeof(struct t_vecval));
1479 for (wi = 0; wi < wlen; wi++)
1480 {
1481 pinfo->expr_value_p[wi].avalbits = (int32) xsp->ap[wi];
1482 pinfo->expr_value_p[wi].bvalbits = (int32) xsp->bp[wi];
1483 }
1484
1485 done:
1486 __pop_xstk();
1487 return(pinfo);
1488 }
1489
1490 /*
1491 * convert a verilog value into a c string and return in malloced string
1492 * notice no truncation here mostly for PLI
1493 * need to leave prefix of exprline since may be called from nested func.
1494 * or as display argument
1495 */
__alloc_vval_to_cstr(word32 * ap,int32 blen,int32 nd_quotes,int32 space_0)1496 extern char *__alloc_vval_to_cstr(word32 *ap, int32 blen, int32 nd_quotes,
1497 int32 space_0)
1498 {
1499 int32 sav_sofs, slen;
1500 char *chp;
1501
1502 sav_sofs = __cur_sofs;
1503 /* always convert escaped special character such as new line to \\n */
1504 __xline_vval_to_cstr(ap, blen, nd_quotes, space_0, TRUE);
1505 slen = __cur_sofs - sav_sofs;
1506 chp = __mytf_malloc(slen + 1);
1507 strcpy(chp, &(__exprline[sav_sofs]));
1508 /* restore exprline */
1509 __cur_sofs = sav_sofs;
1510 __exprline[sav_sofs] = '\0';
1511 return(chp);
1512 }
1513
1514 /*
1515 * initialize an expr info struct
1516 */
init_exprinfo(struct t_tfexprinfo * xinfop)1517 static void init_exprinfo(struct t_tfexprinfo *xinfop)
1518 {
1519 xinfop->expr_type = TF_READONLY;
1520 xinfop->expr_value_p = NULL;
1521 xinfop->expr_string = NULL;
1522 xinfop->expr_ngroups = 0;
1523 xinfop->expr_vec_size = 0;
1524 xinfop->expr_sign = FALSE;
1525 xinfop->expr_lhs_select = 0;
1526 xinfop->expr_rhs_select = 0;
1527 }
1528
1529 /*
1530 * routine to get exprinfo type
1531 */
get_xinfo_typ(struct expr_t * xp)1532 static int32 get_xinfo_typ(struct expr_t *xp)
1533 {
1534 struct net_t *np;
1535
1536 switch ((byte) xp->optyp) {
1537 case OPEMPTY: return(TF_NULLPARAM);
1538 case NUMBER:
1539 if (xp->is_string) return(TF_STRING);
1540 return(TF_READONLY);
1541 case ISNUMBER:
1542 if (xp->is_string) __arg_terr(__FILE__, __LINE__);
1543 return(TF_READONLY);
1544 case REALNUM: case ISREALNUM: return(TF_READONLYREAL);
1545 }
1546 /* some kind of rhs expr. that cannot be assigned to */
1547 if (xp->tf_isrw)
1548 switch ((byte) xp->optyp) {
1549 case ID:
1550 case GLBREF:
1551 np = xp->lu.sy->el.enp;
1552 if (np->ntyp == N_REAL) return(TF_READWRITEREAL);
1553 /* know this is id than can be lhs */
1554 return(TF_READWRITE);
1555 case LSB:
1556 np = xp->lu.x->lu.sy->el.enp;
1557 if (np->n_isarr) return(TF_RWMEMSELECT);
1558 return(TF_RWBITSELECT);
1559 case PARTSEL: return(TF_RWPARTSELECT);
1560 default: __case_terr(__FILE__, __LINE__);
1561 }
1562 return(TF_READONLY);
1563 }
1564
1565 /*
1566 * PARAMETER ACCESS ROUTINES
1567 */
1568
tf_igetp(int32 pnum,char * inst)1569 extern int32 tf_igetp(int32 pnum, char *inst)
1570 {
1571 int32 rv;
1572 struct tfinst_t *sav_tfip;
1573 struct tfrec_t *sav_tfrp;
1574
1575 set_tfinst_(inst, sav_tfip, sav_tfrp);
1576 __push_itstk(__tfinst->tfitp);
1577 rv = tf_getp(pnum);
1578 __pop_itstk();
1579 __tfinst = sav_tfip;
1580 __tfrec = sav_tfrp;
1581 return(rv);
1582 }
1583
1584 /*
1585 * return value of parameter as int
1586 * values here are assumed to be signed
1587 * LOOKATME - document that ingores b val
1588 * according to LRM just return the low 32 bits without any checking
1589 */
tf_getp(int32 pnum)1590 extern int32 tf_getp(int32 pnum)
1591 {
1592 int32 rv;
1593 word32 *wp;
1594 struct expr_t *xp;
1595 struct xstk_t *xsp;
1596 char *chp;
1597
1598 if (__tfrec == NULL) return(bad_notfcontext_err("tf_getp"));
1599 if (pnum < 0 || pnum >= __tfrec->tfanump1) return(TF_NULLPARAM);
1600 /* 0 ok here for possible func. return value */
1601
1602 xsp = NULL;
1603 /* func. return value is special case */
1604 if (pnum == 0)
1605 {
1606 if (!__tfrec->tf_func) return(TF_NULLPARAM);
1607
1608 push_xstk_(xsp, __tfrec->fretsiz);
1609 wp = __tfrec->tfargs[0].arg.awp;
1610 memcpy(xsp->ap, wp, 2*wlen_(__tfrec->fretsiz)*WRDBYTES);
1611 if (__tfrec->fretreal) goto do_real;
1612
1613 /* SJM 08/31/00 - misread LRM for 2 value PLI 1.0 routines x/z is 0 */
1614 if (!vval_is0_(xsp->bp, xsp->xslen)) rv = 0; else rv = (int32) xsp->ap[0];
1615 goto done;
1616 }
1617
1618 xp = __tfrec->tfargs[pnum].arg.axp;
1619 if (xp->optyp == OPEMPTY) return(TF_NULLPARAM);
1620
1621 xsp = __eval_xpr(xp);
1622 /* if real, must round */
1623 if (xp->is_real)
1624 {
1625 do_real:
1626 /* this implements Verilog style rounding */
1627 __cnv_stk_fromreal_toreg32(xsp);
1628 rv = (int32) xsp->ap[0];
1629 goto done;
1630 }
1631 /* if any kind of literal string - cannot be expr - need c style */
1632 /* the return 32 bit int32 is pointer to string */
1633 if (xp->optyp == NUMBER && xp->is_string)
1634 {
1635 chp = __alloc_vval_to_cstr(xsp->ap, xsp->xslen, FALSE, FALSE);
1636 /* FIXME ??? - not 64 bit clean */
1637 rv = (int32) chp;
1638 goto done;
1639 }
1640
1641 /* finally just return bit pattern - caller must interpret sign */
1642 /* SJM 08/31/00 - misread LRM for 2 value PLI 1.0 routines x/z is 0 */
1643 if (!vval_is0_(xsp->bp, xsp->xslen)) rv = 0; else rv = (int32) xsp->ap[0];
1644 done:
1645 __pop_xstk();
1646 return(rv);
1647 }
1648
tf_igetlongp(int32 * aof_highvalue,int32 pnum,char * inst)1649 extern int32 tf_igetlongp(int32 *aof_highvalue, int32 pnum, char *inst)
1650 {
1651 int32 rv;
1652 struct tfinst_t *sav_tfip;
1653 struct tfrec_t *sav_tfrp;
1654
1655 set_tfinst_(inst, sav_tfip, sav_tfrp);
1656 __push_itstk(__tfinst->tfitp);
1657 rv = tf_getlongp(aof_highvalue, pnum);
1658 __pop_itstk();
1659 __tfinst = sav_tfip;
1660 __tfrec = sav_tfrp;
1661 return(rv);
1662 }
1663
1664 /*
1665 * get parameter into 2 32 bit ints (64 bits non x/z)
1666 * if string return ptr in low 32 bits
1667 * if paremeter real return error, must use getrealp
1668 */
tf_getlongp(int32 * aof_highvalue,int32 pnum)1669 extern int32 tf_getlongp(int32 *aof_highvalue, int32 pnum)
1670 {
1671 int32 rv;
1672 word32 *wp;
1673 double d1;
1674 struct expr_t *xp;
1675 struct xstk_t *xsp;
1676 char *chp;
1677
1678 if (__tfrec == NULL) return(bad_notfcontext_err("tf_getlongp"));
1679 *aof_highvalue = 0;
1680 if (pnum < 0 || pnum >= __tfrec->tfanump1) return(TF_NULLPARAM);
1681 /* 0 ok here for possible func. return value */
1682
1683 xsp = NULL;
1684 /* func. return value is special case */
1685 if (pnum == 0)
1686 {
1687 if (!__tfrec->tf_func) return(TF_NULLPARAM);
1688
1689 push_xstk_(xsp, __tfrec->fretsiz);
1690 wp = __tfrec->tfargs[0].arg.awp;
1691 memcpy(xsp->ap, wp, 2*wlen_(__tfrec->fretsiz)*WRDBYTES);
1692 if (__tfrec->fretreal) goto do_real;
1693
1694 /* SJM 08/31/00 - misread LRM for 2 value PLI 1.0 routines x/z is 0 */
1695 if (!vval_is0_(xsp->bp, xsp->xslen)) { *aof_highvalue = 0; rv = 0; }
1696 else
1697 {
1698 if (__tfrec->fretsiz > 32) *aof_highvalue = (int32) xsp->ap[1];
1699 else *aof_highvalue = 0;
1700 rv = (int32) xsp->ap[0];
1701 }
1702 goto done;
1703 }
1704
1705 xp = __tfrec->tfargs[pnum].arg.axp;
1706 if (xp->optyp == OPEMPTY) return(TF_NULLPARAM);
1707
1708 xsp = __eval_xpr(xp);
1709 if (xp->is_real)
1710 {
1711 do_real:
1712 memcpy(&d1, xsp->ap, sizeof(double));
1713 tf_real_to_long(d1, &rv, aof_highvalue);
1714 goto done;
1715 }
1716 /* if any kind of literal string - cannot be expr - need c style */
1717 /* the return 32 bit int32 is pointer to string */
1718 if (xp->optyp == NUMBER && xp->is_string)
1719 {
1720 chp = __alloc_vval_to_cstr(xsp->ap, xsp->xslen, FALSE, FALSE);
1721
1722 /* FIXME ??? - not 64 bit clean */
1723 rv = (int32) chp;
1724 goto done;
1725 }
1726
1727 /* caller must interpret any sign */
1728 /* SJM 08/31/00 - misread LRM for 2 value PLI 1.0 routines x/z is 0 */
1729 if (!vval_is0_(xsp->bp, xsp->xslen)) { *aof_highvalue = 0; rv = 0; }
1730 else
1731 {
1732 if (xsp->xslen > 32) *aof_highvalue = (int32) xsp->ap[1];
1733 else *aof_highvalue = 0;
1734 rv = (int32) xsp->ap[0];
1735 }
1736
1737 done:
1738 __pop_xstk();
1739 return(rv);
1740 }
1741
1742 /*
1743 * return double from passed routine
1744 */
tf_igetrealp(int32 pnum,char * inst)1745 extern double tf_igetrealp(int32 pnum, char *inst)
1746 {
1747 double d1;
1748 struct tfinst_t *sav_tfip;
1749 struct tfrec_t *sav_tfrp;
1750
1751 set_tfinst_(inst, sav_tfip, sav_tfrp);
1752 __push_itstk(__tfinst->tfitp);
1753 d1 = tf_getrealp(pnum);
1754 __pop_itstk();
1755 __tfinst = sav_tfip;
1756 __tfrec = sav_tfrp;
1757 return(d1);
1758 }
1759
1760 /*
1761 * get value of nparam (convert to real if needed) and return
1762 * here return 0 if literal string and use signedness of node for sign of r
1763 */
tf_getrealp(int32 pnum)1764 extern double tf_getrealp(int32 pnum)
1765 {
1766 int32 i1;
1767 word32 *wp;
1768 double d1;
1769 word64 t1;
1770 struct expr_t *xp;
1771 struct xstk_t *xsp;
1772
1773 xp = NULL;
1774 if (__tfrec == NULL)
1775 {
1776 bad_notfcontext_err("tf_getrealp");
1777 return((double) TF_NULLPARAM);
1778 }
1779 if (pnum < 0 || pnum >= __tfrec->tfanump1) return((double) TF_NULLPARAM);
1780
1781 /* 0 ok here for possible func. return value */
1782 /* func. return value is special case */
1783 if (pnum == 0)
1784 {
1785 if (!__tfrec->tf_func) return(TF_NULLPARAM);
1786 push_xstk_(xsp, __tfrec->fretsiz);
1787 wp = __tfrec->tfargs[0].arg.awp;
1788 if (__tfrec->fretreal)
1789 { memcpy(&d1, wp, sizeof(double)); goto done; }
1790 memcpy(xsp->ap, wp, 2*wlen_(__tfrec->fretsiz)*WRDBYTES);
1791 goto do_non_real;
1792 }
1793
1794 xp = __tfrec->tfargs[pnum].arg.axp;
1795 /* literal string is error */
1796 if (xp->optyp == OPEMPTY || (xp->optyp == NUMBER && xp->is_string))
1797 return((double) TF_NULLPARAM);
1798
1799 xsp = __eval_xpr(xp);
1800 /* if real, must round */
1801 if (xp->is_real) { memcpy(&d1, xsp->ap, sizeof(double)); goto done; }
1802 /* only true if int32 and exactly 32 bits */
1803 if (xp->has_sign) { i1 = (int32) xsp->ap[0]; d1 = (double) i1; goto done; }
1804
1805 do_non_real:
1806 /* SJM 05/10/04 - must handle conversion of signed 33-64 to signed double */
1807 if (xsp->xslen > WBITS)
1808 {
1809 if (xp->has_sign) d1 = __cnvt_signed64_to_real(xsp->ap, xsp->xslen);
1810 else
1811 {
1812 t1 = ((word64) xsp->ap[0]) | (((word64) xsp->ap[1]) << 32);
1813 if (!__v64_to_real(&d1, &t1)) d1 = 0.0;
1814 }
1815 }
1816 else d1 = (double) xsp->ap[0];
1817
1818 done:
1819 __pop_xstk();
1820 return(d1);
1821 }
1822
1823 /*
1824 * convert signed 33 to 64 bit to real - tricky if narrow than 64
1825 */
__cnvt_signed64_to_real(word32 * ap,int32 blen)1826 extern double __cnvt_signed64_to_real(word32 *ap, int32 blen)
1827 {
1828 word64 t1;
1829 sword64 st1;
1830 double d1;
1831
1832 /* DBG remove -- */
1833 if (blen <= WBITS) __misc_terr(__FILE__, __LINE__);
1834 /* -- */
1835
1836 /* t1 is just the word32 bit pattern */
1837 t1 = ((word64) ap[0]) | (((word64) ap[1]) << 32);
1838 if (__is_lnegative(ap, blen))
1839 {
1840 t1 &= (((word64) ~(__masktab[ubits_(blen)])) << 32);
1841 st1 = (sword64) t1;
1842 st1 = -st1;
1843 t1 = (word64) st1;
1844 if (!__v64_to_real(&d1, &t1)) d1 = 0.0;
1845 else d1 = -d1;
1846 }
1847 else
1848 {
1849 if (!__v64_to_real(&d1, &t1)) d1 = 0.0;
1850 }
1851 return(d1);
1852 }
1853
1854 /*
1855 * TF_ PARAMETER STORE ROUTINES
1856 */
1857
tf_iputp(int32 pnum,int32 value,char * inst)1858 extern int32 tf_iputp(int32 pnum, int32 value, char *inst)
1859 {
1860 int32 rv;
1861 struct tfinst_t *sav_tfip;
1862 struct tfrec_t *sav_tfrp;
1863
1864 set_tfinst_(inst, sav_tfip, sav_tfrp);
1865 __push_itstk(__tfinst->tfitp);
1866 rv = tf_putp(pnum, value);
1867 __pop_itstk();
1868 __tfinst = sav_tfip;
1869 __tfrec = sav_tfrp;
1870 return(rv);
1871 }
1872
1873 /*
1874 * assign int32 value to parameter nparm
1875 * return 0 on error else 1 and assign
1876 */
tf_putp(int32 pnum,int32 value)1877 extern int32 tf_putp(int32 pnum, int32 value)
1878 {
1879 int32 rv;
1880 word32 *wp;
1881 struct tfarg_t *tfap;
1882 struct expr_t *xp;
1883 struct xstk_t *xsp;
1884
1885 if (__run_state != SS_SIM)
1886 {
1887 rv = bad_nosimtf_err("tf_(i)putp");
1888 /* SJM 12/17/02 - error is 1 and success is 0 */
1889 if (rv == TF_NULLPARAM) return(1); else return(0);
1890 }
1891 if (__rosync_slot)
1892 {
1893 rv = bad_rosync_err("tf_(i)putp");
1894 /* SJM 12/17/02 - error is 1 and success is 0 */
1895 if (rv == TF_NULLPARAM) return(1); else return(0);
1896 }
1897 if (__tfrec == NULL)
1898 {
1899 rv = bad_notfcontext_err("tf_putp");
1900 /* SJM 12/17/02 - error is 1 and success is 0 */
1901 if (rv == TF_NULLPARAM) return(1); else return(0);
1902 }
1903 if (pnum < 0 || pnum >= __tfrec->tfanump1) return(1);
1904
1905 tfap = &(__tfrec->tfargs[pnum]);
1906 /* 0 ok here for possible func. return value */
1907 /* func. return value is special case - change return value, no assign */
1908 if (pnum == 0)
1909 {
1910 push_xstk_(xsp, WBITS);
1911 xsp->ap[0] = (word32) value;
1912 xsp->bp[0] = 0L;
1913
1914 if (!__tfrec->tf_func) return(1);
1915 if (__tfrec->fretreal) __cnv_stk_fromreg_toreal(xsp, TRUE);
1916 /* contiguous bytes of stack have value after possible conversion */
1917 /* SJM 05/10/04 - deprecated PLI 1.0 can only return word32 regs */
1918 else if (xsp->xslen != __tfrec->fretsiz)
1919 {
1920 __sizchgxs(xsp, __tfrec->fretsiz);
1921 }
1922 wp = tfap->arg.awp;
1923 memcpy(wp, xsp->ap, 2*wlen_(__tfrec->fretsiz)*WRDBYTES);
1924 __pop_xstk();
1925 return(0);
1926 }
1927
1928 xp = tfap->arg.axp;
1929 if (!xp->tf_isrw) return(1);
1930 push_xstk_(xsp, WBITS);
1931 xsp->ap[0] = (word32) value;
1932 xsp->bp[0] = 0L;
1933
1934 /* assigned to param is real must convert before assign */
1935 if (xp->is_real) __cnv_stk_fromreg_toreal(xsp, TRUE);
1936 /* SJM 05/10/04 - deprecated PLI 1.0 can only return word32 regs */
1937 else if (xsp->xslen != xp->szu.xclen) __sizchgxs(xsp, xp->szu.xclen);
1938 /* ok to assign (by continuous) to wire */
1939 exec_tfarg_assign(tfap, xp, xsp->ap, xsp->bp);
1940 __pop_xstk();
1941 return(0);
1942 }
1943
tf_iputlongp(int32 pnum,int32 lowvalue,int32 highvalue,char * inst)1944 extern int32 tf_iputlongp(int32 pnum, int32 lowvalue, int32 highvalue, char *inst)
1945 {
1946 int32 rv;
1947 struct tfinst_t *sav_tfip;
1948 struct tfrec_t *sav_tfrp;
1949
1950 set_tfinst_(inst, sav_tfip, sav_tfrp);
1951 __push_itstk(__tfinst->tfitp);
1952 rv = tf_putlongp(pnum, lowvalue, highvalue);
1953 __pop_itstk();
1954 __tfinst = sav_tfip;
1955 __tfrec = sav_tfrp;
1956 return(rv);
1957 }
1958
1959 /*
1960 * input is 64 bit as 2 ints that is assigned to expr.
1961 * may need to convert stack to right lhs width and type
1962 * return 0 on error else 1 and assign
1963 */
tf_putlongp(int32 pnum,int32 lowvalue,int32 highvalue)1964 extern int32 tf_putlongp(int32 pnum, int32 lowvalue, int32 highvalue)
1965 {
1966 int32 rv;
1967 double d1;
1968 struct tfarg_t *tfap;
1969 struct expr_t *xp;
1970 struct xstk_t *xsp;
1971
1972 if (__run_state != SS_SIM)
1973 {
1974 rv = bad_nosimtf_err("tf_(i)putlongp");
1975 /* SJM 12/17/02 - error is 1 and success is 0 */
1976 if (rv == TF_NULLPARAM) return(1); else return(0);
1977 }
1978 if (__rosync_slot)
1979 {
1980 rv = bad_rosync_err("tf_(i)putlongp");
1981 /* SJM 12/17/02 - error is 1 and success is 0 */
1982 if (rv == TF_NULLPARAM) return(1); else return(0);
1983 }
1984 if (__tfrec == NULL)
1985 {
1986 rv = bad_notfcontext_err("tf_putlongp");
1987 /* SJM 12/17/02 - error is 1 and success is 0 */
1988 if (rv == TF_NULLPARAM) return(1); else return(0);
1989 }
1990 if (pnum < 0 || pnum >= __tfrec->tfanump1) return(1);
1991
1992 tfap = &(__tfrec->tfargs[pnum]);
1993 /* 0 ok here for possible func. return value */
1994 /* func. return value is special case - change return value, no assign */
1995 if (pnum == 0)
1996 {
1997 if (!__tfrec->tf_func) return(1);
1998
1999 /* if assigning to real convert - but rule is to ignore high 32 bits here */
2000 if (__tfrec->fretreal)
2001 {
2002 tf_long_to_real(lowvalue, highvalue, &d1);
2003 memcpy(tfap->arg.awp, &d1, sizeof(double));
2004 return(0);
2005 }
2006
2007 push_xstk_(xsp, 64);
2008 xsp->ap[0] = (word32) lowvalue;
2009 xsp->ap[1] = (word32) highvalue;
2010 xsp->bp[0] = xsp->bp[1] = 0L;
2011 /* contiguous bytes of stack have value after possible conversion */
2012 /* SJM 05/10/04 - deprecated PLI 1.0 can only return word32 regs */
2013 if (xsp->xslen != __tfrec->fretsiz) __sizchgxs(xsp, __tfrec->fretsiz);
2014 memcpy(tfap->arg.awp, xsp->ap, 2*wlen_(__tfrec->fretsiz)*WRDBYTES);
2015 __pop_xstk();
2016 return(0);
2017 }
2018
2019 xp = tfap->arg.axp;
2020 if (!xp->tf_isrw) return(1);
2021
2022 /* assigned to param is real must convert to double before assign */
2023 /* this must use time long form */
2024 if (xp->is_real)
2025 {
2026 tf_long_to_real(lowvalue, highvalue, &d1);
2027 push_xstk_(xsp, REALBITS);
2028 memcpy(xsp->ap, &d1, sizeof(double));
2029 }
2030 else
2031 {
2032 push_xstk_(xsp, 64);
2033 xsp->ap[0] = (word32) lowvalue;
2034 xsp->ap[1] = (word32) highvalue;
2035 xsp->bp[0] = xsp->bp[1] = 0L;
2036 /* SJM 05/10/04 - deprecated PLI 1.0 can only return word32 regs */
2037 if (xsp->xslen != xp->szu.xclen) __sizchgxs(xsp, xp->szu.xclen);
2038 }
2039 exec_tfarg_assign(tfap, xp, xsp->ap, xsp->bp);
2040 __pop_xstk();
2041 return(0);
2042 }
2043
tf_iputrealp(int32 pnum,double value,char * inst)2044 extern int32 tf_iputrealp(int32 pnum, double value, char *inst)
2045 {
2046 int32 rv;
2047 struct tfinst_t *sav_tfip;
2048 struct tfrec_t *sav_tfrp;
2049
2050 set_tfinst_(inst, sav_tfip, sav_tfrp);
2051 __push_itstk(__tfinst->tfitp);
2052 rv = tf_putrealp(pnum, value);
2053 __pop_itstk();
2054 __tfinst = sav_tfip;
2055 __tfrec = sav_tfrp;
2056 return(rv);
2057 }
2058
2059 /*
2060 * assign real value to paramter nparm
2061 */
tf_putrealp(int32 pnum,double value)2062 extern int32 tf_putrealp(int32 pnum, double value)
2063 {
2064 register struct tfarg_t *tfap;
2065 int32 rv;
2066 struct expr_t *xp;
2067 struct xstk_t *xsp;
2068
2069 if (__run_state != SS_SIM)
2070 {
2071 rv = bad_nosimtf_err("tf_(i)putrealp");
2072 /* SJM 12/17/02 - error is 1 and success is 0 */
2073 if (rv == TF_NULLPARAM) return(1); else return(0);
2074 }
2075 if (__rosync_slot)
2076 {
2077 rv = bad_rosync_err("tf_(i)putrealp");
2078 /* SJM 12/17/02 - error is 1 and success is 0 */
2079 if (rv == TF_NULLPARAM) return(1); else return(0);
2080 }
2081 if (__tfrec == NULL)
2082 {
2083 rv = bad_notfcontext_err("tf_putrealp");
2084 /* SJM 12/17/02 - error is 1 and success is 0 */
2085 if (rv == TF_NULLPARAM) return(1); else return(0);
2086 }
2087 if (pnum < 0 || pnum >= __tfrec->tfanump1) return(1);
2088
2089 tfap = &(__tfrec->tfargs[pnum]);
2090 /* 0 ok here for possible func. return value */
2091 /* func. return value is special case - change return value, no assign */
2092 if (pnum == 0)
2093 {
2094 if (!__tfrec->tf_func) return(1);
2095 if (__tfrec->fretreal)
2096 {
2097 memcpy(tfap->arg.awp, &value, sizeof(double));
2098 return(0);
2099 }
2100 if ((xsp = tf_pushconvfromreal(value, __tfrec->fretsiz)) == NULL)
2101 return(1);
2102 memcpy(tfap->arg.awp, xsp->ap, 2*wlen_(__tfrec->fretsiz)*WRDBYTES);
2103 __pop_xstk();
2104 return(0);
2105 }
2106
2107 xp = tfap->arg.axp;
2108 if (!xp->tf_isrw) return(1);
2109
2110 if (xp->is_real)
2111 {
2112 push_xstk_(xsp, REALBITS);
2113 memcpy(xsp->ap, &value, sizeof(double));
2114 }
2115 else
2116 {
2117 if ((xsp = tf_pushconvfromreal(value, xp->szu.xclen)) == NULL)
2118 return(1);
2119 }
2120 exec_tfarg_assign(tfap, xp, xsp->ap, xsp->bp);
2121 __pop_xstk();
2122 return(0);
2123 }
2124
2125 /*
2126 * routine to push and convert to real tf task/function parameter onto stack
2127 * know only called
2128 * returns nil with nothing on stack on error
2129 */
tf_pushconvfromreal(double d1,int32 destsiz)2130 static struct xstk_t *tf_pushconvfromreal(double d1, int32 destsiz)
2131 {
2132 int32 i, lo, hi;
2133 struct xstk_t *xsp;
2134
2135 if (destsiz > WBITS)
2136 {
2137 tf_real_to_long(d1, &lo, &hi);
2138 push_xstk_(xsp, 64);
2139 xsp->ap[0] = (word32) lo;
2140 xsp->ap[1] = (word32) hi;
2141 xsp->bp[0] = xsp->bp[1] = 0L;
2142 }
2143 else
2144 {
2145 push_xstk_(xsp, WBITS);
2146 i = (int32) d1;
2147 xsp->ap[0] = (word32) i;
2148 xsp->bp[0] = 0L;
2149 }
2150 /* SJM 05/10/04 - deprecated PLI 1.0 can only return word32 regs */
2151 if (xsp->xslen != destsiz) __sizchgxs(xsp, destsiz);
2152 return(xsp);
2153 }
2154
2155 /*
2156 * TF STRING FORM GET VALUE (FOR X/Z) ROUTINES
2157 */
2158
2159 /*
2160 * get a formatted c style string
2161 */
tf_istrgetp(int32 pnum,int32 format_char,char * inst)2162 extern char *tf_istrgetp(int32 pnum, int32 format_char, char *inst)
2163 {
2164 char *chp;
2165 struct tfinst_t *sav_tfip;
2166 struct tfrec_t *sav_tfrp;
2167
2168 set_tfinst_(inst, sav_tfip, sav_tfrp);
2169 __push_itstk(__tfinst->tfitp);
2170 chp = tf_strgetp(pnum, format_char);
2171 __pop_itstk();
2172 __tfinst = sav_tfip;
2173 __tfrec = sav_tfrp;
2174 return(chp);
2175 }
2176
2177 /*
2178 * get a parameter into c style string
2179 */
tf_strgetp(int32 pnum,int32 format_char)2180 extern char *tf_strgetp(int32 pnum, int32 format_char)
2181 {
2182 struct expr_t *xp;
2183
2184 if (__tfrec == NULL)
2185 {
2186 bad_notfcontext_err("tf_strgetp");
2187 return(NULL);
2188 }
2189 if (pnum < 0 || pnum >= __tfrec->tfanump1) return(NULL);
2190 /* 0 ok here for possible func. return value */
2191 if (pnum == 0)
2192 {
2193 if (!__tfrec->tf_func) return(NULL);
2194 return(__alloc_getasfmt((struct expr_t *) NULL, __tfrec, format_char));
2195 }
2196 xp = __tfrec->tfargs[pnum].arg.axp;
2197 if (xp->optyp == OPEMPTY) return(NULL);
2198
2199 /* if returns 0, know expr line not changed */
2200 return(__alloc_getasfmt(xp, (struct tfrec_t *) NULL, format_char));
2201 }
2202
2203 /*
2204 * convert parameter to c string
2205 * i.e. force intrepretation as string
2206 */
tf_igetcstringp(int32 nparam,char * inst)2207 extern char *tf_igetcstringp(int32 nparam, char *inst)
2208 {
2209 char *chp;
2210 struct tfinst_t *sav_tfip;
2211 struct tfrec_t *sav_tfrp;
2212
2213 set_tfinst_(inst, sav_tfip, sav_tfrp);
2214 __push_itstk(__tfinst->tfitp);
2215 chp = tf_getcstringp(nparam);
2216 __pop_itstk();
2217 __tfinst = sav_tfip;
2218 __tfrec = sav_tfrp;
2219 return(chp);
2220 }
2221
2222 /*
2223 * convert a value to a c string - evaluate expressions if needed
2224 * converts bit pattern to c string
2225 */
tf_getcstringp(int32 nparam)2226 extern char *tf_getcstringp(int32 nparam)
2227 {
2228 int32 blen;
2229 word32 *wp;
2230 struct expr_t *xp;
2231 struct xstk_t *xsp;
2232 char *chp;
2233
2234 if (__tfrec == NULL)
2235 {
2236 bad_notfcontext_err("tf_getcstringp");
2237 return(NULL);
2238 }
2239 if (nparam < 0 || nparam >= __tfrec->tfanump1) return(NULL);
2240 /* 0 ok here for possible func. return value */
2241 if (nparam == 0)
2242 {
2243 if (!__tfrec->tf_func) return(NULL);
2244 wp = __tfrec->tfargs[0].arg.awp;
2245 blen = __trim1_0val(wp, __tfrec->fretsiz);
2246 chp = __alloc_vval_to_cstr(wp, __tfrec->fretsiz, FALSE, FALSE);
2247 return(chp);
2248 }
2249 xp = __tfrec->tfargs[nparam].arg.axp;
2250 if (xp->optyp == OPEMPTY) return(NULL);
2251
2252 /* real bit pattern can't be output as string */
2253 if (xp->is_real) return(NULL);
2254
2255 /* even if literal string can still evaluate */
2256 /* this takes any bit pattern (i.e. real) and makes a string */
2257 /* and ignores and b value */
2258 xsp = __eval_xpr(xp);
2259 /* must remove high 0 bytes */
2260 blen = __trim1_0val(xsp->ap, xsp->xslen);
2261 chp = __alloc_vval_to_cstr(xsp->ap, blen, FALSE, FALSE);
2262 __pop_xstk();
2263 return(chp);
2264 }
2265
2266 /*
2267 * TF_ STRING FORM PARAMETER DELAYED STORE ROUTINES
2268 */
2269
2270 /*
2271 * set a delay from a string that is scanfed into a value that is set
2272 * for nparam of length bitlength use format_char to interpret value_p
2273 * where schedule is delayed delay (scaled) and if of type delaytype
2274 * and store value into parameter which will be lhs expr. at scheduled time
2275 *
2276 * return 0 on error 1 if ok, delaytype is 0 inertial, 1 transport, 2
2277 * pure transport
2278 * must be >= 0, 0 is #0 form
2279 */
2280
2281 /*
2282 * schedule set for other pli task
2283 */
tf_istrdelputp(int32 nparam,int32 bitlength,int32 format_char,char * value_p,int32 delay,int32 delaytype,char * inst)2284 extern int32 tf_istrdelputp(int32 nparam, int32 bitlength, int32 format_char,
2285 char *value_p, int32 delay, int32 delaytype, char *inst)
2286 {
2287 int32 rv;
2288 struct tfinst_t *sav_tfip;
2289 struct tfrec_t *sav_tfrp;
2290
2291 set_tfinst_(inst, sav_tfip, sav_tfrp);
2292 __push_itstk(__tfinst->tfitp);
2293 rv = tf_strdelputp(nparam, bitlength, format_char, value_p, delay,
2294 delaytype);
2295 __pop_itstk();
2296 __tfinst = sav_tfip;
2297 __tfrec = sav_tfrp;
2298 return(rv);
2299 }
2300
tf_strdelputp(int32 nparam,int32 bitlength,int32 format_char,char * value_p,int32 delay,int32 delaytype)2301 extern int32 tf_strdelputp(int32 nparam, int32 bitlength, int32 format_char,
2302 char *value_p, int32 delay, int32 delaytype)
2303 {
2304 int32 rv;
2305 word64 ticks, t1;
2306
2307 /* scale from module delay to ticks */
2308 t1 = (word64) delay;
2309 if (!__inst_mod->mno_unitcnv) cnv_num64to_ticks_(ticks, t1, __inst_mod);
2310 else ticks = t1;
2311
2312 rv = delayed_str_putp(nparam, bitlength, format_char, value_p,
2313 ticks, delaytype);
2314 return(rv);
2315 }
2316
2317 /*
2318 * routine that executes all delays since only difference is form
2319 * of delay - by here converted to internal ticks (scaling done)
2320 * dtyp is delay reschedule determining mode
2321 * possibilities:
2322 *
2323 * inertial replaces pending sched ev with later and removes earlier
2324 * 0: normal Verilog inertial (change so exactly one delay that is latest)
2325 * 1: transport - remove all delays later than scheduled
2326 * 2: pure transport - just add delay - never remove
2327 */
delayed_str_putp(int32 nparam,int32 blen,int32 fmtch,char * value,word64 ticksdel,int32 dtyp)2328 static int32 delayed_str_putp(int32 nparam, int32 blen, int32 fmtch, char *value,
2329 word64 ticksdel, int32 dtyp)
2330 {
2331 register struct tfarg_t *tfap;
2332 register struct dltevlst_t *dlp, *dlp2, *ins_after_dlp;
2333 int32 nbytes;
2334 word64 schtim;
2335 i_tev_ndx tevpi;
2336 struct expr_t *xp;
2337 struct tedputp_t *tedp;
2338 struct xstk_t *xsp;
2339
2340 if (__run_state != SS_SIM) return(bad_nosimtf_err("strdelputp type"));
2341 if (__rosync_slot) return(bad_rosync_err("strdelputp type"));
2342 if (__tfrec == NULL) return(bad_notfcontext_err("strdelputp type"));
2343
2344 /* cannot used schedule delayed putp to assign to return value */
2345 if (nparam < 1 || nparam >= __tfrec->tfanump1) return(TF_NULLPARAM);
2346 tfap = &(__tfrec->tfargs[nparam]);
2347 xp = tfap->arg.axp;
2348 if (!xp->tf_isrw) return(TF_NULLPARAM);
2349 /* push value on to stack - width is lhs needed */
2350 xsp = __putdstr_to_val(value, blen, xp->szu.xclen, fmtch);
2351 if (xsp == NULL) return(TF_NULLPARAM);
2352
2353 schtim = __simtime + ticksdel;
2354 ins_after_dlp = NULL;
2355 /* eliminate new and/or cancel any olds */
2356 if ((dlp = tfap->dputp_tedlst[__inum]) != NULL)
2357 {
2358 /* case 1: inertial - remove all but one latest - return if no effect */
2359 if (dtyp == 0)
2360 {
2361 /* start by removing all of list but last (if needed) - know >=2 */
2362 if (dlp->terp != NULL)
2363 {
2364 dlp2 = __spliceout_last(dlp);
2365 cancel_dputp_toend(tfap, dlp);
2366 dlp = dlp2;
2367 tfap->dputp_tedlst[__inum] = dlp;
2368 dlp->telp = NULL;
2369 }
2370 /* by here list has exactly one element (last) */
2371 /* if new one earlier - do not schedule, same time, use new */
2372 if (__tevtab[dlp->tevpi].etime > schtim) { __pop_xstk(); return(1); }
2373
2374 /* know new event time is later - cancel all of list (i.e. 1 in list) */
2375 cancel_dputp_toend(tfap, dlp);
2376 tfap->dputp_tedlst[__inum] = NULL;
2377 ins_after_dlp = NULL;
2378 goto bld_tev;
2379 }
2380 /* case 2: modified transport - remove all delays > than new */
2381 /* notice if same time delays must leave and insert this after all */
2382 /* currently scheduled for this time */
2383 if (dtyp == 1)
2384 {
2385 /* SJM 09/05/99 - think elmination when scheduled wrong */
2386 /* nothing to remove, just put on end of active pnd0 queue */
2387 /* SJM - if (schtim == 0ULL) goto bld_tev; WRONG */
2388
2389 /* know delay list in time order */
2390 /* dlp2 is one before first after (maybe last), nil is before all */
2391 if ((dlp2 = __find_last_bdltevp(dlp, schtim)) == NULL)
2392 {
2393 /* new delay is before all - must empty list */
2394 /* all delays at same time not removed */
2395 dlp2 = tfap->dputp_tedlst[__inum];
2396 cancel_dputp_toend(tfap, dlp2);
2397 tfap->dputp_tedlst[__inum] = NULL;
2398 ins_after_dlp = NULL;
2399 goto bld_tev;
2400 }
2401 /* new delay is after all - nothing to remove */
2402 if (dlp2->terp == NULL) { ins_after_dlp = dlp2; goto bld_tev; }
2403 /* new delay is after some and before some */
2404 ins_after_dlp = dlp2;
2405 if (dlp2->terp != NULL)
2406 { cancel_dputp_toend(tfap, dlp2->terp); dlp2->terp = NULL; }
2407 goto bld_tev;
2408 }
2409 /* case 3: pure transport - insert in right place in list */
2410 if (dtyp != 2) return(TF_NULLPARAM);
2411 /* new delay is before all - insert at front */
2412 if ((dlp2 = __find_last_bdltevp(dlp, schtim)) == NULL)
2413 { ins_after_dlp = NULL; goto bld_tev; }
2414 /* if goes after list, end of list returned else place to ins after */
2415 ins_after_dlp = dlp2;
2416 }
2417
2418 bld_tev:
2419 /* always build and fill the tev */
2420 alloc_tev_(tevpi, TE_TFPUTPDEL, __inst_ptr, schtim);
2421 if (__tedpfreelst != NULL)
2422 {
2423 tedp = __tedpfreelst;
2424 __tedpfreelst = (struct tedputp_t *)__tedpfreelst->tedtfrp;
2425 }
2426 else tedp = (struct tedputp_t *) __my_malloc(sizeof(struct tedputp_t));
2427 tedp->tedtfrp = __tfrec;
2428 tedp->tedpnum = nparam;
2429 __tevtab[tevpi].tu.tedputp = tedp;
2430
2431 nbytes = 2*WRDBYTES*wlen_(xsp->xslen);
2432 tedp->tedwp = (word32 *) __my_malloc(nbytes);
2433 memcpy(tedp->tedwp, xsp->ap, nbytes);
2434 __pop_xstk();
2435 /* schedule event */
2436 /* case 1: schedule and add to list */
2437 /* SJM 09/05/99 - was only adding to pound 0 at time 0 - WRONG */
2438 if (ticksdel == 0ULL)
2439 {
2440 if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
2441 else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
2442 }
2443 else __insert_event(tevpi);
2444 /* build the dl tev lst */
2445 if (__dltevfreelst != NULL)
2446 { dlp = __dltevfreelst; __dltevfreelst = __dltevfreelst->terp; }
2447 else dlp = (struct dltevlst_t *) __my_malloc(sizeof(struct dltevlst_t));
2448 dlp->tevpi = tevpi;
2449
2450 /* insert at front of list */
2451 if (ins_after_dlp == NULL)
2452 {
2453 dlp2 = tfap->dputp_tedlst[__inum];
2454 dlp->terp = dlp2;
2455 if (dlp2 != NULL) dlp2->telp = dlp;
2456 dlp->telp = NULL;
2457 tfap->dputp_tedlst[__inum] = dlp;
2458 }
2459 /* insert after */
2460 else
2461 {
2462 dlp->terp = ins_after_dlp->terp;
2463 if (dlp->terp != NULL) dlp->terp->telp = dlp;
2464 ins_after_dlp->terp = dlp;
2465 dlp->telp = ins_after_dlp;
2466 }
2467 return(1);
2468 }
2469
2470 /*
2471 * convert putp tf_ routine string to value
2472 * returns nil if number bad
2473 * stacked return value always lhs expected len wide
2474 *
2475 * convert to lhs length and strength if lhs expr stren
2476 * this is special type of scan with mechanism not needed by v_cnv
2477 *
2478 * blen is size for building number with x/z extension - lhslen is needed
2479 * to convert so event eval. assign has exactly rigth width - assign convert
2480 *
2481 * allowing 'v'/'V' extension
2482 */
__putdstr_to_val(char * s,int32 blen,int32 lhslen,int32 fmtch)2483 extern struct xstk_t *__putdstr_to_val(char *s, int32 blen, int32 lhslen,
2484 int32 fmtch)
2485 {
2486 register struct xstk_t *xsp;
2487 int32 slen, stlen;
2488
2489 /* value can be at most id len postions wide - used lhs part sel. for wider */
2490 if (fmtch == 'v' || fmtch == 'V')
2491 {
2492 if ((slen = strlen(s)) >= IDLEN) return(NULL);
2493 if ((xsp = tftostrenval(s, &stlen)) == NULL) return(NULL);
2494 /* adjusts xslen for narrow (xsawlen alloced size) else rebuilds */
2495 if (stlen != lhslen) __strenwiden_sizchg(xsp, lhslen);
2496 return(xsp);
2497 }
2498 /* check the number - must fit in id */
2499 __itokbase = __to_base(fmtch);
2500 /* this copies string without change to num token */
2501 if (!chk_putdstr(s, __itokbase, &slen)) return(NULL);
2502 if (slen >= IDLEN) return(NULL);
2503
2504 /* numeric case caller's passed length is token length */
2505 __itoklen = blen;
2506 /* this cannot fail but to get here know string good - value in ac/bc wr k*/
2507 __to_dhboval(__itokbase, TRUE);
2508 push_xstk_(xsp, __itoklen);
2509 cp_walign_(xsp->ap, __acwrk, __itoklen);
2510 cp_walign_(xsp->bp, __bcwrk, __itoklen);
2511 /* convert in preparation for storing in event for maybe later assign */
2512 /* SJM 05/10/04 - deprecated PLI 1.0 can only return word32 regs */
2513 /* SJM 05/10/04 FIXME ??? ### but here could use format to determine */
2514 if (xsp->xslen != lhslen) __sizchgxs(xsp, lhslen);
2515 return(xsp);
2516 }
2517
2518 /*
2519 * check a number - also copies into token (only change is '_' removed)
2520 * returns F on error else T returned len only valid if T
2521 */
chk_putdstr(char * s,int32 base,int32 * len)2522 static int32 chk_putdstr(char *s, int32 base, int32 *len)
2523 {
2524 register char *chp, *chp2;
2525 register int32 slen;
2526
2527 /* SJM - 03/20/00 - know num token wide eough */
2528 for (*len = 0, slen = 0, chp = s, chp2 = __numtoken; *chp != '\0';)
2529 {
2530 if (*chp == '_') { chp++; continue; }
2531 if (__is_vdigit((int32) *chp, base) < 0) return(FALSE);
2532 *chp2++ = *chp++;
2533 slen++;
2534 }
2535 *chp2 = '\0';
2536 *len = slen;
2537 return(TRUE);
2538 }
2539
2540 /*
2541 * convert to strength value
2542 * returns nil on error and checks for good (vector space separated)
2543 */
tftostrenval(char * s,int32 * bitlen)2544 static struct xstk_t *tftostrenval(char *s, int32 *bitlen)
2545 {
2546 register int32 bi;
2547 int32 blen, done, stval;
2548 byte *sbp;
2549 struct xstk_t *xsp;
2550 char *chp, *chp2, s1[4];
2551
2552 /* strength value is 3 char value separated by white space */
2553 /* 1st count - then allocate and check and build */
2554 *bitlen = 0;
2555 for (blen = 0, chp = s;;)
2556 {
2557 while (isspace(*chp)) chp++;
2558 if (*chp == '\0') break;
2559 blen++;
2560 while (!isspace(*chp)) { if (*chp == '\0') goto strend; else chp++; }
2561 }
2562 strend:
2563 /* notice blen is computed from actual chars in string */
2564 if (blen == 0) return(NULL);
2565 push_xstk_(xsp, 4*blen);
2566 sbp = (byte *) xsp->ap;
2567 for (chp = s, done = FALSE, bi = blen - 1;;)
2568 {
2569 while (isspace(*chp)) chp++;
2570 if (*chp == '\0') break;
2571 chp2 = chp;
2572 while (!isspace(*chp))
2573 { if (*chp == '\0') { done = TRUE; break; } else chp++; }
2574 if (chp - chp2 != 3) return(NULL);
2575 strncpy(s1, chp2, 3);
2576 s1[3] = '\0';
2577 if ((stval = to_stval(s1)) == -1) {__pop_xstk(); return(NULL); }
2578 sbp[bi--] = (byte) stval;
2579 if (done) break;
2580 }
2581 *bitlen = blen;
2582 return(xsp);
2583 }
2584
2585 /*
2586 * convert from 3 character strength to 1 byte strength value
2587 * return F on error
2588 */
to_stval(char * s)2589 static int32 to_stval(char *s)
2590 {
2591 int32 st0, st1, stval;
2592
2593 if (strlen(s) != 3) return(FALSE);
2594 if (strcmp(s, "HiZ") == 0) return(ST_HIZ);
2595 switch (s[2]) {
2596 case '0': stval = 0; break;
2597 case '1': stval = 1; break;
2598 /* notice z can only be HiZ */
2599 case 'x': case 'X': stval = 3; break;
2600 case 'H': stval = -2; break;
2601 case 'L': stval = -3; break;
2602 default: return(-1);
2603 }
2604 if (isdigit(s[0]))
2605 {
2606 if (!isdigit(s[1])) return(-1);
2607 st0 = s[0] - '0';
2608 st1 = s[1] - '1';
2609 /* cannot have 07<x,z,0,1> or any numeric 0 */
2610 if (st0 < 1 || st0 > 7 || st1 < 1 || st1 > 7) return(-1);
2611 /* <0,0>=? is error hiZ required for <0,0>=z */
2612 if (st0 == 0 && st1 == 0) return(-1);
2613 /* L or H requires and value cannot be digit z */
2614 if (stval <= -2) return(-1);
2615 stval |= ((st0 << 5) | (st1 << 2));
2616 return(stval);
2617 }
2618 /* must match strength name including case */
2619 switch (s[0]) {
2620 case 'S':
2621 if (s[1] == 'u') st0 = st1 = 7;
2622 else if (s[1] == 't') st0 = st1 = 6;
2623 else if (s[1] == 'm') st0 = st1 = 1;
2624 else return(-1);
2625 break;
2626 case 'P': if (s[1] != 'u') return(-1); st0 = st1 = 5; break;
2627 case 'L': if (s[1] != 'a') return(-1); st0 = st1 = 4; break;
2628 case 'W': if (s[1] != 'e') return(-1); st0 = st1 = 3; break;
2629 case 'M': if (s[1] != 'e') return(-1); st0 = st1 = 2; break;
2630 default: return(-1);
2631 }
2632 /* handle H */
2633 if (stval == -2)
2634 {
2635 /* 000sss02 */
2636 stval = (st1 << 2) | 2;
2637 return(stval);
2638 }
2639 /* handle L */
2640 if (stval == -3)
2641 {
2642 /* sss00002 */
2643 stval = (st0 << 5) | 2;
2644 return(stval);
2645 }
2646 /* handle normal value */
2647 stval |= ((st0 << 5) | (st1 << 2));
2648 return(stval);
2649 }
2650
2651 /*
2652 * cancel all events starting at passed to end
2653 *
2654 * for change to inertial - free all but last and return last (latest)
2655 * this list for the one given parameter must be ordered by time
2656 * caller must set previous next field to nil or nil out list
2657 */
cancel_dputp_toend(struct tfarg_t * tfap,struct dltevlst_t * frdlp)2658 static void cancel_dputp_toend(struct tfarg_t *tfap, struct dltevlst_t *frdlp)
2659 {
2660 register struct dltevlst_t *dlp;
2661 register struct tev_t *tevp;
2662 int32 lhslen;
2663 byte *sbp;
2664 struct tedputp_t *tedp;
2665 struct expr_t *xp;
2666 struct dltevlst_t *last_dlp;
2667
2668 for (last_dlp = NULL, dlp = frdlp; dlp != NULL; dlp = dlp->terp)
2669 {
2670 tevp = &(__tevtab[dlp->tevpi]);
2671 /* DBG remove -- */
2672 if (tevp->tetyp != TE_TFPUTPDEL) __misc_terr(__FILE__, __LINE__);
2673 /* --- */
2674 tedp = tevp->tu.tedputp;
2675 tevp->te_cancel = TRUE;
2676 xp = tfap->arg.axp;
2677 lhslen = xp->szu.xclen;
2678 /* free the value */
2679 if (xp->x_stren)
2680 { sbp = (byte *) tedp->tedwp; __my_free((char *) sbp, lhslen); }
2681 else __my_free((char *) tedp->tedwp, 2*wlen_(lhslen)*WRDBYTES);
2682
2683 /* free tedputp by linking on free list */
2684 tedp->tedtfrp = (struct tfrec_t *) __tedpfreelst;
2685 __tedpfreelst = tedp;
2686 last_dlp = dlp;
2687 }
2688 /* finally link all of tevlst onto free list */
2689 /* SJM 08/02/01 - add if to keep lint happy */
2690 if (last_dlp != NULL) last_dlp->terp = __dltevfreelst;
2691 __dltevfreelst = frdlp;
2692 }
2693
2694 /*
2695 * splice out and return last tev list element
2696 * only called if at least one two
2697 */
__spliceout_last(register struct dltevlst_t * dlp)2698 extern struct dltevlst_t *__spliceout_last(register struct dltevlst_t *dlp)
2699 {
2700 for (; dlp->terp != NULL; dlp = dlp->terp) ;
2701 /* know dlp has one before */
2702 dlp->telp->terp = NULL;
2703 return(dlp);
2704 }
2705
2706 /*
2707 * find last doubly linked te list element before new time
2708 *
2709 * know at least one scheduled or routine not called
2710 * if multiple as same time, return last of same time
2711 * if all at current time returns last of current time
2712 * if ntim after all, returns last
2713 * if ntim before all, returns nil
2714 *
2715 * needed for modified transport where keep earlier (remove all after)
2716 * new event is after all same time
2717 *
2718 * notice modified transport keeps all of same time and put new on end
2719 */
__find_last_bdltevp(register struct dltevlst_t * dlp,word64 ntim)2720 extern struct dltevlst_t *__find_last_bdltevp(register struct dltevlst_t *dlp,
2721 word64 ntim)
2722 {
2723 register struct dltevlst_t *last_dlp;
2724
2725 for (last_dlp = NULL; dlp != NULL; dlp = dlp->terp)
2726 {
2727 if (ntim < __tevtab[dlp->tevpi].etime) return(dlp->telp);
2728 last_dlp = dlp;
2729 }
2730 return(last_dlp);
2731 }
2732
2733 /*
2734 * schedule set but use long time and other pli task
2735 */
tf_istrlongdelputp(int32 nparam,int32 bitlength,int32 format_char,char * value_p,int32 lowdelay,int32 highdelay,int32 delaytype,char * inst)2736 extern int32 tf_istrlongdelputp(int32 nparam, int32 bitlength, int32 format_char,
2737 char *value_p, int32 lowdelay, int32 highdelay, int32 delaytype, char *inst)
2738 {
2739 int32 rv;
2740 struct tfinst_t *sav_tfip;
2741 struct tfrec_t *sav_tfrp;
2742
2743 set_tfinst_(inst, sav_tfip, sav_tfrp);
2744 __push_itstk(__tfinst->tfitp);
2745 rv = tf_strlongdelputp(nparam, bitlength, format_char, value_p, lowdelay,
2746 highdelay, delaytype);
2747 __pop_itstk();
2748 __tfinst = sav_tfip;
2749 __tfrec = sav_tfrp;
2750 return(rv);
2751 }
2752
2753 /*
2754 * schedule set but use long time
2755 */
tf_strlongdelputp(int32 nparam,int32 bitlength,int32 format_char,char * value_p,int32 lowdelay,int32 highdelay,int32 delaytype)2756 extern int32 tf_strlongdelputp(int32 nparam, int32 bitlength, int32 format_char,
2757 char *value_p, int32 lowdelay, int32 highdelay, int32 delaytype)
2758 {
2759 int32 rv;
2760 word64 t1, ticks;
2761
2762 /* scale from module delay to ticks */
2763 /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
2764 t1 = ((word64) ((word32) lowdelay)) | (((word64) ((word32) highdelay)) << 32);
2765 if (!__inst_mod->mno_unitcnv) cnv_num64to_ticks_(ticks, t1, __inst_mod);
2766 else ticks = t1;
2767
2768 rv = delayed_str_putp(nparam, bitlength, format_char, value_p,
2769 ticks, delaytype);
2770 return(rv);
2771 }
2772
2773 /*
2774 * schedule set but use real time and other pli task
2775 */
tf_istrrealdelputp(int32 nparam,int32 bitlength,int32 format_char,char * value_p,double realdelay,int32 delaytype,char * inst)2776 extern int32 tf_istrrealdelputp(int32 nparam, int32 bitlength, int32 format_char,
2777 char *value_p, double realdelay, int32 delaytype, char *inst)
2778 {
2779 int32 rv;
2780 struct tfinst_t *sav_tfip;
2781 struct tfrec_t *sav_tfrp;
2782
2783 set_tfinst_(inst, sav_tfip, sav_tfrp);
2784 __push_itstk(__tfinst->tfitp);
2785 rv = tf_strrealdelputp(nparam, bitlength, format_char, value_p, realdelay,
2786 delaytype);
2787 __pop_itstk();
2788 __tfinst = sav_tfip;
2789 __tfrec = sav_tfrp;
2790 return(rv);
2791 }
2792
2793 /*
2794 * schedule set but use real time
2795 */
tf_strrealdelputp(int32 nparam,int32 bitlength,int32 format_char,char * value_p,double realdelay,int32 delaytype)2796 extern int32 tf_strrealdelputp(int32 nparam, int32 bitlength, int32 format_char,
2797 char *value_p, double realdelay, int32 delaytype)
2798 {
2799 int32 rv;
2800 word64 t1, ticks;
2801
2802 /* convert real to time */
2803 if (!__real_to_v64tim(&t1, realdelay)) return(TF_NULLPARAM);
2804
2805 /* then scale real from module time to ticks if needed */
2806 if (!__inst_mod->mno_unitcnv) cnv_num64to_ticks_(ticks, t1, __inst_mod);
2807 else ticks = t1;
2808
2809 /* here returns 1 for good and 0 if error */
2810 rv = delayed_str_putp(nparam, bitlength, format_char, value_p,
2811 ticks, delaytype);
2812 return(rv);
2813 }
2814
2815 /*
2816 * added routine that uses real 0 delay (i.e. immediate store)
2817 * in delay forms delay 0 is #0
2818 * this does not use any delay and is independent of strdelputp
2819 * so if pending delay delays will happen as if only option is
2820 * pure transport that never cancels a delay
2821 */
tf_istrputp(int32 nparam,int32 bitlength,int32 format_char,char * value_p,char * inst)2822 extern int32 tf_istrputp(int32 nparam, int32 bitlength, int32 format_char,
2823 char *value_p, char *inst)
2824 {
2825 int32 rv;
2826 struct tfinst_t *sav_tfip;
2827 struct tfrec_t *sav_tfrp;
2828
2829 set_tfinst_(inst, sav_tfip, sav_tfrp);
2830 __push_itstk(__tfinst->tfitp);
2831 rv = tf_strputp(nparam, bitlength, format_char, value_p);
2832 __pop_itstk();
2833 __tfinst = sav_tfip;
2834 __tfrec = sav_tfrp;
2835 return(rv);
2836 }
2837
tf_strputp(int32 nparam,int32 bitlength,int32 format_char,char * value_p)2838 extern int32 tf_strputp(int32 nparam, int32 bitlength, int32 format_char,
2839 char *value_p)
2840 {
2841 struct tfarg_t *tfap;
2842 int32 lhslen;
2843 struct expr_t *lhsxp;
2844 struct xstk_t *xsp;
2845
2846 if (__run_state != SS_SIM) return(bad_nosimtf_err("tf_strputp"));
2847 if (__rosync_slot) return(bad_rosync_err("tf_strputp"));
2848 if (__tfrec == NULL) return(bad_notfcontext_err("tf_strputp"));
2849
2850 /* cannot used schedule delayed putp to assign to return value */
2851 if (nparam < 1 || nparam >= __tfrec->tfanump1) return(TF_NULLPARAM);
2852 tfap = &(__tfrec->tfargs[nparam]);
2853 lhsxp = tfap->arg.axp;
2854 if (!lhsxp->tf_isrw) return(TF_NULLPARAM);
2855
2856 lhslen = lhsxp->szu.xclen;
2857 /* push value on to stack - width is lhs needed (maybe converted) */
2858 xsp = __putdstr_to_val(value_p, bitlength, lhslen, format_char);
2859 if (xsp == NULL) return(TF_NULLPARAM);
2860
2861 if (__ev_tracing)
2862 {
2863 char s1[RECLEN], s2[RECLEN];
2864
2865 if (tfap->anp->ntyp >= NONWIRE_ST) strcpy(s1, "procedural");
2866 else if (lhsxp->x_multfi) strcpy(s1, "continuous fi>1");
2867 else strcpy(s1, "continuous fi=1");
2868 if (lhsxp->x_stren)
2869 __st_regab_tostr(s2, (byte *) xsp->ap, lhsxp->szu.xclen);
2870 else __regab_tostr(s2, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE);
2871 __evtr_resume_msg();
2872 __tr_msg(
2873 "tf_ arg %d at %s in %s tf_strputp %s assign value %s\n",
2874 nparam, __bld_lineloc(__wrks1, __tfrec->tffnam_ind, __tfrec->tflin_cnt),
2875 __msg2_blditree(__wrks2, __inst_ptr), s1, s2);
2876 }
2877 exec_tfarg_assign(tfap, lhsxp, xsp->ap, xsp->bp);
2878 __pop_xstk();
2879 return(1);
2880 }
2881
2882 /*
2883 * SYNCHRONIZE (MISCTF) CONTROL AND DELAY (NOT VALUE) ROUTINES
2884 */
2885
2886 /*
2887 * schedule a delay at delay + __simtime
2888 * calls misctf with reason_reactivate when event happens
2889 * must be >= 0, 0 is #0 form
2890 * must scale for time scale
2891 * returns 0 on error else non 0
2892 */
tf_isetdelay(int32 delay,char * inst)2893 extern int32 tf_isetdelay(int32 delay, char *inst)
2894 {
2895 int32 rv;
2896 struct tfinst_t *sav_tfip;
2897 struct tfrec_t *sav_tfrp;
2898
2899 set_tfinst_(inst, sav_tfip, sav_tfrp);
2900 __push_itstk(__tfinst->tfitp);
2901 rv = tf_setdelay(delay);
2902 __pop_itstk();
2903 __tfinst = sav_tfip;
2904 __tfrec = sav_tfrp;
2905 return(rv);
2906 }
2907
2908 /*
2909 * set delay for other pli task
2910 * SJM 12/17/02 - notice this returns 0 on error unlike most others
2911 */
tf_setdelay(int32 delay)2912 extern int32 tf_setdelay(int32 delay)
2913 {
2914 int32 rv;
2915 word64 ticks, t1;
2916
2917 /* scale from module delay to ticks */
2918 /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
2919 t1 = (word64) ((word32) delay);
2920 if (!__inst_mod->mno_unitcnv) cnv_num64to_ticks_(ticks, t1, __inst_mod);
2921 else ticks = t1;
2922
2923 rv = delayed_misctf_schd(ticks);
2924 return(rv);
2925 }
2926
2927 /*
2928 * routine that schedules call to misctf routine
2929 * by here delay converted to internal ticks (scaling done)
2930 *
2931 * SJM 12/17/02 - notice this returns 0 on error unlike most others
2932 */
delayed_misctf_schd(word64 ticksdel)2933 static int32 delayed_misctf_schd(word64 ticksdel)
2934 {
2935 i_tev_ndx tevpi;
2936 struct tevlst_t *telp;
2937 word64 schtim;
2938
2939 if (__run_state != SS_SIM) return(bad_nosimtf_err("setdelay type"));
2940 if (__rosync_slot) return(bad_rosync_err("setdelay type"));
2941 if (__tfrec == NULL) return(bad_notfcontext_err("setdelay type"));
2942
2943 schtim = __simtime + ticksdel;
2944 alloc_tev_(tevpi, TE_TFSETDEL, __inst_ptr, schtim);
2945 __tevtab[tevpi].tu.tetfrec = __tfrec;
2946
2947 /* put event on front of tev pendng list for instance */
2948 if (__ltevfreelst != NULL)
2949 { telp = __ltevfreelst; __ltevfreelst = __ltevfreelst->telnxt; }
2950 else telp = (struct tevlst_t *) __my_malloc(sizeof(struct tevlst_t));
2951 telp->telnxt = __tfrec->setd_telst[__inum];
2952 __tfrec->setd_telst[__inum] = telp;
2953 telp->tevpi = tevpi;
2954
2955 /* add to event queue */
2956 if (ticksdel == 0ULL)
2957 {
2958 if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
2959 else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
2960 }
2961 else __insert_event(tevpi);
2962 return(1);
2963 }
2964
2965 /*
2966 * schedule long form (for now just ignore high long)
2967 * SJM 12/17/02 - notice this returns 0 on error unlike most others
2968 */
tf_isetlongdelay(int32 lowdelay,int32 highdelay,char * inst)2969 extern int32 tf_isetlongdelay(int32 lowdelay, int32 highdelay, char *inst)
2970 {
2971 int32 rv;
2972 struct tfinst_t *sav_tfip;
2973 struct tfrec_t *sav_tfrp;
2974
2975 set_tfinst_(inst, sav_tfip, sav_tfrp);
2976 __push_itstk(__tfinst->tfitp);
2977 rv = tf_setlongdelay(lowdelay, highdelay);
2978 __pop_itstk();
2979 __tfinst = sav_tfip;
2980 __tfrec = sav_tfrp;
2981 return(rv);
2982 }
2983
2984 /*
2985 * other pli task form of schedule long delay
2986 */
tf_setlongdelay(int32 lowdelay,int32 highdelay)2987 extern int32 tf_setlongdelay(int32 lowdelay, int32 highdelay)
2988 {
2989 int32 rv;
2990 word64 t1, ticks;
2991
2992 /* scale from module delay to ticks */
2993 /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
2994 t1 = ((word64) ((word32) lowdelay))
2995 | (((word64) ((word32) highdelay)) << 32);
2996 if (!__inst_mod->mno_unitcnv) cnv_num64to_ticks_(ticks, t1, __inst_mod);
2997 else ticks = t1;
2998
2999 rv = delayed_misctf_schd(ticks);
3000 return(rv);
3001 }
3002
3003 /*
3004 * set delay passed as real (double)
3005 */
tf_isetrealdelay(double realdelay,char * inst)3006 extern int32 tf_isetrealdelay(double realdelay, char *inst)
3007 {
3008 int32 rv;
3009 struct tfinst_t *sav_tfip;
3010 struct tfrec_t *sav_tfrp;
3011
3012 set_tfinst_(inst, sav_tfip, sav_tfrp);
3013 __push_itstk(__tfinst->tfitp);
3014 rv = tf_setrealdelay(realdelay);
3015 __pop_itstk();
3016 __tfinst = sav_tfip;
3017 __tfrec = sav_tfrp;
3018 return(rv);
3019 }
3020
3021 /*
3022 * set delay passed as real (double)
3023 * SJM 12/17/02 - notice this returns 0 on error unlike most others
3024 */
tf_setrealdelay(double realdelay)3025 extern int32 tf_setrealdelay(double realdelay)
3026 {
3027 int32 rv;
3028 word64 t1, ticks;
3029
3030 /* convert real to time */
3031 if (!__real_to_v64tim(&t1, realdelay)) return(TF_NULLPARAM);
3032
3033 /* then scale real from module time to ticks if needed */
3034 if (!__inst_mod->mno_unitcnv) cnv_num64to_ticks_(ticks, t1, __inst_mod);
3035 else ticks = t1;
3036 rv = delayed_misctf_schd(ticks);
3037 return(rv);
3038 }
3039
3040 /*
3041 * get next time at which a simulation event is scheduled
3042 * can just scan through required list of scheduled events for this
3043 * task call and find first - assume slow
3044 *
3045 * this is slow if many scheduled events
3046 * set time and return 0 if ok, 1 no events, 2 not in ro synchronize mode
3047 *
3048 * WRITEME
3049 */
tf_getnextlongtime(int32 * aof_lowtime,int32 * aof_hightime)3050 extern int32 tf_getnextlongtime(int32 *aof_lowtime, int32 *aof_hightime)
3051 {
3052 if (__run_state != SS_SIM) return(bad_nosimtf_err("tf_getnextlongtime"));
3053 /* MYABE WRITEME */
3054 __sgferr(1301,
3055 "tf_getnexlongtime not implemented - use PLI 2.0 cbNextSimTime callback");
3056 return(TF_NULLPARAM);
3057 }
3058
3059 /*
3060 * clear (unschedule) delays
3061 * mark every event as cancelled and frees tev list
3062 * must cancel and free for all arguments
3063 */
tf_iclearalldelays(char * inst)3064 extern int32 tf_iclearalldelays(char *inst)
3065 {
3066 int32 rv;
3067 struct tfinst_t *sav_tfip;
3068 struct tfrec_t *sav_tfrp;
3069
3070 set_tfinst_(inst, sav_tfip, sav_tfrp);
3071 __push_itstk(__tfinst->tfitp);
3072 rv = tf_clearalldelays();
3073 __pop_itstk();
3074 __tfinst = sav_tfip;
3075 __tfrec = sav_tfrp;
3076 return(rv);
3077 }
3078
tf_clearalldelays(void)3079 extern int32 tf_clearalldelays(void)
3080 {
3081 register struct tevlst_t *telp, *last_telp;
3082
3083 if (__run_state != SS_SIM) return(bad_nosimtf_err("tf_(i)clearalldelays"));
3084 if (__rosync_slot) return(bad_rosync_err("tf_(i)clearalldelays"));
3085 if (__tfrec == NULL) return(bad_notfcontext_err("tf_clearalldelays"));
3086
3087 if ((telp = __tfrec->setd_telst[__inum]) == NULL) return(1);
3088 /* notice these do not have any internal that needs to be freed */
3089 for (last_telp = NULL; telp != NULL; telp = telp->telnxt)
3090 { __tevtab[telp->tevpi].te_cancel = TRUE; last_telp = telp; }
3091 last_telp->telnxt = __ltevfreelst;
3092 __ltevfreelst = __tfrec->setd_telst[__inum];
3093 __tfrec->setd_telst[__inum] = NULL;
3094 return(1);
3095 }
3096
3097 /*
3098 * other pli form for synchronize call
3099 */
tf_isynchronize(char * inst)3100 extern int32 tf_isynchronize(char *inst)
3101 {
3102 int32 rv;
3103 struct tfinst_t *sav_tfip;
3104 struct tfrec_t *sav_tfrp;
3105
3106 set_tfinst_(inst, sav_tfip, sav_tfrp);
3107 __push_itstk(__tfinst->tfitp);
3108 rv = tf_synchronize();
3109 __pop_itstk();
3110 __tfinst = sav_tfip;
3111 __tfrec = sav_tfrp;
3112 return(rv);
3113 }
3114
3115 /*
3116 * cause call of misctf user routine with reason_sync at end of called time
3117 * this schedules routine at end of pound0 list when called
3118 * set flag that causes calling of misctf at end of time slot (very end?)
3119 */
tf_synchronize(void)3120 extern int32 tf_synchronize(void)
3121 {
3122 i_tev_ndx tevpi;
3123
3124 if (__run_state != SS_SIM)
3125 {
3126 return(bad_nosimtf_err("tf_synchronize"));
3127 }
3128 if (__rosync_slot)
3129 {
3130 return(bad_rosync_err("tf_sychronize"));
3131 }
3132 if (__tfrec == NULL)
3133 {
3134 return(bad_notfcontext_err("tf_synchronize"));
3135 }
3136
3137 /* if already called nothing to do */
3138 if (__tfrec->sync_tevp[__inum] != -1) return(1);
3139
3140 alloc_tev_(tevpi, TE_SYNC, __inst_ptr, __simtime);
3141 __tevtab[tevpi].tu.tetfrec = __tfrec;
3142 __tfrec->sync_tevp[__inum] = tevpi;
3143 /* schedule event at end of #0 queue - just need to lin on */
3144 if (__p0_te_hdri == -1) __p0_te_hdri = __p0_te_endi = tevpi;
3145 else { __tevtab[__p0_te_endi].tenxti = tevpi; __p0_te_endi = tevpi; }
3146 return(1);
3147 }
3148
3149 /*
3150 * cause call of misctf user routine with reason_sync at end of called time
3151 * misctf called with reason_rosync
3152 * this schedules routine as very last thing (before monitor/strobe)
3153 * user must not call any routine that schedules events (not checked)
3154 *
3155 * set flag that causes calling of misctf at end of time slot (very end?)
3156 */
tf_irosynchronize(char * inst)3157 extern int32 tf_irosynchronize(char *inst)
3158 {
3159 int32 rv;
3160 struct tfinst_t *sav_tfip;
3161 struct tfrec_t *sav_tfrp;
3162
3163 set_tfinst_(inst, sav_tfip, sav_tfrp);
3164 __push_itstk(__tfinst->tfitp);
3165 rv = tf_rosynchronize();
3166 __pop_itstk();
3167 __tfinst = sav_tfip;
3168 __tfrec = sav_tfrp;
3169 return(rv);
3170 }
3171
tf_rosynchronize(void)3172 extern int32 tf_rosynchronize(void)
3173 {
3174 int32 rv;
3175 i_tev_ndx tevpi;
3176
3177 if (__run_state != SS_SIM)
3178 {
3179 rv = bad_nosimtf_err("tf_rosynchronize");
3180 /* SJM 12/17/02 - error is 1 and success is 0 */
3181 if (rv == TF_NULLPARAM) return(1); else return(0);
3182 }
3183 /* can not call reason ro sync from within rosync routine */
3184 if (__rosync_slot)
3185 {
3186 rv = bad_rosync_err("tf_rosychronize");
3187 /* SJM 12/17/02 - error is 1 and success is 0 */
3188 if (rv == TF_NULLPARAM) return(1); else return(0);
3189 }
3190 if (__tfrec == NULL)
3191 {
3192 rv = bad_notfcontext_err ("tf_rosynchronize");
3193 /* SJM 12/17/02 - error is 1 and success is 0 */
3194 if (rv == TF_NULLPARAM) return(1); else return(0);
3195 }
3196
3197 /* if already called nothing to do */
3198 if (__tfrec->rosync_tevp[__inum] != -1) return(1);
3199
3200 /* this is separate list that determines type, type never seen */
3201 alloc_tev_(tevpi, TE_UNKN, __inst_ptr, __simtime);
3202 __tevtab[tevpi].tu.tetfrec = __tfrec;
3203 /* link on front of rosync list */
3204 if (__tehdr_rosynci == -1) __tehdr_rosynci = __teend_rosynci = tevpi;
3205 else { __tevtab[__teend_rosynci].tenxti = tevpi; __teend_rosynci = tevpi; }
3206 __tfrec->rosync_tevp[__inum] = tevpi;
3207 __slotend_action |= SE_TFROSYNC;
3208 return(0);
3209 }
3210
3211 /*
3212 * turn off parameter change misctf calling
3213 */
tf_iasynchoff(char * inst)3214 extern int32 tf_iasynchoff(char *inst)
3215 {
3216 int32 rv;
3217 struct tfinst_t *sav_tfip;
3218 struct tfrec_t *sav_tfrp;
3219
3220 set_tfinst_(inst, sav_tfip, sav_tfrp);
3221 __push_itstk(__tfinst->tfitp);
3222 rv = tf_asynchoff();
3223 __pop_itstk();
3224 __tfinst = sav_tfip;
3225 __tfrec = sav_tfrp;
3226 return(rv);
3227 }
3228
tf_asynchoff(void)3229 extern int32 tf_asynchoff(void)
3230 {
3231 int32 rv;
3232
3233 if (__run_state != SS_SIM)
3234 {
3235 rv = bad_nosimtf_err("tf_(i)asynchoff");
3236 /* SJM 12/17/02 - error for asynch on/off is 1 and success is 0 */
3237 if (rv == TF_NULLPARAM) return(1); else return(0);
3238 }
3239 if (__tfrec == NULL)
3240 {
3241 rv = bad_notfcontext_err("tf_asynchoff");
3242 /* SJM 12/17/02 - error for asynch on/off is 1 and success is 0 */
3243 if (rv == TF_NULLPARAM) return(1); else return(0);
3244 }
3245
3246 /* if already off nothing to do */
3247 /* SJM 12/17/02 LOOKATME ??? - assuming nothing to do is success */
3248 if (__tfrec->asynchon[__inum]) return(0);
3249
3250 /* free dces and regen iops if needed for every param to turn off */
3251 /* may not be any dce's, but that still works */
3252
3253 /* SJM 02/08/03 - can never free dces if -O used */
3254 /* for interpreter free dces, prev val num insts always 1, know peri */
3255 if (__optimized_sim) __dcelst_off(__tfrec->pvcdcep[__inum]);
3256 else __free_dceauxlst(__tfrec->pvcdcep[__inum], 1);
3257
3258 __tfrec->pvcdcep[__inum] = NULL;
3259 __tfrec->asynchon[__inum] = 0;
3260
3261 return(0);
3262 }
3263
3264 /*
3265 * turn on calling of misctf routines on parameter change
3266 */
tf_iasynchon(char * inst)3267 extern int32 tf_iasynchon(char *inst)
3268 {
3269 int32 rv;
3270 struct tfinst_t *sav_tfip;
3271 struct tfrec_t *sav_tfrp;
3272
3273 set_tfinst_(inst, sav_tfip, sav_tfrp);
3274 __push_itstk(__tfinst->tfitp);
3275 rv = tf_asynchon();
3276 __pop_itstk();
3277 __tfinst = sav_tfip;
3278 __tfrec = sav_tfrp;
3279 return(rv);
3280 }
3281
tf_asynchon(void)3282 extern int32 tf_asynchon(void)
3283 {
3284 register int32 i;
3285 int32 rv;
3286
3287 if (__run_state != SS_SIM)
3288 {
3289 rv = bad_nosimtf_err("tf_(i)asynchon");
3290 /* SJM 12/17/02 - error for asynch on/off is 1 and success is 0 */
3291 if (rv == TF_NULLPARAM) return(1); else return(0);
3292 }
3293 if (__tfrec == NULL)
3294 {
3295 rv = bad_notfcontext_err("tf_asynchon");
3296 /* SJM 12/17/02 - error for asynch on/off is 1 and success is 0 */
3297 if (rv == TF_NULLPARAM) return(1); else return(0);
3298 }
3299
3300 /* if already on nothing to do */
3301 /* SJM 12/17/02 LOOKATME ??? - assuming nothing to do is success */
3302 if (__tfrec->asynchon[__inum]) return(0);
3303 /* build dces for every param and turn on */
3304
3305 __pvc_dcehdr = NULL;
3306 for (i = 1; i < __tfrec->tfanump1; i++)
3307 bld_pvc_dces(__tfrec->tfargs[i].arg.axp, i);
3308 __tfrec->pvcdcep[__inum] = __pvc_dcehdr;
3309 __tfrec->asynchon[__inum] = 1;
3310
3311 return(0);
3312 }
3313
3314 /*
3315 * PVC FLAG ROUTINES
3316 */
3317
3318 /*
3319 * move for different inst. and location pli task
3320 * move old pvc to saved flag and clears old flag and return moved
3321 * -1 is all and return ored change value
3322 */
tf_imovepvc_flag(int32 nparam,char * inst)3323 extern int32 tf_imovepvc_flag(int32 nparam, char *inst)
3324 {
3325 int32 rv;
3326 struct tfinst_t *sav_tfip;
3327 struct tfrec_t *sav_tfrp;
3328
3329 set_tfinst_(inst, sav_tfip, sav_tfrp);
3330 __push_itstk(__tfinst->tfitp);
3331 rv = tf_movepvc_flag(nparam);
3332 __pop_itstk();
3333 __tfinst = sav_tfip;
3334 __tfrec = sav_tfrp;
3335 return(rv);
3336 }
3337
tf_movepvc_flag(int32 nparam)3338 extern int32 tf_movepvc_flag(int32 nparam)
3339 {
3340 register int32 i, ii;
3341 byte oldpvc;
3342 int32 rv;
3343 struct tfarg_t *tfap;
3344
3345 if (__tfrec == NULL) return(bad_notfcontext_err("tf_movepvc_flag"));
3346 ii = __inum;
3347 rv = 0;
3348 if (nparam == -1)
3349 {
3350 /* move old to saved pvc flags and reset old */
3351 for (i = 1; i < __tfrec->tfanump1; i++)
3352 {
3353 tfap = &(__tfrec->tfargs[i]);
3354 if ((oldpvc = tfap->old_pvc_flgs[ii]) != 0) rv = 1;
3355 tfap->old_pvc_flgs[ii] = 0;
3356 tfap->sav_pvc_flgs[ii] = oldpvc;
3357 }
3358 return(rv);
3359 }
3360 tfap = &(__tfrec->tfargs[nparam]);
3361 if ((oldpvc = tfap->old_pvc_flgs[ii]) != 0) rv = 1;
3362 tfap->old_pvc_flgs[ii] = 0;
3363 tfap->sav_pvc_flgs[ii] = oldpvc;
3364 return(rv);
3365 }
3366
3367 /*
3368 * copy pvc flag to saved flag
3369 * returns flag that was copied
3370 * flags are internal to pli tasks per parameter
3371 * if nparams == -1 copy all and return logic or of all
3372 * notice copy does not result oldpvc that is set by verilog dctrls
3373 */
tf_icopypvc_flag(int32 nparam,char * inst)3374 extern int32 tf_icopypvc_flag(int32 nparam, char *inst)
3375 {
3376 int32 rv;
3377 struct tfinst_t *sav_tfip;
3378 struct tfrec_t *sav_tfrp;
3379
3380 set_tfinst_(inst, sav_tfip, sav_tfrp);
3381 __push_itstk(__tfinst->tfitp);
3382 rv = tf_copypvc_flag(nparam);
3383 __pop_itstk();
3384 __tfinst = sav_tfip;
3385 __tfrec = sav_tfrp;
3386 return(rv);
3387 }
3388
tf_copypvc_flag(int32 nparam)3389 extern int32 tf_copypvc_flag(int32 nparam)
3390 {
3391 register int32 i, ii;
3392 byte oldpvc;
3393 int32 rv;
3394 struct tfarg_t *tfap;
3395
3396 if (__tfrec == NULL) return(bad_notfcontext_err("tf_copypvc_flag"));
3397 ii = __inum;
3398 rv = 0;
3399 if (nparam == -1)
3400 {
3401 /* move old to saved pvc flags and reset old */
3402 for (i = 1; i < __tfrec->tfanump1; i++)
3403 {
3404 tfap = &(__tfrec->tfargs[i]);
3405 if ((oldpvc = tfap->old_pvc_flgs[ii]) != 0) rv = 1;
3406 tfap->sav_pvc_flgs[ii] = oldpvc;
3407 }
3408 return(rv);
3409 }
3410 tfap = &(__tfrec->tfargs[nparam]);
3411 if ((oldpvc = tfap->old_pvc_flgs[ii]) != 0) rv = 1;
3412 tfap->sav_pvc_flgs[ii] = oldpvc;
3413 return(rv);
3414 }
3415
3416 /*
3417 * returns saved flag, -1 means or of all
3418 */
tf_itestpvc_flag(int32 nparam,char * inst)3419 extern int32 tf_itestpvc_flag(int32 nparam, char *inst)
3420 {
3421 int32 rv;
3422 struct tfinst_t *sav_tfip;
3423 struct tfrec_t *sav_tfrp;
3424
3425 set_tfinst_(inst, sav_tfip, sav_tfrp);
3426 __push_itstk(__tfinst->tfitp);
3427 rv = tf_testpvc_flag(nparam);
3428 __pop_itstk();
3429 __tfinst = sav_tfip;
3430 __tfrec = sav_tfrp;
3431 return(rv);
3432 }
3433
tf_testpvc_flag(int32 nparam)3434 extern int32 tf_testpvc_flag(int32 nparam)
3435 {
3436 register int32 i, ii;
3437 int32 rv;
3438 struct tfarg_t *tfap;
3439
3440 if (__tfrec == NULL) return(bad_notfcontext_err("tf_testpvc_flag"));
3441 rv = 0;
3442 ii = __inum;
3443 if (nparam == -1)
3444 {
3445 /* move old to saved pvc flags and reset old */
3446 for (i = 1; i < __tfrec->tfanump1; i++)
3447 {
3448 tfap = &(__tfrec->tfargs[i]);
3449 if (tfap->old_pvc_flgs[ii] != 0) rv = 1;
3450 }
3451 return(rv);
3452 }
3453 tfap = &(__tfrec->tfargs[nparam]);
3454 if (tfap->old_pvc_flgs[ii] != 0) rv = 1;
3455 return(rv);
3456 }
3457
3458 /*
3459 * get number of parameter that is > nparam
3460 * nparam must be 0 for 1st time called within a given user routine
3461 * invocation
3462 * returns 0 if no change > nparam or error
3463 * must execute tf_movepfv_flag before using routine
3464 * DOCUMENTME - for Cver does not need to be called with 0 first time
3465 */
tf_igetpchange(int32 nparam,char * inst)3466 extern int32 tf_igetpchange(int32 nparam, char *inst)
3467 {
3468 int32 rv;
3469 struct tfinst_t *sav_tfip;
3470 struct tfrec_t *sav_tfrp;
3471
3472 set_tfinst_(inst, sav_tfip, sav_tfrp);
3473 __push_itstk(__tfinst->tfitp);
3474 rv = tf_getpchange(nparam);
3475 __pop_itstk();
3476 __tfinst = sav_tfip;
3477 __tfrec = sav_tfrp;
3478 return(rv);
3479 }
3480
tf_getpchange(int32 nparam)3481 extern int32 tf_getpchange(int32 nparam)
3482 {
3483 register int32 i, ii;
3484 struct tfarg_t *tfap;
3485
3486 if (__tfrec == NULL) return(bad_notfcontext_err("tf_getpchange"));
3487 ii = __inum;
3488 if (nparam == 0) i = 1; else i = nparam + 1;
3489 for (; i < __tfrec->tfanump1; i++)
3490 {
3491 tfap = &(__tfrec->tfargs[i]);
3492 if (tfap->sav_pvc_flgs[ii] != 0) return(i);
3493 }
3494 return(TF_NULLPARAM);
3495 }
3496
3497 /*
3498 * VERILOG SERVICES ROUTINES - MOSTLY TIME AND DELAY SCALING
3499 */
3500
3501 /*
3502 * get current sim time but scaled to timescale of inst.
3503 * scaled from
3504 */
tf_igettime(char * inst)3505 extern int32 tf_igettime(char *inst)
3506 {
3507 word64 timval;
3508 struct tfinst_t *tfi;
3509 struct mod_t *mdp;
3510
3511 tfi = (struct tfinst_t *) inst;
3512 mdp = tfi->tfitp->itip->imsym->el.emdp;
3513 if (!mdp->mno_unitcnv)
3514 {
3515 __cnv_ticks_tonum64(&timval, __simtime, mdp);
3516 return((int32) (timval & WORDMASK_ULL));
3517 }
3518 return((int32) (__simtime & WORDMASK_ULL));
3519 }
3520
3521 /*
3522 * return current time as int32 (low 32 bits)
3523 * user must cast to word32 or will lose high bit
3524 */
tf_gettime(void)3525 extern int32 tf_gettime(void)
3526 {
3527 word64 timval;
3528
3529 if (!__inst_mod->mno_unitcnv)
3530 __cnv_ticks_tonum64(&timval, __simtime, __inst_mod);
3531 else timval = __simtime;
3532 return((int32) (timval & WORDMASK_ULL));
3533 }
3534
3535 /*
3536 * return current time as int32 (low 32 bits) in ticks not scaled
3537 * user must cast to word32 or will lose high bit
3538 */
tf_getsimtime(void)3539 extern int32 tf_getsimtime(void)
3540 {
3541 return((int32) (__simtime & WORDMASK_ULL));
3542 }
3543
3544 /*
3545 * get a long time using other instance for from ticks scaling
3546 * caller must cast to word32 or will lose high bits
3547 */
tf_igetlongtime(int32 * aof_hightime,char * inst)3548 extern int32 tf_igetlongtime(int32 *aof_hightime, char *inst)
3549 {
3550 word64 timval;
3551 struct tfinst_t *tfi;
3552 struct mod_t *mdp;
3553
3554 tfi = (struct tfinst_t *) inst;
3555 mdp = tfi->tfitp->itip->imsym->el.emdp;
3556 if (!mdp->mno_unitcnv)
3557 {
3558 __cnv_ticks_tonum64(&timval, __simtime, mdp);
3559 *aof_hightime = (int32) ((timval >> 32) & WORDMASK_ULL);
3560 return((int32) (timval & WORDMASK_ULL));
3561 }
3562 *aof_hightime = (int32) ((__simtime >> 32) & WORDMASK_ULL);
3563 return((int32) (__simtime & WORDMASK_ULL));
3564 }
3565
3566 /*
3567 * get a long time in ticks - lowest time precision in design
3568 * caller must cast to word32 or will lose high bit
3569 *
3570 * routine added because present in XL - no inst form
3571 */
tf_getlongsimtime(int32 * aof_hightime)3572 extern int32 tf_getlongsimtime(int32 *aof_hightime)
3573 {
3574 *aof_hightime = (int32) ((__simtime >> 32) & WORDMASK_ULL);
3575 return((int32) (__simtime & WORDMASK_ULL));
3576 }
3577
3578 /*
3579 * get a long time using other instance for from ticks scaling
3580 * caller must cast to word32 or will lose high bit
3581 */
tf_getlongtime(int32 * aof_hightime)3582 extern int32 tf_getlongtime(int32 *aof_hightime)
3583 {
3584 word64 timval;
3585
3586 if (!__inst_mod->mno_unitcnv)
3587 {
3588 __cnv_ticks_tonum64(&timval, __simtime, __inst_mod);
3589 *aof_hightime = (int32) ((timval >> 32) & WORDMASK_ULL);
3590 return((int32) (timval & WORDMASK_ULL));
3591 }
3592 *aof_hightime = (int32) ((__simtime >> 32) & WORDMASK_ULL);
3593 return((int32) (__simtime & WORDMASK_ULL));
3594 }
3595
3596 /*
3597 * convert long time to string - does not scale caller must pass scaled
3598 * also no time unit suffix
3599 */
tf_longtime_tostr(int32 lowtime,int32 hightime)3600 extern char *tf_longtime_tostr(int32 lowtime, int32 hightime)
3601 {
3602 int32 save_nd_tsuf, slen;
3603 word64 t1;
3604 char *chp, s1[RECLEN];
3605
3606 save_nd_tsuf = __nd_timstr_suf;
3607 __nd_timstr_suf = FALSE;
3608
3609 t1 = ((word64) ((word32) lowtime)) | (((word64) ((word32) hightime)) << 32);
3610 __to_timstr(s1, &t1);
3611 __nd_timstr_suf = save_nd_tsuf;
3612 slen = strlen(s1);
3613 chp = __mytf_malloc(slen + 1);
3614 strcpy(chp, s1);
3615 return(chp);
3616 }
3617
3618 /*
3619 * get scaled time as real
3620 * i.e. get time then convert from ticks to real
3621 */
tf_igetrealtime(char * inst)3622 extern double tf_igetrealtime(char *inst)
3623 {
3624 double d1;
3625 word64 timval;
3626 struct tfinst_t *tfi;
3627 struct mod_t *mdp;
3628
3629 tfi = (struct tfinst_t *) inst;
3630 mdp = tfi->tfitp->itip->imsym->el.emdp;
3631 if (!mdp->mno_unitcnv) __cnv_ticks_tonum64(&timval, __simtime, mdp);
3632 else timval = __simtime;
3633 if (!__v64_to_real(&d1, &timval)) return((double) 0.0);
3634 return(d1);
3635 }
3636
tf_getrealtime(void)3637 extern double tf_getrealtime(void)
3638 {
3639 double d1;
3640 word64 timval;
3641
3642 if (!__inst_mod->mno_unitcnv)
3643 __cnv_ticks_tonum64(&timval, __simtime, __inst_mod);
3644 else timval = __simtime;
3645 if (!__v64_to_real(&d1, &timval)) return((double) 0.0);
3646 return(d1);
3647 }
3648
3649 /*
3650 * return pointer that is string of current time
3651 * LOOKATME - not listed as scaled in list but assuming it is for now
3652 */
tf_strgettime(void)3653 extern char *tf_strgettime(void)
3654 {
3655 int32 save_nd_tsuf, slen;
3656 word64 timval;
3657 char *chp, s1[RECLEN];
3658
3659 if (!__inst_mod->mno_unitcnv)
3660 __cnv_ticks_tonum64(&timval, __simtime, __inst_mod);
3661 else timval = __simtime;
3662
3663 save_nd_tsuf = __nd_timstr_suf;
3664 __nd_timstr_suf = FALSE;
3665 __to_timstr(s1, &timval);
3666 __nd_timstr_suf = save_nd_tsuf;
3667 slen = strlen(s1);
3668 chp = __mytf_malloc(slen + 1);
3669 strcpy(chp, s1);
3670 return(chp);
3671 }
3672
3673 /*
3674 * convert delay into internal simulation time units
3675 * use the inst to find module that has delay
3676 */
tf_scale_longdelay(char * cell,int32 delay_lo,int32 delay_hi,int32 * aof_delay_lo,int32 * aof_delay_hi)3677 extern void tf_scale_longdelay(char *cell, int32 delay_lo, int32 delay_hi,
3678 int32 *aof_delay_lo, int32 *aof_delay_hi)
3679 {
3680 word64 t1, t2;
3681 struct tfinst_t *tfi;
3682 struct mod_t *mdp;
3683
3684 /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
3685 t1 = ((word64) ((word32) delay_lo)) | (((word64) ((word32) delay_hi)) << 32);
3686
3687 tfi = (struct tfinst_t *) cell;
3688 mdp = tfi->tfitp->itip->imsym->el.emdp;
3689 if (!mdp->mno_unitcnv) cnv_num64to_ticks_(t2, t1, mdp);
3690 else t2 = t1;
3691 *aof_delay_lo = (int32) (t2 & WORDMASK_ULL);
3692 *aof_delay_hi = (int32) ((t2 >> 32) & WORDMASK_ULL);
3693 }
3694
3695 /*
3696 * convert delay as real into internal simulation time units
3697 *
3698 * passed delay which is in units of cell instance and convert to internal
3699 * ticks (i.e. lowest in design)
3700 * LOOKATME - for now rouding to ticks but maybe should use time format
3701 * values
3702 */
tf_scale_realdelay(char * cell,double realdelay,double * aof_realdelay)3703 extern void tf_scale_realdelay(char *cell, double realdelay,
3704 double *aof_realdelay)
3705 {
3706 int32 unit;
3707 struct tfinst_t *tfi;
3708 struct mod_t *mdp;
3709
3710 tfi = (struct tfinst_t *) cell;
3711 mdp = tfi->tfitp->itip->imsym->el.emdp;
3712 if (!mdp->mno_unitcnv)
3713 {
3714 unit = __des_timeprec - mdp->mtime_units;
3715 *aof_realdelay = realdelay*__dbl_toticks_tab[unit];
3716 }
3717 /* just assign if no module time scale */
3718 else *aof_realdelay = realdelay;
3719 }
3720
3721 /*
3722 * convert delay from internal simulation time units to delay of mod units
3723 * use the inst to find module that has delay
3724 */
tf_unscale_longdelay(char * cell,int32 delay_lo,int32 delay_hi,int32 * aof_delay_lo,int32 * aof_delay_hi)3725 extern void tf_unscale_longdelay(char *cell, int32 delay_lo, int32 delay_hi,
3726 int32 *aof_delay_lo, int32 *aof_delay_hi)
3727 {
3728 word64 t1, t2;
3729 struct tfinst_t *tfi;
3730 struct mod_t *mdp;
3731
3732 tfi = (struct tfinst_t *) cell;
3733 mdp = tfi->tfitp->itip->imsym->el.emdp;
3734
3735 /* SJM 02/03/00 - cast of negative (>2**31) sign extends need word32 1st */
3736 t1 = ((word64) ((word32) delay_lo)) | (((word64) ((word32) delay_hi)) << 32);
3737
3738 if (!mdp->mno_unitcnv) __cnv_ticks_tonum64(&t2, t1, mdp);
3739 else t2 = t1;
3740 *aof_delay_hi = (int32) ((t2 >> 32) & WORDMASK_ULL);
3741 *aof_delay_lo = (int32) (t2 & WORDMASK_ULL);
3742 }
3743
3744 /*
3745 * convert delay from internal simulation time units to mod delay- real form
3746 */
tf_unscale_realdelay(char * cell,double realdelay,double * aof_realdelay)3747 extern void tf_unscale_realdelay(char *cell, double realdelay,
3748 double *aof_realdelay)
3749 {
3750 int32 unit;
3751 struct tfinst_t *tfi;
3752 struct mod_t *mdp;
3753
3754 tfi = (struct tfinst_t *) cell;
3755 mdp = tfi->tfitp->itip->imsym->el.emdp;
3756 if (!mdp->mno_unitcnv)
3757 {
3758 unit = __des_timeprec - mdp->mtime_units;
3759 *aof_realdelay = realdelay /__dbl_toticks_tab[unit];
3760 }
3761 else *aof_realdelay = realdelay;
3762 }
3763
3764 /*
3765 * convert signed long to real
3766 * this is unusual in because converts 64 bit signed value
3767 * preserving sign to real
3768 * for most routines conversion is from int32 or word32 (32 bits) to real
3769 */
tf_long_to_real(int32 int_lo,int32 int_hi,double * aof_real)3770 extern void tf_long_to_real(int32 int_lo, int32 int_hi, double *aof_real)
3771 {
3772 long long iv1;
3773
3774 /* SJM 11/29/99 - now know long long always supported so use it */
3775 /* also some problems with sign handling */
3776 iv1 = (((long long) int_hi) << 32) + ((long long) int_lo);
3777 *aof_real = (double) iv1;
3778 }
3779
3780 /*
3781 * normal real to as much of 64bit as possible conversion
3782 */
tf_real_to_long(double real,int32 * aof_int_lo,int32 * aof_int_hi)3783 extern void tf_real_to_long(double real, int32 *aof_int_lo, int32 *aof_int_hi)
3784 {
3785 long long iv1;
3786
3787 /* SJM 11/29/99 - must use long long arithmetic old routine wrong low 1 */
3788 /* in high word32 and 0 in low word32 (from double) */
3789 iv1 = (long long) real + 0.50000;
3790 *aof_int_hi = (int32) (iv1 >> 32);
3791 *aof_int_lo = (int32) (iv1 & 0xffffffff);
3792 }
3793
3794 /*
3795 * get time unit as scaled exponent 1 sec is 0 of time unit of cur module
3796 * get from other instance module
3797 * if null, return design wide time unit (smallest)
3798 */
tf_igettimeunit(char * inst)3799 extern int32 tf_igettimeunit(char *inst)
3800 {
3801 int32 i;
3802 struct tfinst_t *tfi;
3803 struct mod_t *mdp;
3804
3805 tfi = (struct tfinst_t *) inst;
3806 /* special case return smallest time precision (not units) in design */
3807 if (tfi == NULL) { i = -((int32) __des_timeprec); return(i); }
3808
3809 mdp = tfi->tfitp->itip->imsym->el.emdp;
3810 /* this works because no unit conversion means design time prec (min. */
3811 /* but stored as positive inverse of neg. exponent) is same as unit */
3812 if (!mdp->mno_unitcnv) i = -((int32) mdp->mtime_units);
3813 else i = -((int32) __des_timeprec);
3814 return(i);
3815 }
3816
tf_gettimeunit(void)3817 extern int32 tf_gettimeunit(void)
3818 {
3819 int32 i;
3820
3821 if (!__inst_mod->mno_unitcnv)
3822 i = -((int32) (__inst_mod->mtime_units + __inst_mod->mtime_prec));
3823 /* if no time scale both precision and units the same */
3824 else i = -((int32) __des_timeprec);
3825 return(i);
3826 }
3827
3828 /*
3829 * get the time precision for a module
3830 */
tf_igettimeprecision(char * inst)3831 extern int32 tf_igettimeprecision(char *inst)
3832 {
3833 int32 i;
3834 struct tfinst_t *tfi;
3835 struct mod_t *mdp;
3836
3837 tfi = (struct tfinst_t *) inst;
3838 /* special case return design precison (sim. tick) value */
3839 /* design time units is minimum of all units in design */
3840 if (tfi == NULL) { i = -((int32) __des_timeprec); return(i); }
3841
3842 mdp = tfi->tfitp->itip->imsym->el.emdp;
3843 if (!mdp->mno_unitcnv) i = -((int32) (mdp->mtime_units + mdp->mtime_prec));
3844 else i = -((int32) __des_timeprec);
3845 return(i);
3846 }
3847
3848 /*
3849 * get the time precision for a module
3850 */
tf_gettimeprecision(void)3851 extern int32 tf_gettimeprecision(void)
3852 {
3853 int32 i;
3854
3855 if (!__inst_mod->mno_unitcnv)
3856 i = -((int32) (__inst_mod->mtime_units + __inst_mod->mtime_prec));
3857 else i = -((int32) __des_timeprec);
3858 return(i);
3859 }
3860
3861 /*
3862 * return a string giving module name for task call from other inst/place
3863 */
tf_imipname(char * inst)3864 extern char *tf_imipname(char *inst)
3865 {
3866 char *chp;
3867 struct tfinst_t *sav_tfip;
3868
3869 sav_tfip = __tfinst;
3870 __tfinst = (struct tfinst_t *) inst;
3871 __push_itstk(__tfinst->tfitp);
3872 chp = tf_mipname();
3873 __pop_itstk();
3874 __tfinst = sav_tfip;
3875 return(chp);
3876 }
3877
3878 /*
3879 * return a string (. separated) that is the path to the call to a user
3880 * task or function
3881 *
3882 * just gets this out of cur_itp - when return if schedule has itp
3883 */
tf_mipname(void)3884 extern char *tf_mipname(void)
3885 {
3886 char *chp;
3887 int32 slen;
3888 int32 sav_sofs = __cur_sofs;
3889
3890 __disp_itree_path(__inst_ptr, (struct task_t *) NULL);
3891 slen = __cur_sofs - sav_sofs;
3892 chp = __mytf_malloc(slen + 1);
3893 strcpy(chp, &(__exprline[sav_sofs]));
3894 __cur_sofs = sav_sofs;
3895 __exprline[__cur_sofs] = '\0';
3896 return(chp);
3897 }
3898
tf_ispname(char * cell)3899 extern char *tf_ispname(char *cell)
3900 {
3901 char *chp;
3902 struct tfinst_t *sav_tfip;
3903 struct tfrec_t *sav_tfrp;
3904
3905 set_tfinst_(cell, sav_tfip, sav_tfrp);
3906 __push_itstk(__tfinst->tfitp);
3907 chp = tf_spname();
3908 __pop_itstk();
3909 __tfinst = sav_tfip;
3910 __tfrec = sav_tfrp;
3911 return(chp);
3912 }
3913
3914 /*
3915 * return a string (. separated) that is the scope to the call to a user
3916 * task or function - will contain possible named block or task called from
3917 * plus module name prefix
3918 * for nested blocks can have multiple components
3919 */
tf_spname(void)3920 extern char *tf_spname(void)
3921 {
3922 int32 slen;
3923 int32 sav_sofs = __cur_sofs;
3924 char *chp;
3925
3926 if (__tfrec == NULL)
3927 {
3928 bad_notfcontext_err("tf_spname");
3929 return(NULL);
3930 }
3931 __disp_itree_path(__inst_ptr, __tfrec->tf_intskp);
3932 slen = __cur_sofs - sav_sofs;
3933 chp = __mytf_malloc(slen + 1);
3934 strcpy(chp, &(__exprline[sav_sofs]));
3935 __cur_sofs = sav_sofs;
3936 __exprline[__cur_sofs] = '\0';
3937 return(chp);
3938 }
3939
3940 /*
3941 * cause $finish simulation termination (any clean up needed)
3942 *
3943 * normal convention to check verbose mode but no argument for messages
3944 */
tf_dofinish(void)3945 extern int32 tf_dofinish(void)
3946 {
3947 __pli_dofinish(0, "tf_dofinish");
3948 return(TF_NULLPARAM);
3949 }
3950
3951 /*
3952 * PLI either tf_ or vpi_ routine to stop simulation ($finish)
3953 */
__pli_dofinish(int32 diag_level,char * caller)3954 extern void __pli_dofinish(int32 diag_level, char *caller)
3955 {
3956 int32 rv;
3957
3958 /* need to call PLI end of sim routines before finishing */
3959 if (__tfrec_hdr != NULL) __call_misctfs_finish();
3960 if (__have_vpi_actions) __vpi_endsim_trycall();
3961
3962 /* if not simulating just exit */
3963 if (__run_state != SS_SIM)
3964 {
3965 __cv_msg(
3966 "Halted from call to PLI %s before simulation has begun.\n", caller);
3967 goto endit;
3968 }
3969
3970 if (__verbose)
3971 {
3972 __cv_msg(
3973 "Halted at location %s time %s from call to PLI %s.\n",
3974 __bld_lineloc(__wrks2, (word32) __sfnam_ind, __slin_cnt),
3975 __to_timstr(__wrks1, &__simtime), caller);
3976 __emit_stsk_endmsg();
3977 }
3978 /* notice must always print error counts if any */
3979 endit:
3980 if (__pv_err_cnt != 0 || __pv_warn_cnt != 0 || __inform_cnt != 0)
3981 __cv_msg(" There were %d error(s), %d warning(s), and %d inform(s).\n",
3982 __pv_err_cnt, __pv_warn_cnt, __inform_cnt);
3983 /* SJM 04/26/04 - needs to exit with non zero if any errors occurred */
3984 if (__pv_err_cnt != 0) rv = 1; else rv = 0;
3985 __my_exit(rv, TRUE);
3986 }
3987
3988 /*
3989 * cause $stop return to interactive mode
3990 * this is tricky since must run interactive environment under here
3991 */
tf_dostop(void)3992 extern int32 tf_dostop(void)
3993 {
3994 if (__run_state != SS_SIM) return(bad_nosimtf_err("tf_dostop"));
3995 if (__no_iact)
3996 {
3997 __sgfwarn(560,
3998 "Call to PLI tf_dostop no effect - interactive environment disabled");
3999 return(TF_NULLPARAM);
4000 }
4001 __pending_enter_iact = TRUE;
4002 __iact_reason = IAER_STOP;
4003 /* must leave signal on - if ^c hit before stop, same effect */
4004 /* but entry reason different and lost */
4005 return(TF_NULLPARAM);
4006 }
4007
4008 /*
4009 * INSTANCE AND LOCATION USER STORAGE ROUTINES
4010 */
4011
4012 /*
4013 * convert current inst - arg list and itree place to alloced rec.
4014 * allocates record that user can free with tf_freeinst - added
4015 */
tf_getinstance(void)4016 extern char *tf_getinstance(void)
4017 {
4018 struct tfinst_t *tfip;
4019
4020 /* LOOKATME - this storage is not freeable (inherent memory leak?) */
4021 tfip = (struct tfinst_t *) malloc(sizeof(struct tfinst_t));
4022 *tfip = *__tfinst;
4023 return((char *) tfip);
4024 }
4025
4026 /*
4027 * get associated work area
4028 * since can just use malloc this is pointless (was for IBM 360 mvs?)
4029 */
tf_igetworkarea(char * inst)4030 extern char *tf_igetworkarea(char *inst)
4031 {
4032 char *chp;
4033 struct tfinst_t *sav_tfip;
4034 struct tfrec_t *sav_tfrp;
4035
4036 set_tfinst_(inst, sav_tfip, sav_tfrp);
4037 __push_itstk(__tfinst->tfitp);
4038 chp = tf_getworkarea();
4039 __pop_itstk();
4040 __tfinst = sav_tfip;
4041 __tfrec = sav_tfrp;
4042 return(chp);
4043 }
4044
4045 /*
4046 * get associated work area
4047 */
tf_getworkarea(void)4048 extern char *tf_getworkarea(void)
4049 {
4050 if (__tfrec == NULL)
4051 {
4052 bad_notfcontext_err("tf_getworkarea");
4053 return(NULL);
4054 }
4055 return(__tfrec->savwrkarea[__inum]);
4056 }
4057
4058 /*
4059 * store work area for other inst/loc pli task
4060 */
tf_isetworkarea(char * workarea,char * inst)4061 extern int32 tf_isetworkarea(char *workarea, char *inst)
4062 {
4063 int32 rv;
4064 struct tfinst_t *sav_tfip;
4065 struct tfrec_t *sav_tfrp;
4066
4067 set_tfinst_(inst, sav_tfip, sav_tfrp);
4068 __push_itstk(__tfinst->tfitp);
4069 rv = tf_setworkarea(workarea);
4070 __pop_itstk();
4071 __tfinst = sav_tfip;
4072 __tfrec = sav_tfrp;
4073 return(rv);
4074 }
4075
4076 /*
4077 * store (associate) routine with pli task
4078 * just a pointer assignment
4079 */
tf_setworkarea(char * workarea)4080 extern int32 tf_setworkarea(char *workarea)
4081 {
4082 if (__tfrec == NULL) return(bad_notfcontext_err("tf_setworkarea"));
4083 __tfrec->savwrkarea[__inum] = workarea;
4084 return(1);
4085 }
4086
4087 /*
4088 * 64 BIT ARITHMETIC ROUTINES
4089 */
4090
4091 /*
4092 * add long's which even though passed as int32 are really unsigned
4093 * LOOKATME - is this supposed to be long but signed add
4094 * if really word32 should change veriuser.h template
4095 */
tf_add_long(int32 * aof_lowtime1,int32 * aof_hightime1,int32 lowtime2,int32 hightime2)4096 extern void tf_add_long(int32 *aof_lowtime1, int32 *aof_hightime1, int32 lowtime2,
4097 int32 hightime2)
4098 {
4099 register int32 lowsum;
4100
4101 lowsum = *aof_lowtime1 + lowtime2;
4102 *aof_hightime1 = *aof_hightime1 + hightime2
4103 + ((word32) lowsum < (word32) *aof_lowtime1);
4104 *aof_lowtime1 = lowsum;
4105 }
4106
4107 /*
4108 * 2's complement signed long subtract
4109 * built in 32 bit size for int32 and any borrow is lost
4110 * fails on machine that does not use 2's complement for signed ints
4111 * also assumes conversion from word32 to int32 can make a negative int
4112 * per normal c conventions
4113 */
tf_subtract_long(int32 * aof_lowtime1,int32 * aof_hightime1,int32 lowtime2,int32 hightime2)4114 extern void tf_subtract_long(int32 *aof_lowtime1, int32 *aof_hightime1,
4115 int32 lowtime2, int32 hightime2)
4116 {
4117 register int32 lowdif;
4118
4119 lowdif = *aof_lowtime1 - lowtime2;
4120 /* tmp greater than subtracted from means wrap around and need borrow */
4121 /* word32 borrow test since need to include high bit */
4122 *aof_hightime1 = *aof_hightime1 - hightime2
4123 - (int32) (((word32) lowdif > (word32) *aof_lowtime1));
4124 *aof_lowtime1 = lowdif;
4125 }
4126
4127 /*
4128 * compare 2 long ints passed in 4 halves
4129 * return -1 <, 0 =, +1 >
4130 * requires 2 complement representation according to normal c convention
4131 */
tf_compare_long(unsigned int low1,unsigned int high1,unsigned int low2,unsigned int high2)4132 extern int tf_compare_long(unsigned int low1, unsigned int high1,
4133 unsigned int low2, unsigned int high2)
4134 {
4135 if (high1 == high2)
4136 {
4137 if (low1 == low2) return(0);
4138 if (low1 > low2) return(1);
4139 return(-1);
4140 }
4141 if (high1 < high2) return(-1);
4142 return(1);
4143 }
4144
4145 /*
4146 * 2's complement long multiply of 2 64 bit values
4147 * this is built in 64 bits because int32 must be 32 bits for portability
4148 * this removes and puts back sign
4149 */
tf_multiply_long(int32 * aof_low1,int32 * aof_high1,int32 low2,int32 high2)4150 extern void tf_multiply_long(int32 *aof_low1, int32 *aof_high1, int32 low2,
4151 int32 high2)
4152 {
4153 word32 r[2], u[2], v[2];
4154 register int32 ir0, ir1;
4155 int32 minus;
4156
4157 if (*aof_high1 < 0)
4158 {
4159 minus = TRUE;
4160 u[0] = (word32) -(*aof_low1);
4161 u[1] = (word32) (-(*aof_high1) - (u[0] != 0));
4162 }
4163 else
4164 {
4165 minus = FALSE;
4166 u[0] = (word32) *aof_low1;
4167 u[1] = (word32) *aof_high1;
4168 }
4169 if (high2 < 0)
4170 {
4171 minus = !minus;
4172 v[0] = (word32) -low2;
4173 v[1] = (word32) (-high2 - (v[0] != 0));
4174 }
4175 else { v[0] = (word32) low2; v[1] = (word32) high2; }
4176
4177 __lmult((word32 *) r, (word32 *) u, (word32 *) v, 64);
4178 if (minus)
4179 {
4180 ir0 = (int32) r[0];
4181 ir1 = (int32) r[1];
4182 *aof_low1 = -ir0;
4183 *aof_high1 = -ir1 - (*aof_low1 != 0);
4184 }
4185 else { *aof_low1 = (int32) r[0]; *aof_high1 = (int32) r[1]; }
4186 }
4187
4188 /*
4189 * long divide of word32 times - assuming word32 div not mod
4190 * LOOKATME - treating as word32 why are arguments ints? and no way to
4191 * indicate divide by 0
4192 */
tf_divide_long(int32 * aof_low1,int32 * aof_high1,int32 low2,int32 high2)4193 extern void tf_divide_long(int32 *aof_low1, int32 *aof_high1, int32 low2, int32 high2)
4194 {
4195 word32 res[02], u[2], v[2], dum[2];
4196 register int32 ir0, ir1;
4197 int32 minus;
4198
4199 /* divide by 0 must be 0 since no error mechanism */
4200 if (low2 == 0L && high2 == 0L) { *aof_low1 = *aof_high1 = 0L; return; }
4201
4202 if (*aof_high1 < 0)
4203 {
4204 minus = TRUE;
4205 u[0] = (word32) -(*aof_low1);
4206 u[1] = (word32) (-(*aof_high1) - (u[0] != 0));
4207 }
4208 else
4209 {
4210 minus = FALSE;
4211 u[0] = (word32) *aof_low1;
4212 u[1] = (word32) *aof_high1;
4213 }
4214 if (high2 < 0)
4215 {
4216 minus = !minus;
4217 v[0] = (word32) -low2;
4218 v[1] = (word32) (-high2 - (v[0] != 0));
4219 }
4220 else { v[0] = (word32) low2; v[1] = (word32) high2; }
4221 __ldivmod2(res, dum, u, v, 64);
4222 if (minus)
4223 {
4224 ir0 = (int32) res[0];
4225 ir1 = (int32) res[1];
4226 *aof_low1 = -ir0;
4227 *aof_high1 = -ir1 - (*aof_low1 != 0);
4228 }
4229 else { *aof_low1 = (int32) res[0]; *aof_high1 = (int32) res[1]; }
4230 }
4231
4232 /*
4233 * I/O ROUTINES
4234 */
4235
4236 /*
4237 * emit error using cver mechanism
4238 */
tf_error(char * fmt,...)4239 extern int32 tf_error(char *fmt, ...)
4240 {
4241 va_list va, va2;
4242
4243 va_start(va, fmt);
4244 va_start(va2, fmt);
4245 vprt_tferr_msg(fmt, va, va2);
4246 va_end(va);
4247 va_end(va2);
4248 return(1);
4249 }
4250
4251 /*
4252 * actually print an error message tf form - also used by tf message
4253 */
vprt_tferr_msg(char * fmt,va_list va,va_list va2)4254 static void vprt_tferr_msg(char *fmt, va_list va, va_list va2)
4255 {
4256 char s1[RECLEN], s2[RECLEN];
4257
4258 __pv_err_cnt++;
4259 if (!__no_errs)
4260 {
4261 if (__run_state == SS_SIM)
4262 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
4263 else strcpy(s1, "");
4264
4265 __my_fprintf(stdout, "**%s(%d) USER PLI ERROR**%s [1290] ",
4266 __in_fils[__sfnam_ind], __slin_cnt, s1);
4267 __my_vfprintf(stdout, fmt, va, va2);
4268 my_putc_('\n', stdout);
4269 }
4270 /* no maximum error count for these */
4271 }
4272
tf_warning(char * fmt,...)4273 extern int32 tf_warning(char *fmt, ...)
4274 {
4275 va_list va, va2;
4276
4277 va_start(va, fmt);
4278 va_start(va2, fmt);
4279 vprt_tfwarn_msg(fmt, va, va2);
4280 va_end(va);
4281 va_end(va2);
4282 return(1);
4283 }
4284
4285 /*
4286 * actually print a warning message tf form - also used by tf message
4287 */
vprt_tfwarn_msg(char * fmt,va_list va,va_list va2)4288 static void vprt_tfwarn_msg(char *fmt, va_list va, va_list va2)
4289 {
4290 char s1[RECLEN], s2[RECLEN];
4291
4292 __pv_warn_cnt++;
4293 /* warning number 600 is for all pli tasks so all can be suppressed */
4294 if (__no_warns || __em_suppr(600)) return;
4295
4296 if (__run_state == SS_SIM)
4297 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
4298 else strcpy(s1, "");
4299
4300 __my_fprintf(stdout, "**%s(%d) PLI WARN**%s [600] ", __in_fils[__sfnam_ind],
4301 __slin_cnt, s1);
4302 __my_vfprintf(stdout, fmt, va, va2);
4303 my_putc_('\n', stdout);
4304 }
4305
4306 /*
4307 * unimplemented sprintf like routine
4308 */
tf_text(char * fmt,...)4309 extern int32 tf_text(char *fmt, ...)
4310 {
4311 /* ---
4312 va_list va;
4313
4314 va_start(va, fmt);
4315 va_end(va);
4316 --- */
4317 __sgferr(1287, "tf_text not implemented - use sprintf and tf_message");
4318 return(TF_NULLPARAM);
4319 }
4320
4321 /*
4322 * print a message using Cver style error message format
4323 * facility and messno ignored
4324 */
tf_message(int32 level,char * facility,char * messno,char * message,...)4325 extern int32 tf_message(int32 level, char *facility, char *messno,
4326 char *message, ...)
4327 {
4328 va_list va, va2;
4329 char s1[RECLEN], s2[RECLEN];
4330
4331 va_start(va, message);
4332 va_start(va2, message);
4333
4334 switch (level) {
4335 case ERR_INTERNAL:
4336 if (__run_state == SS_SIM)
4337 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
4338 else strcpy(s1, "");
4339 __my_fprintf(stdout, "**%s(%d) PLI INTERNAL FATAL**%s [300] ",
4340 __in_fils[__sfnam_ind], __slin_cnt, s1);
4341 __my_vfprintf(stdout, message, va, va2);
4342 my_putc_('\n', stdout);
4343 va_end(va);
4344 va_end(va2);
4345 __my_exit(2, TRUE);
4346 break;
4347 case ERR_ERROR: case ERR_SYSTEM:
4348 vprt_tferr_msg(message, va, va2);
4349 break;
4350 case ERR_MESSAGE:
4351 if (!__no_informs && !__em_suppr(400))
4352 {
4353 __my_fprintf(stdout, "--%s(%d) PLI MESSAGE** [400] ",
4354 __in_fils[__sfnam_ind], __slin_cnt);
4355 __my_vfprintf(stdout, message, va, va2);
4356 my_putc_('\n', stdout);
4357 }
4358 break;
4359 case ERR_WARNING:
4360 vprt_tfwarn_msg(message, va, va2);
4361 break;
4362 }
4363 va_end(va);
4364 va_end(va2);
4365 return(1);
4366 }
4367
4368 /*
4369 * printf to multi-channel descriptor
4370 */
io_mcdprintf(int32 mcd,char * format,...)4371 extern void io_mcdprintf(int32 mcd, char *format, ...)
4372 {
4373 register int32 i;
4374 va_list va, va2;
4375
4376 /* SJM 09/09/03 - fd case easy because only one stream to write to */
4377 if ((mcd & FIO_MSB) == FIO_MSB)
4378 {
4379 int32 fd;
4380
4381 fd = (int32) (mcd & ~FIO_MSB);
4382 /* if fd does not correspond to open file, just set error indicator */
4383 if (__fio_fdtab[fd] == NULL)
4384 {
4385 __sgfwarn(651,
4386 "in tf_ pli file not open for descriptor number %d ", fd);
4387 errno = EBADF;
4388 return;
4389 }
4390 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf */
4391 va_start(va, format);
4392 vfprintf(__fio_fdtab[fd]->fd_s, format, va);
4393 va_end(va);
4394 return;
4395 }
4396
4397 /* SJM 03/26/00 - mcd 1 now both stdout and log if open */
4398 if ((mcd & 1) != 0)
4399 {
4400 va_start(va, format);
4401 va_start(va2, format);
4402
4403 vprintf(format, va);
4404 if (__log_s != NULL) vfprintf(__log_s, format, va2);
4405
4406 va_end(va);
4407 va_end(va2);
4408 }
4409
4410 /* mcd's may require writing to lots of files */
4411 for (i = 1; i < 31; i++)
4412 {
4413 if (((mcd >> i) & 1L) != 0L)
4414 {
4415 if (__mulchan_tab[i].mc_s == NULL)
4416 {
4417 __sgfwarn(651,
4418 "in tf_ pli multi-channel descriptor bit %d on, but file not open",
4419 i);
4420 }
4421 else
4422 {
4423 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf */
4424 va_start(va, format);
4425 vfprintf(__mulchan_tab[i].mc_s, format, va);
4426 va_end(va);
4427 }
4428 }
4429 }
4430 if (((mcd >> 31) & 1) != 0)
4431 {
4432 __sgfwarn(651,
4433 "in tf_ pli multi-channel descriptor bit 31 on but file not open - unusable because reserved for new Verilog 2001 file I/O");
4434 }
4435 }
4436
4437 /*
4438 * formatted print to both standard output and log file (if open)
4439 */
io_printf(char * format,...)4440 extern void io_printf(char *format, ...)
4441 {
4442 va_list va, va2;
4443
4444 va_start(va, format);
4445 va_start(va2, format);
4446 vprintf(format, va);
4447 if (__log_s != NULL) vfprintf(__log_s, format, va2);
4448 va_end(va);
4449 va_end(va2);
4450 }
4451
4452 /*
4453 * scan plus args (for now scan args and if no + do not try to match)
4454 * plusarg does not have leading +
4455 * DOCUMENTME - returned string is read only
4456 */
mc_scan_plusargs(char * plusarg)4457 extern char *mc_scan_plusargs(char *plusarg)
4458 {
4459 register struct optlst_t *olp;
4460 register char *chp;
4461 int32 arglen, optlen;
4462
4463 arglen = strlen(plusarg);
4464 /* all options expanded and saved so this is easy */
4465 for (olp = __opt_hdr; olp != NULL; olp = olp->optlnxt)
4466 {
4467 /* ignore markers added for building vpi argc/argv */
4468 if (olp->is_bmark || olp->is_emark) continue;
4469
4470 chp = olp->opt;
4471 if (*chp != '+') continue;
4472 /* if plus arg longer than option cannot match */
4473 if ((optlen = strlen(&(chp[1]))) < arglen) continue;
4474 /* match prefix */
4475 if (strncmp(&(chp[1]), plusarg, arglen) != 0) continue;
4476 /* return pointer to 1st char after matched prefix */
4477 /* may be empty string */
4478 return(&(chp[arglen + 1]));
4479 }
4480 /* if no match return nil ptr not empty string */
4481 return(NULL);
4482 }
4483
4484 /*
4485 * OLD ROUTINES NO LONGER IN STANDARD?
4486 */
4487
4488 /*
4489 * free instance - added routine if needed
4490 * rarely needed
4491 */
4492 /* ---
4493 extern char tf_freeinstance(char *inst)
4494 {
4495 free(inst);
4496 }
4497 --- */
4498
4499 /*
4500 * ROUTINES NOT INCLUDED IN PRELIMARY IEEE VERIUSER.H
4501 */
4502
4503 /*
4504 * think this is no longer needed since assigning causes propagate
4505 */
tf_ievaluatep(int32 pnum,char * inst)4506 extern int32 tf_ievaluatep(int32 pnum, char *inst)
4507 {
4508 int32 rv;
4509 struct tfinst_t *sav_tfip;
4510 struct tfrec_t *sav_tfrp;
4511
4512 set_tfinst_(inst, sav_tfip, sav_tfrp);
4513 __push_itstk(__tfinst->tfitp);
4514 rv = tf_evaluatep(pnum);
4515 __pop_itstk();
4516 __tfinst = sav_tfip;
4517 __tfrec = sav_tfrp;
4518 return(rv);
4519 }
4520
4521 /*
4522 * evaluate an expression for its value and set in tf_texprinfo node
4523 * notice this is for exprinfo not nodeinfo
4524 *
4525 * this uses a previously (last) set tf_texprinfo for this inst.
4526 * return 0 if no previous expr or error else 1
4527 * places new value into exprinfo structure
4528 *
4529 * for memories must be cell select since tf_ func/task argument must be
4530 * legal ver expr.
4531 * notice this is fast because only changes value exprinfo fields
4532 */
tf_evaluatep(int32 pnum)4533 extern int32 tf_evaluatep(int32 pnum)
4534 {
4535 register int32 wi;
4536 register struct t_tfexprinfo *pinfo;
4537 register struct xstk_t *xsp;
4538 int32 wlen, rv;
4539 double d1;
4540 struct tfarg_t *tfap;
4541 struct expr_t *xp;
4542
4543 if (__tfrec == NULL)
4544 {
4545 rv = bad_notfcontext_err("tf_evaluatep");
4546 /* SJM 12/17/02 - error is 1 and success is 0 */
4547 if (rv == TF_NULLPARAM) return(1); else return(0);
4548 }
4549 tfap = &(__tfrec->tfargs[pnum]);
4550 pinfo = (struct t_tfexprinfo *) tfap->sav_xinfos[__inum];
4551 if (pinfo == NULL) return(1);
4552 xp = tfap->arg.axp;
4553
4554 /* here this always handles any gref itree pushing and popping */
4555 xsp = __eval_xpr(xp);
4556 if (xp->is_real)
4557 {
4558 memcpy(&d1, xsp->ap, sizeof(double));
4559 pinfo->real_value = d1;
4560 }
4561 else
4562 {
4563 wlen = wlen_(xp->szu.xclen);
4564 for (wi = 0; wi < wlen; wi++)
4565 {
4566 pinfo->expr_value_p[wi].avalbits = (int32) xsp->ap[wi];
4567 pinfo->expr_value_p[wi].bvalbits = (int32) xsp->bp[wi];
4568 }
4569 }
4570 __pop_xstk();
4571 return(0);
4572 }
4573
4574 /*
4575 * progogate a changed rhs value to all lhs?
4576 * what does this do and how is expr. stored ?
4577 */
tf_ipropagatep(int32 pnum,char * inst)4578 extern int32 tf_ipropagatep(int32 pnum, char *inst)
4579 {
4580 int32 rv;
4581 struct tfinst_t *sav_tfip;
4582 struct tfrec_t *sav_tfrp;
4583
4584 set_tfinst_(inst, sav_tfip, sav_tfrp);
4585 __push_itstk(__tfinst->tfitp);
4586 rv = tf_propagatep(pnum);
4587 __pop_itstk();
4588 __tfinst = sav_tfip;
4589 __tfrec = sav_tfrp;
4590 return(rv);
4591 }
4592
4593 /*
4594 * propagate the value user placed in node info structure
4595 * previous call of tf nodeinfo set current node info struct
4596 *
4597 * this does not work for strengths because node info fails
4598 *
4599 * SJM 11/30/99 - changed to follow new LRM and use exprinfo for
4600 * save (from tf_exprinfo) instead of node info (from tf_nodeinfo)
4601 */
tf_propagatep(int32 pnum)4602 extern int32 tf_propagatep(int32 pnum)
4603 {
4604 register int32 wi;
4605 register struct xstk_t *xsp;
4606 register struct t_vecval *vecp;
4607 register struct t_tfexprinfo *xpinfo;
4608 int32 rv;
4609 double d1;
4610 struct tfarg_t *tfap;
4611 struct expr_t *lhsxp;
4612
4613 if (__tfrec == NULL)
4614 {
4615 rv = bad_notfcontext_err("tf_propagatep");
4616 /* SJM 12/17/02 - error is 1 and success is 0 */
4617 if (rv == TF_NULLPARAM) return(1); else return(0);
4618 }
4619 tfap = &(__tfrec->tfargs[pnum]);
4620 if (pnum < 1 || pnum >= __tfrec->tfanump1) return(1);
4621
4622 /* need previously stored from call to expr info */
4623 xpinfo = (struct t_tfexprinfo *) tfap->sav_xinfos[__inum];
4624 if (xpinfo == NULL) return(1);
4625
4626 if (xpinfo->expr_type == TF_READONLY
4627 || xpinfo->expr_type == TF_READONLYREAL
4628 || xpinfo->expr_type == TF_STRING
4629 || xpinfo->expr_type == TF_NULLPARAM)
4630 {
4631 __sgferr(1280,
4632 "tf_propagatep saved expression illegal - expressions not writeable");
4633 return(1);
4634 }
4635 lhsxp = tfap->arg.axp;
4636 if (lhsxp->x_stren)
4637 {
4638 __sgferr(1212,
4639 "tf_propagatep of strength expression illegal - tf_ does not store strength");
4640 return(1);
4641 }
4642
4643 /* know user filled field of pinfo before calling this */
4644 /* copy value to internal a/b form for assignment */
4645 if (xpinfo->expr_type == TF_READWRITEREAL)
4646 {
4647 d1 = xpinfo->real_value;
4648 push_xstk_(xsp, REALBITS);
4649 memcpy(xsp->ap, &d1, sizeof(double));
4650 }
4651 else
4652 {
4653 /* here just convert from vecval p form to internal a/b form */
4654 /* SJM 02/16/07 - push xstk takes num bits not bytes - thanks SAS@Tharas */
4655 push_xstk_(xsp, xpinfo->expr_ngroups*WBITS);
4656 vecp = xpinfo->expr_value_p;
4657 for (wi = 0; wi < xpinfo->expr_ngroups; wi++)
4658 {
4659 xsp->ap[wi] = (word32) vecp[wi].avalbits;
4660 xsp->bp[wi] = (word32) vecp[wi].bvalbits;
4661 }
4662 }
4663 exec_tfarg_assign(tfap, lhsxp, xsp->ap, xsp->bp);
4664 __pop_xstk();
4665 return(0);
4666 }
4667
4668 /*
4669 * need $restart mechanism for this
4670 */
tf_read_restart(char * blockptr,int32 blocklen)4671 extern int32 tf_read_restart(char *blockptr, int32 blocklen)
4672 {
4673 /* UNIMPLMENTED */
4674 __sgferr(1287,
4675 "tf_read_restart not implemented - $save/$restart not yet implemented");
4676 return(0);
4677 }
4678
tf_write_save(char * blockptr,int32 blocklen)4679 extern int32 tf_write_save(char *blockptr, int32 blocklen)
4680 {
4681 /* UNIMPLMENTED */
4682 __sgferr(1287,
4683 "tf_write_save not implemented - $save/$restart not yet implemented");
4684 return(0);
4685 }
4686
4687 /*
4688 * other pli function/task call version of sleep ?
4689 */
4690 /* ---
4691 extern int32 tf_isleep(int32 delay, char *inst)
4692 {
4693 int32 rv;
4694 }
4695 -- */
4696
4697 /*
4698 * scale to internal time unit and then block for that time
4699 * think this is like setdelay - or maybe has no argument and just
4700 * terminates ? - why not just set delay and return?
4701 */
4702 /* --
4703 extern int32 tf_sleep(int32 delay)
4704 {
4705 return(0);
4706 }
4707 -- */
4708
4709 /*
4710 * NEW ROUTINES ADDED FOR PVER
4711 */
4712
4713 /*
4714 * routine to determine source location of tf_ instance
4715 */
tf_igetsourceloc(int32 * lineno,char * inst)4716 extern char *tf_igetsourceloc(int32 *lineno, char *inst)
4717 {
4718 char *chp;
4719 struct tfinst_t *sav_tfip;
4720 struct tfrec_t *sav_tfrp;
4721
4722 set_tfinst_(inst, sav_tfip, sav_tfrp);
4723 chp = tf_getsourceloc(lineno);
4724 __tfinst = sav_tfip;
4725 __tfrec = sav_tfrp;
4726 return(chp);
4727 }
4728
4729
tf_getsourceloc(int32 * lineno)4730 extern char *tf_getsourceloc(int32 *lineno)
4731 {
4732 int32 slen;
4733 char *chp, *chp2;
4734
4735 if (__tfrec == NULL)
4736 {
4737 bad_notfcontext_err("tf_getsourceloc");
4738 return(NULL);
4739 }
4740 chp2 = __in_fils[__tfrec->tffnam_ind];
4741 slen = strlen(chp2);
4742 chp = __my_malloc(slen + 1);
4743 strcpy(chp, chp2);
4744 *lineno = __tfrec->tflin_cnt;
4745 return(chp);
4746 }
4747
4748 /*
4749 * ROUTINES FOR MISCTF PARAMETER CHANGE PROCESSING
4750 */
4751
4752 /*
4753 * call the misctf routine after parameter changed
4754 *
4755 * know dce will not be linked on unless async is on for this inst/call
4756 * know right itree location
4757 *
4758 * notice since this dce does not fit into normal scheme dce 1inst T if
4759 * func or F if task, dce2 union is ptr to task call statement or fcall expr
4760 * and unused dce_downitp is cast to int32 for pnum (set when built)
4761 */
__pvc_call_misctf(struct dcevnt_t * dcep)4762 extern void __pvc_call_misctf(struct dcevnt_t *dcep)
4763 {
4764 int32 pnum, sav_fnam_ind, sav_slin_cnt;
4765 struct st_t *stp;
4766 struct expr_t *fcallx;
4767 struct t_tfcell *tfcp;
4768 struct tskcall_t *tkcp;
4769 struct systsk_t *stbp;
4770 struct sysfunc_t *sfbp;
4771 struct tfinst_t tfiwrk;
4772 int32 (*misctf)();
4773
4774 stp = NULL;
4775 fcallx = NULL;
4776 /* T dce iscol for pvc means dce2 union is ptr to fcallx else to stp */
4777 if (dcep->dce_tfunc)
4778 {
4779 fcallx = dcep->dceu2.dce_pvc_fcallx;
4780 sfbp = fcallx->lu.x->lu.sy->el.esyftbp;
4781 tfcp = &(__shadow_veriusertfs[sfbp->syfnum - BASE_VERIUSERTFS]);
4782 __tfrec = fcallx->lu.x->szu.xfrec;
4783 }
4784 else
4785 {
4786 stp = dcep->dceu2.dce_pvc_stp;
4787 tkcp = &(stp->st.stkc);
4788 stbp = tkcp->tsksyx->lu.sy->el.esytbp;
4789 tfcp = &(__shadow_veriusertfs[stbp->stsknum - BASE_VERIUSERTFS]);
4790 __tfrec = tkcp->tkcaux.trec;
4791 }
4792
4793 pnum = dcep->dceu.pnum;
4794 /* step 1: update pvc change flags */
4795 /* pvc code never turns change flags off user must call movepvc routine */
4796 __tfrec->tfargs[pnum].old_pvc_flgs[__inum] = 1;
4797
4798 /* if no misc tf routine - done */
4799 /* SJM 06/13/1999 - misctf always requires 3rd argument although ignored */
4800 /* except for synchon callbacks ?? */
4801 if ((misctf = tfcp->misctf) == NULL) return;
4802
4803 sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt;
4804 __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
4805 __vpifnam_ind = __sfnam_ind;
4806 __vpilin_cnt = __slin_cnt;
4807
4808 /* set up environment that is current implied tf instance */
4809 /* notice assignment of addr. to static works since niled in this rout. */
4810 __tfinst = &tfiwrk;
4811 __tfinst->callx = NULL;
4812 __tfinst->tfstp = NULL;
4813 __tfinst->tfitp = __inst_ptr;
4814 if (dcep->dce_tfunc) __tfinst->callx = fcallx; else __tfinst->tfstp = stp;
4815
4816 /* FIXME ??? - not 64 bit clean */
4817 (*misctf)((int32) tfcp->data, REASON_PARAMVC, pnum);
4818 __tfinst = NULL;
4819 __tfrec = NULL;
4820 __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
4821 __vpifnam_ind = 0;
4822 __vpilin_cnt = 0;
4823 }
4824
4825 /*
4826 * build and link on special pvc tf_ parameter change dce for one param
4827 * xp is param expr (can be rhs) - know __tfrec and instance loc. set
4828 */
bld_pvc_dces(struct expr_t * xp,int32 pnum)4829 static void bld_pvc_dces(struct expr_t *xp, int32 pnum)
4830 {
4831 struct net_t *np;
4832 int32 biti, bitj;
4833 word32 *wp;
4834 struct expr_t *idndp, *ndx;
4835 struct expr_t *fax;
4836
4837 switch ((byte) xp->optyp) {
4838 case GLBREF:
4839 idndp = xp;
4840 biti = bitj = -1;
4841 glb_dce:
4842 np = idndp->lu.sy->el.enp;
4843 linkon_pvc_dce(np, biti, bitj, idndp->ru.grp, pnum);
4844 break;
4845 case ID:
4846 idndp = xp;
4847 np = xp->lu.sy->el.enp;
4848 linkon_pvc_dce(np, -1, -1, (struct gref_t *) NULL, pnum);
4849 break;
4850 /* SJM 05/18/00 - must do nothing for reals */
4851 case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
4852 return;
4853 case LSB:
4854 idndp = xp->lu.x;
4855 np = idndp->lu.sy->el.enp;
4856 ndx = xp->ru.x;
4857 /* for monits, any reg or non scalaraed wire must trigger on any chg */
4858 if (ndx->optyp == NUMBER)
4859 {
4860 wp = &(__contab[ndx->ru.xvi]);
4861 if (wp[1] != 0L) biti = -1; else biti = (int32) wp[0];
4862 }
4863 else if (ndx->optyp == ISNUMBER)
4864 {
4865 wp = &(__contab[ndx->ru.xvi]);
4866 wp = &(wp[2*__inum]);
4867
4868 /* need length for IS number because can be wider - but get low */
4869 if (wp[1] != 0L) biti = -1; else biti = (int32) wp[0];
4870 }
4871 else
4872 {
4873 /* notice for monitor and dctrl event change, variable here is legal */
4874 /* and implies change for index and trigger on all bits of variable */
4875 bld_pvc_dces(ndx, pnum);
4876 biti = -1;
4877 }
4878 bitj = biti;
4879 if (biti != -1 && !np->vec_scalared) biti = bitj = -1;
4880 if (idndp->optyp == GLBREF) goto glb_dce;
4881 linkon_pvc_dce(np, biti, biti, (struct gref_t *) NULL, pnum);
4882 break;
4883 case PARTSEL:
4884 idndp = xp->lu.x;
4885 np = idndp->lu.sy->el.enp;
4886 ndx = xp->ru.x;
4887 /* know part select never IS */
4888 biti = (int32) __contab[ndx->lu.x->ru.xvi];
4889 bitj = (int32) __contab[ndx->ru.x->ru.xvi];
4890 if (!np->vec_scalared) biti = bitj = -1;
4891 if (idndp->optyp == GLBREF) goto glb_dce;
4892 linkon_pvc_dce(np, biti, bitj, (struct gref_t *) NULL, pnum);
4893 break;
4894 case FCALL:
4895 /* if any arguments of system or user functions change, monitor triggers */
4896 /* notice $time function do not have arguments */
4897 for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
4898 bld_pvc_dces(fax->lu.x, pnum);
4899 break;
4900 case LCB:
4901 for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
4902 bld_pvc_dces(fax->lu.x, pnum);
4903 break;
4904 default:
4905 if (xp->lu.x != NULL) bld_pvc_dces(xp->lu.x, pnum);
4906 if (xp->ru.x != NULL) bld_pvc_dces(xp->ru.x, pnum);
4907 break;
4908 }
4909 }
4910
4911 /*
4912 * link on a special (one per inst) pvc dce
4913 *
4914 * know one of callx and stp set but not both
4915 * -2 IS form impossible since any one inst. IS form converted to constant
4916 * before here
4917 * need old value for ranges since need exact change processing
4918 * not sure if ref. itp needed here but stored
4919 */
linkon_pvc_dce(struct net_t * np,int32 biti,int32 bitj,struct gref_t * grp,int32 pnum)4920 static void linkon_pvc_dce(struct net_t *np, int32 biti, int32 bitj,
4921 struct gref_t *grp, int32 pnum)
4922 {
4923 register struct dcevnt_t *dcep;
4924 int32 nd_itpop;
4925 struct itree_t *ref_itp;
4926 struct dceauxlst_t *dclp;
4927
4928 ref_itp = __inst_ptr;
4929 nd_itpop = FALSE;
4930 if (grp != NULL) { __xmrpush_refgrp_to_targ(grp); nd_itpop = TRUE; }
4931 /* allocate, init, and fill the fields */
4932 dcep = __alloc_dcevnt(np);
4933
4934 if (biti == -1) dcep->dce_typ = DCE_PVC;
4935 else
4936 {
4937 dcep->dce_typ = DCE_RNG_PVC;
4938 dcep->dci1 = biti;
4939 dcep->dci2.i = bitj;
4940 }
4941 /* link this on front */
4942 dcep->dcenxt = np->dcelst;
4943
4944 /* AIV 09/25/06 - need to set has_dces bit to T - could be only one */
4945 /* has checking bit in record_nchg_ - and not executing list */
4946 np->nchg_has_dces = TRUE;
4947
4948 np->dcelst = dcep;
4949 dcep->dce_1inst = TRUE;
4950 /* this is itree dcep put on */
4951 dcep->dce_matchitp = __inst_ptr;
4952 /* this is placed referenced, unless xmr same as match */
4953 dcep->dce_refitp = ref_itp;
4954
4955 /* also set unused fmon field to pvc object and other pvc fields */
4956 if (__tfrec->tf_func)
4957 {
4958 dcep->dce_tfunc = TRUE;
4959 /* unused fmon field used for callx */
4960 dcep->dceu2.dce_pvc_fcallx = __tfrec->tfu.callx;
4961 }
4962 else
4963 {
4964 dcep->dce_tfunc = FALSE;
4965 /* unused fmon field used for stp */
4966 dcep->dceu2.dce_pvc_stp = __tfrec->tfu.tfstp;
4967 }
4968 /* unused down itp used for tf_ param number (tf_ func ret val not incl) */
4969 dcep->dceu.pnum = pnum;
4970 /* __inst_ptr is right place */
4971 __alloc_1instdce_prevval(dcep);
4972 __init_1instdce_prevval(dcep);
4973
4974 /* then link on undo/chg list */
4975 dclp = (struct dceauxlst_t *) __my_malloc(sizeof(struct dceauxlst_t));
4976 dclp->ldcep = dcep;
4977 dclp->dclnxt = __pvc_dcehdr;
4978 __pvc_dcehdr = dclp;
4979
4980 /* since no dce, no loads, and no dmpvars must always turn chg store on */
4981 if (!dcep->dce_np->nchg_nd_chgstore)
4982 {
4983 /* this also regen net's decl iops from dce if -O on */
4984 __dce_turn_chg_store_on(__inst_mod, dcep, TRUE);
4985 }
4986 /* SJM 02/06/03 - may have npps but not dces so must turn this on */
4987 /* since nchg nd chgstore on, know nchg action right */
4988 if (np->ntyp >= NONWIRE_ST) np->nchg_has_dces = TRUE;
4989
4990 if (nd_itpop) __pop_itstk();
4991 }
4992
4993 /*
4994 * ROUTINES FOR MISCTF ROSYNCHRONIZE PROCESSING
4995 */
4996
4997 /*
4998 * end of slot call misctf with reason ro sync
4999 */
__exec_rosync_misctf(void)5000 extern void __exec_rosync_misctf(void)
5001 {
5002 register i_tev_ndx tevpi;
5003
5004 __rosync_slot = TRUE;
5005 for (tevpi = __tehdr_rosynci; tevpi != -1; tevpi = __tevtab[tevpi].tenxti)
5006 rosync_call_misctf(tevpi);
5007 /* slot end action turned off all at once later */
5008 /* add the list on to head of tev free list */
5009 __tevtab[__teend_rosynci].tenxti = __tefreelsti;
5010 __tefreelsti = __tehdr_rosynci;
5011 __tehdr_rosynci = __teend_rosynci = -1;
5012 __rosync_slot = FALSE;
5013 }
5014
5015 /*
5016 * call the misctf routine for reason ro synchronize
5017 */
rosync_call_misctf(i_tev_ndx tevpi)5018 static void rosync_call_misctf(i_tev_ndx tevpi)
5019 {
5020 int32 sav_fnam_ind, sav_slin_cnt;
5021 struct t_tfcell *tfcp;
5022 struct tfinst_t tfiwrk;
5023 int32 (*misctf)();
5024
5025 __tfrec = __tevtab[tevpi].tu.tetfrec;
5026 tfcp = get_tfcell(__tfrec);
5027
5028 /* if no misc. tf routine just turn off, nothing to do */
5029 if ((misctf = tfcp->misctf) == NULL)
5030 {
5031 __tfrec->rosync_tevp[__tevtab[tevpi].teitp->itinum] = -1;
5032 return;
5033 }
5034
5035 sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt;
5036 __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
5037
5038 __push_itstk(__tevtab[tevpi].teitp);
5039 /* set up environment that is current implied tf instance */
5040 /* notice assignment of addr. to static works since niled in this rout. */
5041 __tfinst = &tfiwrk;
5042 __tfinst->callx = NULL;
5043 __tfinst->tfstp = NULL;
5044 __tfinst->tfitp = __inst_ptr;
5045 if (__tfrec->tf_func) __tfinst->callx = __tfrec->tfu.callx;
5046 else __tfinst->tfstp = __tfrec->tfu.tfstp;
5047
5048 /* SJM 06/13/1999 - misctf always requires 3rd argument although ignored except for syncon callbacks ?? */
5049 /* FIXME ??? - not 64 bit clean */
5050 (*misctf)((int32) tfcp->data, REASON_ROSYNCH, 0);
5051
5052 __tfrec->rosync_tevp[__inum] = -1;
5053 __pop_itstk();
5054 __tfrec = NULL;
5055 __tfinst = NULL;
5056 __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
5057 }
5058
5059 /*
5060 * call the misctf routine for reason synchronize
5061 *
5062 * this is called once to process every scheduled #0 sync event
5063 * there will be at most one event per call/inst but turned off
5064 * so can be called next cycle of #0 loop
5065 * no way these can be canceled except removed on reset
5066 */
__sync_call_misctf(struct tev_t * tevp)5067 extern void __sync_call_misctf(struct tev_t *tevp)
5068 {
5069 int32 sav_fnam_ind, sav_slin_cnt;
5070 struct t_tfcell *tfcp;
5071 struct tfinst_t tfiwrk;
5072 int32 (*misctf)();
5073
5074 __tfrec = tevp->tu.tetfrec;
5075 tfcp = get_tfcell(__tfrec);
5076 /* if no misc. tf routine just turn off, nothing to do */
5077 if ((misctf = tfcp->misctf) == NULL)
5078 {
5079 __tfrec->sync_tevp[tevp->teitp->itinum] = -1;
5080 return;
5081 }
5082
5083 sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt;
5084 __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
5085
5086 __push_itstk(tevp->teitp);
5087 /* set up environment that is current implied tf instance */
5088 /* notice assignment of addr. to static works since niled in this rout. */
5089 __tfinst = &tfiwrk;
5090 __tfinst->callx = NULL;
5091 __tfinst->tfstp = NULL;
5092 __tfinst->tfitp = __inst_ptr;
5093 if (__tfrec->tf_func) __tfinst->callx = __tfrec->tfu.callx;
5094 else __tfinst->tfstp = __tfrec->tfu.tfstp;
5095
5096 /* SJM 06/13/1999 - misctf always requires 3rd argument although ignored except for syncon callbacks ?? */
5097 /* FIXME ??? - not 64 bit clean */
5098 (*misctf)((int32) tfcp->data, REASON_SYNCH, 0);
5099
5100 __tfrec->sync_tevp[__inum] = -1;
5101 __pop_itstk();
5102 __tfrec = NULL;
5103 __tfinst = NULL;
5104 __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
5105 }
5106
5107 /*
5108 * call the misctf routine for reason reactivate afer delay
5109 *
5110 * 0 is pound 0
5111 */
__setdel_call_misctf(i_tev_ndx tevpi)5112 extern void __setdel_call_misctf(i_tev_ndx tevpi)
5113 {
5114 register struct tevlst_t *telp, *last_telp;
5115 int32 sav_fnam_ind, sav_slin_cnt;
5116 struct t_tfcell *tfcp;
5117 struct tfinst_t tfiwrk;
5118 int32 (*misctf)();
5119
5120 __tfrec = __tevtab[tevpi].tu.tetfrec;
5121 tfcp = get_tfcell(__tfrec);
5122
5123 /* if no misc. tf routine just turn off, nothing to do */
5124 if ((misctf = tfcp->misctf) == NULL) goto free_telst;
5125
5126 sav_fnam_ind = __sfnam_ind; sav_slin_cnt = __slin_cnt;
5127 __sfnam_ind = (int32) __tfrec->tffnam_ind; __slin_cnt = __tfrec->tflin_cnt;
5128
5129 __push_itstk(__tevtab[tevpi].teitp);
5130 /* set up environment that is current implied tf instance */
5131 /* notice assignment of addr. to static works since niled in this rout. */
5132 __tfinst = &tfiwrk;
5133 __tfinst->callx = NULL;
5134 __tfinst->tfstp = NULL;
5135 __tfinst->tfitp = __inst_ptr;
5136 if (__tfrec->tf_func) __tfinst->callx = __tfrec->tfu.callx;
5137 else __tfinst->tfstp = __tfrec->tfu.tfstp;
5138
5139 /* SJM 06/13/1999 - misctf always requires 3rd argument although ignored except for syncon callbacks ?? */
5140 /* FIXME ??? - not 64 bit clean */
5141 (*misctf)((int32) tfcp->data, REASON_REACTIVATE, 0);
5142
5143 __pop_itstk();
5144 __sfnam_ind = sav_fnam_ind; __slin_cnt = sav_slin_cnt;
5145 __tfinst = NULL;
5146
5147 free_telst:
5148 last_telp = NULL;
5149 telp = __tfrec->setd_telst[__tevtab[tevpi].teitp->itinum];
5150 for (; telp != NULL; telp = telp->telnxt)
5151 {
5152 /* but tevpi can not change */
5153 if (tevpi == telp->tevpi)
5154 {
5155 if (last_telp == NULL)
5156 __tfrec->setd_telst[__tevtab[tevpi].teitp->itinum] = telp->telnxt;
5157 else last_telp->telnxt = telp->telnxt;
5158 /* link 1 freed on front */
5159 telp->telnxt = __ltevfreelst;
5160 __ltevfreelst = telp;
5161 __tfrec = NULL;
5162 return;
5163 }
5164 last_telp = telp;
5165 }
5166 __case_terr(__FILE__, __LINE__);
5167 }
5168
5169 /*
5170 * process a tf strdelputp store
5171 *
5172 * know parameter is read write
5173 * know value converted and available here
5174 * know tf isrw never concat and may be either wire or reg
5175 */
__process_putpdel_ev(i_tev_ndx tevpi)5176 extern void __process_putpdel_ev(i_tev_ndx tevpi)
5177 {
5178 register struct expr_t *lhsxp;
5179 register struct tfarg_t *tfap;
5180 register int32 lhslen;
5181 int32 wlen;
5182 word32 *ap, *bp;
5183 byte *sbp;
5184 struct tfrec_t *tfrp;
5185 struct tedputp_t *tedp;
5186 struct dltevlst_t *dlp;
5187
5188 tedp = __tevtab[tevpi].tu.tedputp;
5189 __tevtab[tevpi].tu.tedputp = NULL;
5190
5191 tfrp = tedp->tedtfrp;
5192 tfap = &(tfrp->tfargs[tedp->tedpnum]);
5193
5194 lhsxp = tfap->arg.axp;
5195 lhslen = lhsxp->szu.xclen;
5196 wlen = wlen_(lhslen);
5197 if (__ev_tracing) emit_tputd_trmsg(tedp, tfap);
5198 ap = tedp->tedwp;
5199 bp = &(ap[wlen]);
5200 exec_tfarg_assign(tfap, lhsxp, ap, bp);
5201 /* free the event tf delputp record stored rhs assign to value */
5202 if (lhsxp->x_stren)
5203 { sbp = (byte *) tedp->tedwp; __my_free((char *) sbp, lhslen); }
5204 else __my_free((char *) tedp->tedwp, 2*wlen_(lhslen)*WRDBYTES);
5205
5206 tedp->tedtfrp = (struct tfrec_t *) __tedpfreelst;
5207 __tedpfreelst = tedp;
5208 dlp = tfap->dputp_tedlst[__inum];
5209 /* also link out tevlst element - must be on front */
5210 /* DBGMAYBELEAVE */
5211 if (dlp == NULL || tevpi != dlp->tevpi) __misc_terr(__FILE__, __LINE__);
5212 /* --- */
5213 tfap->dputp_tedlst[__inum] = dlp->terp;
5214 dlp->telp = NULL;
5215 /* put this telst elemnt on free list */
5216 dlp->terp = __dltevfreelst;
5217 __dltevfreelst = dlp;
5218 }
5219
5220 /*
5221 * routine to assign tf arg
5222 * input is a b pointer (b non used if stren) and lhs expr
5223 * __inst_ptr set to right instance
5224 */
exec_tfarg_assign(struct tfarg_t * tfap,struct expr_t * lhsxp,register word32 * ap,register word32 * bp)5225 static void exec_tfarg_assign(struct tfarg_t *tfap, struct expr_t *lhsxp,
5226 register word32 *ap, register word32 *bp)
5227 {
5228 register int32 lhslen;
5229 register byte *sbp;
5230 int32 schd_wire;
5231
5232 /* case 1 procedural assign */
5233 if (tfap->anp->ntyp >= NONWIRE_ST)
5234 { __exec2_proc_assign(lhsxp, ap, bp); return; }
5235
5236 /* case 2: need continuous assign (concat impossible) */
5237 /* case 2a: fi>1 */
5238 lhslen = lhsxp->szu.xclen;
5239 if (lhsxp->x_multfi)
5240 {
5241 /* first update the driver then reeval all drivers */
5242 if (lhsxp->x_stren)
5243 {
5244 sbp = (byte *) ap;
5245 /* notice can just copy this is per inst table for driver */
5246 memcpy(&(tfap->tfdrv_wp.bp[__inum*lhslen]), sbp, lhslen);
5247 }
5248 else __st_perinst_val(tfap->tfdrv_wp, lhslen, ap, bp);
5249 __mdr_assign_or_sched(lhsxp);
5250 return;
5251 }
5252
5253 /* case 2b: fi == 1 conta assign */
5254 if (lhsxp->lhsx_ndel && !__wire_init) schd_wire = TRUE;
5255 else schd_wire = FALSE;
5256 __exec_conta_assign(lhsxp, ap, bp, schd_wire);
5257 }
5258
5259 /*
5260 * emit a strdelputp trace message if tracing on
5261 */
emit_tputd_trmsg(struct tedputp_t * tedp,struct tfarg_t * tfap)5262 static void emit_tputd_trmsg(struct tedputp_t *tedp, struct tfarg_t *tfap)
5263 {
5264 word32 *ap, *bp;
5265 struct tfrec_t *tfrp;
5266 struct expr_t *lhsxp;
5267 char s1[RECLEN], s2[IDLEN];
5268
5269 lhsxp = tfap->arg.axp;
5270 if (tfap->anp->ntyp >= NONWIRE_ST) strcpy(s1, "procedural");
5271 else
5272 {
5273 if (lhsxp->x_multfi) strcpy(s1, "continuous fi>1");
5274 else strcpy(s1, "continuous fi=1");
5275 }
5276 tfrp = tedp->tedtfrp;
5277 if (lhsxp->x_stren)
5278 __st_regab_tostr(s2, (byte *) tedp->tedwp, lhsxp->szu.xclen);
5279 else
5280 {
5281 ap = tedp->tedwp;
5282 bp = &(ap[wlen_(lhsxp->szu.xclen)]);
5283 __regab_tostr(s2, ap, bp, lhsxp->szu.xclen, BHEX, FALSE);
5284 }
5285 __evtr_resume_msg();
5286 __tr_msg("tf_ arg %d at %s in %s strdelputp %s assign value %s\n",
5287 tedp->tedpnum, __bld_lineloc(__wrks1, tfrp->tffnam_ind, tfrp->tflin_cnt),
5288 __msg2_blditree(__wrks2, __inst_ptr), s1, s2);
5289 }
5290
5291 /*
5292 * ROUTINES TO REINITIALIZE PLI STUFF - TFRECS AND VPI ON RESET
5293 */
5294
5295 /*
5296 * during reset reinitialize tfrecs
5297 */
__reinit_tfrecs(void)5298 extern void __reinit_tfrecs(void)
5299 {
5300 register struct tfrec_t *tfrp;
5301
5302 for (tfrp = __tfrec_hdr; tfrp != NULL; tfrp = tfrp->tfrnxt)
5303 reinit_1tfrec(tfrp);
5304
5305 /* free all ro sync events */
5306 if (__tehdr_rosynci != -1)
5307 {
5308 /* add the list on to head of tev free list */
5309 __tevtab[__teend_rosynci].tenxti = __tefreelsti;
5310 __tefreelsti = __tehdr_rosynci;
5311 __tehdr_rosynci = __teend_rosynci = -1;
5312 }
5313 }
5314
5315 /*
5316 * reinit 1 tfrec
5317 */
reinit_1tfrec(struct tfrec_t * tfrp)5318 static void reinit_1tfrec(struct tfrec_t *tfrp)
5319 {
5320 register int32 i, pi;
5321 register struct dltevlst_t *dlp;
5322 register struct tevlst_t *tlp;
5323 struct dltevlst_t *last_dlp;
5324 struct tevlst_t *last_tlp;
5325 struct tfarg_t *tfap;
5326 struct expr_t *xp;
5327 struct mod_t *mdp;
5328 struct dceauxlst_t *dclp;
5329
5330 /* DBG remove --- */
5331 if (tfrp->tf_inmdp == NULL) __misc_terr(__FILE__, __LINE__);
5332 /* ---*/
5333
5334 mdp = tfrp->tf_inmdp;
5335 /* notice arguments start from 1 - 0 is place holder */
5336 /* arg 0 used for func. return value, but tfap[0] not used */
5337 for (pi = 1; pi < tfrp->tfanump1; pi++)
5338 {
5339 tfap = &(tfrp->tfargs[pi]);
5340 memset(tfap->old_pvc_flgs, 0, mdp->flatinum);
5341 memset(tfap->sav_pvc_flgs, 0, mdp->flatinum);
5342 xp = tfap->arg.axp;
5343 for (i = 0; i < mdp->flatinum; i++)
5344 {
5345 tfap->sav_xinfos[i] = NULL;
5346 if ((dlp = tfap->dputp_tedlst[i]) != NULL)
5347 {
5348 for (last_dlp = NULL; dlp != NULL; dlp = dlp->terp) last_dlp = dlp;
5349 last_dlp->terp = __dltevfreelst;
5350 __dltevfreelst = tfap->dputp_tedlst[i];
5351 tfap->dputp_tedlst[i] = NULL;
5352 }
5353 }
5354 if (tfap->tfdrv_wp.bp != NULL) __init_tfdrv(tfap, xp, mdp);
5355 }
5356
5357 for (i = 0; i < mdp->flatinum; i++)
5358 {
5359 if (tfrp->asynchon[i])
5360 {
5361 /* DBG remove ---*/
5362 if (tfrp->pvcdcep[i] == NULL) __misc_terr(__FILE__, __LINE__);
5363 /* --- */
5364
5365 /* SJM 01/02/03 - new algorithm pvcs stay on across reset like vpi */
5366 for (dclp = tfrp->pvcdcep[i]; dclp != NULL; dclp = dclp->dclnxt)
5367 {
5368 /* SJM 05/08/03 - always one inst form */
5369 /* but need to re-initialize previous value */
5370 __init_1instdce_prevval(dclp->ldcep);
5371 }
5372 }
5373 /* still always remove any pending scheduled event */
5374 tfrp->rosync_tevp[i] = -1;
5375 tfrp->sync_tevp[i] = -1;
5376 /* notice any events for these freed elswhere */
5377 if ((tlp = tfrp->setd_telst[i]) != NULL)
5378 {
5379 for (last_tlp = NULL; tlp != NULL; tlp = tlp->telnxt) last_tlp = tlp;
5380 last_tlp->telnxt = __ltevfreelst;
5381 __ltevfreelst = tfrp->setd_telst[i];
5382 tfrp->setd_telst[i] = NULL;
5383 }
5384 }
5385 }
5386
5387 /*
5388 * MISCELLANEOUS ROUTINES
5389 */
5390
5391 /*
5392 * call to malloc that dies if no memory available
5393 * these are normal OS memory allocation with error terminaton
5394 */
__mytf_malloc(int32 size)5395 extern char *__mytf_malloc(int32 size)
5396 {
5397 char *cp;
5398
5399 if ((cp = (char *) malloc((word32) size)) == NULL)
5400 {
5401 __crit_msg(
5402 "**FATAL[1]: No more memory from tf_ call at file %s line %d - %ld bytes memory used\n",
5403 __in_fils[__tfrec->tffnam_ind], __tfrec->tflin_cnt, __mem_use);
5404 __my_exit(4, TRUE);
5405 }
5406 /* DBG remove ---
5407 if (__debug_flg)
5408 __dbg_msg("tf_ allocated %d bytes\n", size);
5409 --- */
5410 return(cp);
5411 }
5412