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