1 /* Copyrght (c) 1993-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  * debugger - interactive environment
30  */
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 
37 #ifdef __linux__
38 #include <sys/types.h>
39 #include <sys/wait.h>
40 #endif
41 
42 #include <signal.h>
43 
44 #include <unistd.h>
45 #include <setjmp.h>
46 
47 #ifdef __DBMALLOC__
48 #include "../malloc.h"
49 #endif
50 
51 #include "v.h"
52 #include "cvmacros.h"
53 
54 /* local prototypes */
55 static void rem_escape_newlines(register char *);
56 static void snap_finish(void);
57 static void setup_interactive(void);
58 static void add_iahist(void);
59 static int32 get_iahcmdnum(void);
60 static void grow_iahtab(void);
61 static void rd_exec_iact_stmt(int32);
62 static void chk_iact_grefs(int32);
63 static void init_iahctrl(struct hctrl_t *);
64 static void init_sched_iathd(struct hctrl_t *);
65 static struct thread_t *bld_immed_iathrd(struct st_t *);
66 static void free_iact_glbs(struct gref_t *, int32);
67 static void renumber_1stmt(struct st_t *, int32, int32);
68 static void renumber_csitemlst(register struct csitem_t *, int32, int32);
69 static void renumber_stlst(register struct st_t *, int32, int32);
70 static int32 prt1_iahist_cmd(int32);
71 static void free_done_iact_control(struct hctrl_t *, int32);
72 static int32 do_dbg_cmd(void);
73 static void cmd_illegal_msg(char *);
74 static int32 dbcmd_prefix_rep(register int32, char *, int32, struct namlst_t *, int32);
75 static void do_dbg_help(void);
76 static void wr_dbg_hlpmsg(char **);
77 static void wr_dbg_lstofcmds(struct namlst_t *, int32);
78 static void dbg_print(void);
79 static char *dbg_bld_expr_val(char *, struct expr_t *, int32, int32, int32);
80 static void dbg_display(void);
81 static void prt_all_disp_exprs(void);
82 static char *bld_prtbasecode(char *, int32, int32, int32);
83 static void do_dbg_expris(void);
84 static char *bld_expr_telltale(char *, struct expr_t *);
85 static void do_dbg_varis(void);
86 static void print_iddecl_ref(struct sy_t *, struct sy_t *);
87 static void do_dbg_whatis(void);
88 
89 /* extern prototypes (maybe defined in this module) */
90 extern char *__my_malloc(int32);
91 extern FILE *__tilde_fopen(char *, char *);
92 extern char *__pv_stralloc(char *);
93 extern struct task_t *__find_thrdtsk(struct thread_t *);
94 extern void __set_dbentry_listline(void);
95 extern void __call_misctfs_iact(void);
96 extern void __vpi_enteriact_trycall(void);
97 extern void __call_misctfs_scope(void);
98 extern void __vpi_iactscopechg_trycall(void);
99 extern int32 __rd_ialine(void);
100 extern void __my_fclose(FILE *);
101 extern void __call_misctfs_finish(void);
102 extern void __vpi_endsim_trycall(void);
103 extern void __get_vtok(void);
104 extern char *__msg_blditree(char *, struct itree_t *, struct task_t *);
105 extern char *__bld_lineloc(char *, word32, int32);
106 extern void __vpi_exitiact_trycall(void);
107 extern int32 __chk_extra_atend(int32);
108 extern char *__prt_vtok(void);
109 extern void __do_iact_disable(struct hctrl_t *, int32);
110 extern char *__to_timstr(char *, word64 *);
111 extern void __write_snapshot(int32);
112 extern void __my_ftime(time_t *, time_t *);
113 extern void __prt_end_msg(void);
114 extern void __add_infil(char *);
115 extern int32 __wide_vval_is0(register word32 *, int32);
116 extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
117 extern char *__my_realloc(char *, int32, int32);
118 extern void __grow_tevtab(void);
119 extern struct st_t *__rd_stmt(void);
120 extern void __chk_lstofsts(struct st_t *);
121 extern void __chk_nodel_lstofsts(struct st_t *);
122 extern struct st_t *__prep_lstofsts(struct st_t *, int32, int32);
123 extern void __free_1stmt(struct st_t *);
124 extern void __free_dceauxlst(struct dceauxlst_t *, int32);
125 extern void __free_dceauxs_only(struct dceauxlst_t *);
126 extern struct st_t *__brktr_exec_1stmt(struct st_t *);
127 extern void __my_free(char *, int32);
128 extern void __ia_warn(int32, char *, ...);
129 extern char *__msg2_blditree(char *, struct itree_t *);
130 extern struct thread_t *__alloc_thrd(void);
131 extern void __add_ev_to_front(register i_tev_ndx);
132 extern void __free_1glb_flds(struct gref_t *);
133 extern char *__get_eval_cstr(struct expr_t *, int32 *);
134 extern void __free_thd_list(struct thread_t *);
135 extern void __free_1thd(struct thread_t *);
136 extern int32 __get_dbcmdnum(char *, struct namlst_t *, int32);
137 extern char *__bld_ambiguous_list(char *, char *, struct namlst_t *, int32);
138 extern void __prt_where_msg(register struct thread_t *);
139 extern void __do_dbg_list(void);
140 extern void __do_dbg_set(void);
141 extern void __do_dbg_info(void);
142 extern void __do_dbg_dis_enable(int32);
143 extern void __dbg_undisplay(void);
144 extern int32 __get_dbg_val(void);
145 extern void __do_dbg_history(void);
146 extern void __do_dbg_emptyhistory(void);
147 extern void __do_dbg_brkpt(int32);
148 extern void __do_dbg_ibrkpt(int32);
149 extern int32 __do_dbg_nextb(void);
150 extern void __do_dbg_delbrkdis(void);
151 extern void __do_dbg_scope(void);
152 extern void __dbg_brk_ignore(void);
153 extern void __dbg_brk_cond(void);
154 extern void __wrap_puts(char *, FILE *);
155 extern void __wrap_putc(int32, FILE *);
156 extern struct expr_t *__rd_iact_expr(void);
157 extern int32 __colto_eol(void);
158 extern void __free_xtree(struct expr_t *);
159 extern char *__strenexpr_tostr(char *, struct expr_t *);
160 extern struct xstk_t *__eval2_xpr(register struct expr_t *);
161 extern int32 __trim1_0val(word32 *, int32);
162 extern char *__strab_tostr(char *, word32 *, int32, int32, int32);
163 extern char *__regab2_tostr(char *, word32 *, word32 *, int32, int32, int32, int32);
164 extern void __bld_xtree(int32);
165 extern int32 __chk_rhsexpr(struct expr_t *, int32);
166 extern int32 __bld_expnode(void);
167 extern void __set_xtab_errval(void);
168 extern char *__msgexpr_tostr(char *, struct expr_t *);
169 extern char *__to_opname(word32);
170 extern char *__to_sytyp(char *, word32);
171 extern char *__bld_showvars_prefix(char *, struct net_t *,
172  struct gref_t *grp);
173 extern struct sy_t *__get_sym(char *, struct symtab_t *);
174 extern int32 __do_vpi_stop(int32);
175 extern void __do_vpi_reset(int32, int32, int32);
176 extern void __emit_vpi_noiact_warn(void);
177 extern void __emit_vpi_iniact_warn(void);
178 extern void __emit_stsk_endmsg(void);
179 extern struct gref_t *__alloc_grtab(struct gref_t *, int32);
180 extern void __init_mod(struct mod_t *, struct sy_t *);
181 extern void __my_dv_flush(void);
182 extern void __wr_dvtimstr(void);
183 extern void __push_wrkitstk(struct mod_t *, int32);
184 extern void __pop_wrkitstk(void);
185 extern void __free_dce_prevval(struct dcevnt_t *, int32, int32);
186 extern int32 __get_dcewid(struct dcevnt_t *, struct net_t *);
187 extern int32 __get_pcku_chars(int32, int32);
188 
189 
190 extern void __cv_msg(char *, ...);
191 extern void __cvsim_msg(char *, ...);
192 extern void __cvsim2_msg(char *, ...);
193 extern void __cvsim3_msg(char *, ...);
194 extern void __pv_warn(int32, char *,...);
195 extern void __sgfwarn(int32, char *, ...);
196 extern void __sgferr(int32, char *, ...);
197 extern void __pv_terr(int32, char *, ...);
198 extern void __arg_terr(char *, int32);
199 extern void __case_terr(char *, int32);
200 extern void __misc_terr(char *, int32);
201 extern void __my_exit(int32, int32);
202 extern void __ia_err(int32 id_num, char *s, ...);
203 
204 extern char __pv_ctab[];
205 
206 /*
207  * STARTUP SIGNAL INITIALIZATION ROUTINES
208  */
209 
210 /*
211  * signal handler during compilation
212  * should put in alarm here
213  */
__comp_sigint_handler(void)214 extern void __comp_sigint_handler(void)
215 {
216  char s1[RECLEN];
217 
218  /* ignore ^c signal in here */
219  signal(SIGINT, SIG_IGN);
220  __cvsim2_msg(
221   "\nInterrupt (^C) occurred during translate/load, really quit? (y/n) ");
222  if (fgets(s1, RECLEN, stdin) == NULL) goto done;
223 
224  if (s1[0] == 'y' || s1[0] == 'Y')
225   {
226    /* put back called signal */
227 #if defined(INTSIGS)
228    signal(SIGINT, __old_int_sig);
229 #else
230    signal(SIGINT, (void (*)()) __old_int_sig);
231 #endif
232    __pv_terr(311, "translate/load terminated by interrupt (^C) signal");
233   }
234 done:
235  /* why need to reset signal handler */
236 #if defined(INTSIGS)
237  signal(SIGINT, __comp_sigint_handler);
238 #else
239  signal(SIGINT, (void (*)()) __comp_sigint_handler);
240 #endif
241 }
242 
243 /*
244  * signal during execution
245  * just set flag here - must be run to top level before catching
246  *
247  * all this does is set switch - caller must reset internal switch
248  * when processed or ignored
249  */
__sim_sigint_handler(void)250 extern void __sim_sigint_handler(void)
251 {
252  /* SJM 07/31/01 - think need message to indicate interrupt */
253  /* DBG remove -- */
254  __cvsim2_msg( "<INTERRUPT>\n");
255  /* --- */
256  __pending_enter_iact = TRUE;
257  __iact_reason = IAER_CTRLC;
258  /* if stepping, disable as if step completed */
259  __single_step = FALSE;
260  __step_rep_cnt = 0;
261  __step_lini = -1;
262  __step_ifi = -1;
263 /* REMOVEME - no longer supporting SunOS - maybe needed for hpux? */
264 #if (defined(__sparc) && defined(__SVR4))
265  /* LOOKATME _ not sure why needed iact ^c leaves EINTR uncleared ?? */
266  if (__cmd_s != NULL) clearerr(__cmd_s);
267  clearerr(stdin);
268 #endif
269 #if (defined(__i386__) && defined(__SVR4))
270  /* LOOKATME _ not sure why needed iact ^c leaves EINTR uncleared ?? */
271  if (__cmd_s != NULL) clearerr(__cmd_s);
272  clearerr(stdin);
273 #endif
274 }
275 
276 /*
277  * interface to (only way program quits) to reset callers signal handler
278  *
279  * normally do_exit true but to return to caller called with do exit F
280  */
__my_exit(int32 rc,int32 do_exit)281 extern void __my_exit(int32 rc, int32 do_exit)
282 {
283  int32 i;
284 
285 
286  /* put back entry signal */
287 #ifdef INTSIGS
288    signal(SIGINT, __old_int_sig);
289 #else
290    signal(SIGINT, (void (*)()) __old_int_sig);
291 #endif
292 
293  /* for antrim flush buffers */
294  /* always flush here in case of $finish */
295  if (__dv_fd != -1)
296   {
297    /* SJM 10/08/99 - need to write time at end for some wave form viewers */
298    __wr_dvtimstr();
299    __my_dv_flush();
300   }
301  if (__log_s != NULL) fflush(__log_s);
302  if (__tr_s != NULL) fflush(__tr_s);
303  for (i = 0; i < 31; i++)
304   {
305    if (__mulchan_tab[i].mc_s != NULL) fflush(__mulchan_tab[i].mc_s);
306   }
307  if (do_exit) exit(rc);
308  return;
309 }
310 
311 /*
312  * INTERACTIVE SETUP ROUTINES
313  */
314 
315 /*
316  * initialize interactive environment just before simulation begins
317  * but after all initialization wire evaluation finished
318  *
319  * since various interactive system tasks can appear in normal source
320  * this initializes those things - when interactive called real init done
321  * notice this is run with __iact_state off
322  */
__init_interactive(void)323 extern void __init_interactive(void)
324 {
325  register int32 i;
326  struct sy_t *syp;
327 
328  /* set up listing file - nothing open and no line pos. file cached */
329  __filpostab = NULL;
330  __list_cur_fd = -1;
331  /* use can change this with :set - number is one less than no. to list */
332  /* since prt src lines is from - to */
333  __list_cur_listnum = 9;
334  /* start at 1st top level */
335  /* force setting on first :l command */
336  __list_cur_ifi = -1;
337  __nxt_bpnum = 1;
338  __bphdr = NULL;
339  __dispxhdr = NULL;
340  __nxt_dispxnum = 1;
341  __single_step = FALSE;
342  __step_rep_cnt = 0;
343  __step_from_thread = FALSE;
344  __step_match_itp = NULL;
345  __step_lini = -1;
346  __step_ifi = -1;
347  __verbose_step = FALSE;
348  __last_iasytp = NULL;
349 
350  __last_stepitp = NULL;
351  __last_steptskp = NULL;
352  __last_stepifi = -1;
353  __last_brktime = 0xffffffffffffffffULL;
354 
355  /* $scope start at first top level module - no old scope to push */
356  __scope_ptr = __it_roots[0];
357  __scope_tskp = NULL;
358 
359  /* allocate interactive module - re-initialized each time iact entered */
360  /* 08/18/99 - for now only expr tab and glb tab fields used */
361  __iact_mdp = (struct mod_t *) __my_malloc(sizeof(struct mod_t));
362 
363  syp = (struct sy_t *) __my_malloc(sizeof(struct sy_t));
364  syp->synam = __pv_stralloc("**IACT WORK**");
365  syp->sydecl = TRUE;
366 
367  __init_mod(__iact_mdp, syp);
368  __iact_mdp->flatinum = 1;
369  syp->el.emdp = __iact_mdp;
370 
371  /* default is now, use scope of entry in interactive, :set to use old */
372  __iact_scope_chg = TRUE;
373  __dbg_dflt_base = BHEX;
374 
375  /* notice line count and :list command line are unrelated - line count is */
376  /* source line number or command history number */
377  __lin_cnt = 1;
378  /* this forces getc to read from read interactive line */
379  __in_s = NULL;
380  __file_just_op = FALSE;
381  __first_linetok = FALSE;
382  __cmd_fnam = NULL;
383  __cmd_s = NULL;
384 
385  /* special code in get_env_sym so no environment here */
386  __venviron[0] = NULL;
387 
388  /* LOOKATME - should read .[cverdbinit?] with history off */
389  __iahwrklen = 2*IDLEN + 8;
390  __iahwrkline = __my_malloc(__iahwrklen);
391  __hist_cur_listnum = 20;
392  __echo_iactcmds_tolog = TRUE;
393 
394  /* setup history */
395  /* FIXME - need to wrap table not continue growing without limit */
396  __iahsiz = IAHISTSIZ;
397  __iahtab = (struct iahist_t *) __my_malloc(__iahsiz*sizeof(struct iahist_t));
398  /* must start with 0 since first add moves to real 1 start */
399  __iah_lasti = 0;
400  /* indexed from 1 but initialize from 0 */
401  for (i = 0; i < __iahsiz; i++)
402   { __iahtab[i].iah_lp = NULL; __iahtab[i].iah_hcp = NULL; }
403  __hctrl_hd =__hctrl_end = NULL;
404 }
405 
406 /*
407  * INTERACTIVE DEBUGGER ROUTINES
408  */
409 
410 /*
411  * execute the interactive control loop
412  *
413  * unless -<num> or <num> form or not history on put into history list
414  * only break (ctrl-c), $stop, or -s command option tranfer control to here
415  * continue (.) does not return here unless ctrl-c or $stop() execed
416  * when events exhausted looks like $finish hit
417  * commands executed from here return to here
418  *
419  * debugger commands are not added to the history list
420  * this runs with ctrl-c (int32) disabled
421  * upon entry, interrupt signal is SIGIGN
422  * also no current thread - run between processed events
423  * if entry from interactive non immediate $stop, no scope or file change
424  */
__do_interactive_loop(void)425 extern void __do_interactive_loop(void)
426 {
427  int32 histcmd_num, hist_rexec, rv, sav_lin_cnt, sav_cur_fnam_ind;
428  int32 chg_scope, still_stepping;
429  FILE *sav_cmd_s, *f;
430  char *sav_cmd_fnam;
431  struct iahist_t *iahp;
432  struct task_t *tskp;
433  struct sy_t *syp;
434  char s1[RECLEN], s2[RECLEN];
435 
436  /* where call finish callbacks and exit when interactive turned off */
437  signal(SIGINT, SIG_IGN);
438 
439  /* things needed on any entry to interactive */
440  /* if interactive mode off, just finish */
441  __iact_state = TRUE;
442  __pending_enter_iact = FALSE;
443  if (__no_iact) snap_finish();
444  /* if first time do some setup - not done after :reset or $reset */
445  if (!__iasetup)
446   {
447    setup_interactive();
448    __iasetup = TRUE;
449    __cvsim2_msg("Type :help for help\n");
450   }
451  if (!__ia_entered)
452   {
453    if (__cmd_start_fnam != NULL)
454     {
455      /* this was opened once to check but may be problem since then */
456      if ((f = __tilde_fopen(__cmd_start_fnam, "r")) == NULL)
457       {
458        __pv_warn(505,
459         "now cannot open -i startup interactive input file %s - using stdin",
460         __cmd_start_fnam);
461       }
462      else
463       {
464        __cmd_s = f;
465        __cmd_fnam = __pv_stralloc(__cmd_start_fnam);
466       }
467     }
468    __ia_entered = TRUE;
469   }
470  hist_rexec = FALSE;
471  sav_cmd_s = NULL;
472  sav_cmd_fnam = NULL;
473  sav_cur_fnam_ind = -1;
474  sav_lin_cnt = -1;
475 
476  /* for entry from iact ($stop?), use original scope of interactive */
477  /* unless turned off or sim not started, use entry proc. scope as scope */
478  if (__iact_scope_chg && __suspended_thd != NULL)
479   {
480    /* scheme if that is last thread (pending) was in task move to task */
481    /* if enterered from ^c but evaling event, may want scope change */
482    if (__fcspi >= 0) tskp = __fcstk[__fcspi];
483    else if (__suspended_thd->th_fj) tskp = __find_thrdtsk(__suspended_thd);
484    else tskp = __suspended_thd->assoc_tsk;
485    /* this pushes scope since iact flag on */
486    __scope_ptr = __suspended_itp;
487    __scope_tskp = tskp;
488    chg_scope = TRUE;
489   }
490  else chg_scope = FALSE;
491  /* whenever enter iact, must push scope (needs to be in inst. ptr) */
492  __push_itstk(__scope_ptr);
493 
494  /* notice list line and scope now unrelated - but always can set from */
495  /* suspended thread next statement */
496  __set_dbentry_listline();
497 
498  /* if stepping repeat count, decrement and continue execing */
499  still_stepping = FALSE;
500  if (__iact_reason == IAER_STEP && --__step_rep_cnt > 0)
501   {
502    /* save moved to line but continue stepping */
503    __single_step = TRUE;
504    __verbose_step = TRUE;
505    if (__suspended_thd == NULL || __suspended_thd->thnxtstp == NULL)
506     __step_from_thread = FALSE;
507    still_stepping = TRUE;
508    goto do_ret;
509   }
510  if (__tfrec_hdr != NULL) __call_misctfs_iact();
511  if (__have_vpi_actions) __vpi_enteriact_trycall();
512 
513  if (chg_scope)
514   {
515    if (__tfrec_hdr != NULL) __call_misctfs_scope();
516    if (__have_vpi_actions) __vpi_iactscopechg_trycall();
517   }
518  /* process and pending display commands */
519  if (__dispxhdr != NULL) prt_all_disp_exprs();
520 
521 again:
522  /* hist rexec requires command and line no. from history - put back here */
523  /* re-execed history and now re-entering debugger so must change */
524  /* to input line world */
525  if (hist_rexec)
526   {
527    __cmd_s = sav_cmd_s;
528    __cmd_fnam = sav_cmd_fnam;
529    __cur_fnam_ind  = sav_cur_fnam_ind;
530    __cur_fnam = __in_fils[__cur_fnam_ind];
531    __lin_cnt = sav_lin_cnt;
532    hist_rexec = FALSE;
533   }
534 
535  /* write prompt if to screen if needed and/or to log file if exists */
536  /* here need to use next history location even though net yet filled */
537  if (__cmd_s == NULL && isatty(fileno(stdin)))
538   __cvsim2_msg("C%d > ", __iah_lasti + 1);
539  /* LOOKATME - log file output only because typed in from terminal */
540  if (__echo_iactcmds_tolog && __log_s != NULL)
541   __cvsim3_msg("C%d > ", __iah_lasti + 1);
542 
543  /* first read the entire command (possible multiple \[new line] lines */
544  /* notice only $finish gets out of this loop */
545  if (__vin_top > 0) __misc_terr(__FILE__, __LINE__);
546  rv =__rd_ialine();
547  if (rv == TEOF)
548   {
549    if (__cmd_s != NULL)
550     {
551      /* LOOKATME - think this is unneeded */
552      clearerr(__cmd_s);
553      __my_fclose(__cmd_s);
554      __cmd_s = NULL;
555      __cmd_fnam = NULL;
556      __cur_fnam = __in_fils[1];
557      __cur_fnam_ind = __cmd_ifi;
558      /* after close file must emit prompt */
559     }
560    else
561     {
562      if (isatty(fileno(stdin)))
563       {
564        __ia_err(1403,
565         "EOF (^D or ^C) read from tty stdin - use :q or $finish; to exit program");
566        clearerr(stdin);
567        goto again;
568       }
569      /* cver run from batch file - on eof of stdin execute $finish */
570      __ia_err(1406,
571       "EOF on non tty stdin (simulation run from script) - $finish executed");
572      if (__tfrec_hdr != NULL) __call_misctfs_finish();
573      if (__have_vpi_actions) __vpi_endsim_trycall();
574      __my_exit(2, TRUE);
575     }
576   }
577  /* if no $input (or -i) file, line is command number */
578  if (__cmd_s == NULL) __lin_cnt = __iah_lasti;
579 num_reenable:
580  __visp->vichp = __iahwrkline;
581  /* since keywords ok in interactive, set beginning of line */
582  __first_num_eol = TRUE;
583 
584  /* this is command parsing that requires tokenization */
585  __get_vtok();
586  if (__toktyp == TEOF) goto again;
587 
588  switch ((byte) __toktyp) {
589   case TEOF: __case_terr(__FILE__, __LINE__); break;
590   case COLON:
591    __get_vtok();
592    if (__toktyp == TEOF)
593     {
594      if (__scope_tskp != NULL) syp = __scope_tskp->tsksyp;
595      else syp = __scope_ptr->itip->imsym;
596      __cvsim_msg("scope: %s (at %s and :list at %s)\n",
597       __msg_blditree(__xs, __scope_ptr, __scope_tskp),
598       __bld_lineloc(s1, syp->syfnam_ind, syp->sylin_cnt),
599       __bld_lineloc(s2, (word32) __list_cur_ifi, __list_arg_lini));
600      goto again;
601     }
602    /* : debugger commands always go on history list unless hist re-exec */
603    if (__history_on && !hist_rexec) add_iahist();
604    /* implement : [debugger command] - handles errors */
605    if (!do_dbg_cmd())
606     {
607      /* if debug command some kind of step, if rexeced restore iact loc. */
608      if (hist_rexec)
609       {
610        __cmd_s = sav_cmd_s;
611        __cmd_fnam = sav_cmd_fnam;
612        __cur_fnam_ind  = sav_cur_fnam_ind;
613        __cur_fnam = __in_fils[__cur_fnam_ind];
614        __lin_cnt = sav_lin_cnt;
615        hist_rexec = FALSE;
616       }
617      /* here even if re-exec dot, still treat as new step */
618      __step_lini = -1;
619      __step_ifi = -1;
620      goto do_ret;
621     }
622    else goto again;
623   case DOT:
624    __step_lini = -1;
625    __step_ifi = -1;
626 do_ret:
627    if (!still_stepping && __have_vpi_actions) __vpi_exitiact_trycall();
628 
629    __iact_state = FALSE;
630    /* if ^c hit in interactive debugger, unless command handles just ignore */
631    /* this is needed to stop, from immediate statement dbg enter */
632    /* on entry always push a scope, but must pop away before running again */
633    __pop_itstk();
634   /* need to enable sim sigint32 handler since turned off in iact loop */
635 #if defined(INTSIGS)
636    signal(SIGINT, __sim_sigint_handler);
637 #else
638    signal(SIGINT, (void (*)()) __sim_sigint_handler);
639 #endif
640    __pending_enter_iact = FALSE;
641    __iact_reason = IAER_UNKN;
642    return;
643   case SEMI:
644    if (__optimized_sim)
645     {
646      /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
647      cmd_illegal_msg("';' step with no trace (use '.')");
648      goto again;
649     }
650 
651    /* ; statement step with no trace */
652 step_setup:
653    __single_step = TRUE;
654    __step_rep_cnt = 1;
655    if (__iact_reason == IAER_CTRLC || __suspended_thd == NULL
656     || __suspended_thd->thnxtstp == NULL) __step_from_thread = FALSE;
657    __chk_extra_atend(TRUE);
658    goto do_ret;
659   case COMMA:
660    if (__optimized_sim)
661     {
662      /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
663      cmd_illegal_msg("',' step with trace (use '.')");
664      goto again;
665     }
666    /* , statement step with debugger trace */
667    /* notice -t tracing additional and independent */
668    __verbose_step = TRUE;
669    goto step_setup;
670   case MINUS:
671    __get_vtok();
672    if (__toktyp != NUMBER)
673     {
674      __ia_err(1410, "minus disable command number expected: %s read",
675       __prt_vtok());
676      goto again;
677     }
678    /* this emits own error */
679    if ((histcmd_num = get_iahcmdnum()) == -1) goto again;
680 
681    iahp = &(__iahtab[histcmd_num]);
682    if (iahp->iah_hcp == NULL)
683     {
684      __ia_err(1412, "-%d disable failed: command already completed",
685       histcmd_num);
686      goto again;
687     }
688    /* disable the command and free control record */
689    __do_iact_disable(iahp->iah_hcp, FALSE);
690    goto again;
691   case NUMBER:
692    /* this emits own error */
693    if ((histcmd_num = get_iahcmdnum()) == -1) goto again;
694    /* since need eventual history support, free if needed and reparse */
695    if (__iahtab[histcmd_num].iah_hcp != NULL)
696     {
697      __ia_err(1416, "attempt to re-execute C%d failed: command not completed",
698       histcmd_num);
699      goto again;
700     }
701    /* must copy since can edit new and new probably goes in history */
702    strcpy(__iahwrkline, __iahtab[histcmd_num].iah_lp);
703    rem_escape_newlines(__iahwrkline);
704    /* save all line loc. state and set to history command no. */
705    sav_cmd_s = __cmd_s;
706    __cmd_s = NULL;
707    sav_cmd_fnam = __cmd_fnam;
708    __cmd_fnam = NULL;
709    sav_cur_fnam_ind = __cur_fnam_ind;
710    __cur_fnam_ind = __cmd_ifi;
711    __cur_fnam = __in_fils[1];
712    sav_lin_cnt = __lin_cnt;
713    __lin_cnt = histcmd_num;
714    hist_rexec = TRUE;
715    goto num_reenable;
716   default:
717    /* schedule non immediate but never leave debugger from Verilog cmd */
718    rd_exec_iact_stmt(hist_rexec);
719    goto again;
720  }
721 }
722 
723 /*
724  * when reparsing from history list must remove all escaped new lines
725  * since need to emit error message with only loc. history
726  */
rem_escape_newlines(register char * lp)727 static void rem_escape_newlines(register char *lp)
728 {
729  for (; *lp != '\0'; lp++)
730   {
731    if (*lp == '\\') { if (lp[1] == '\n') { *lp = ' '; lp[1] = ' '; lp++; } }
732   }
733 }
734 
735 /*
736  * emit error if extra characters at end of line
737  * return F if more on line
738  */
__chk_extra_atend(int32 emit_err)739 extern int32 __chk_extra_atend(int32 emit_err)
740 {
741  register char *chp;
742 
743  chp = __visp->vichp;
744  while (vis_white_(*chp)) chp++;
745  if (*chp != '\0')
746   {
747    if (emit_err)
748     {
749      __ia_err(1413,
750       "interactive command extra characters [%s] at end discarded", chp);
751     }
752    return(FALSE);
753   }
754  return(TRUE);
755 }
756 
757 /*
758  * routine to write snapshot and quit on interrupt for debugging
759  * notice may not be scope when this called
760  */
snap_finish(void)761 static void snap_finish(void)
762 {
763  char s1[RECLEN];
764 
765  __call_misctfs_finish();
766  if (__have_vpi_actions) __vpi_endsim_trycall();
767 
768  /* return from interrupt signal handler */
769  __cvsim_msg(
770   "\nSimulation terminated by interrupt (^C) now %s (interactive debugger disabled)\n",
771   __to_timstr(s1, &__simtime));
772  if (__intsig_prt_snapshot)
773   {
774    /* DBG FIXME - for now just using large number */
775    if (__debug_flg) __write_snapshot(1000);
776    else __write_snapshot(DFLT_SNAP_EVS);
777   }
778 
779  if (__verbose)
780   {
781    __my_ftime(&__end_time, &__end_mstime);
782    __prt_end_msg();
783   }
784  __my_exit(0, TRUE);
785 }
786 
787 /*
788  * setup the interactive loop - called first time interactive started only
789  * once setup just leave special interactive file on visp stack
790  */
setup_interactive(void)791 static void setup_interactive(void)
792 {
793  /* input looks like reading from macro that is read ia line */
794  /* this justs stays present during simulation */
795  __visp = __vinstk[__vin_top];
796  __visp->vilin_cnt = 0;
797  __visp->vifnam_ind = __cmd_ifi;
798  __visp->vi_s = NULL;
799  /* this is set after each line is read */
800  __visp->vichp = NULL;
801 
802  if (__cmd_s == NULL)
803   {
804    /* file is stdin */
805    __cur_fnam = __in_fils[1];
806    __cur_fnam_ind = __cmd_ifi;
807    /* line count will be set to command no. each time */
808    __lin_cnt = 0;
809   }
810  else
811   {
812    /* start reading from -i interactive file */
813    __add_infil(__cmd_fnam);
814    __cur_fnam_ind = __last_inf;
815    __cmd_fnam = __in_fils[__cur_fnam_ind];
816    __lin_cnt = 0;
817   }
818  __lasttoktyp = UNDEF;
819  return;
820 
821  /* -- FIXME - ADD KEY (for now no key file)
822  -* first entry to interactive - open key file if possible *-
823  if (__key_fnam != NULL)
824   {
825    if ((__key_s = __tilde_fopen(__key_fnam, "w")) == NULL)
826     {
827      __ia_err(1414,
828       "cannot open -k interactive input key file %s - trying default",
829       __key_fnam);
830      __my_free(__key_fnam, strlen(__key_fnam) + 1);
831      __key_fnam = NULL;
832      goto no_explicit;
833     }
834    return;
835   }
836 
837 no_explicit:
838  if ((__key_s = __tilde_fopen(DFLTKEYFNAM, "w")) == NULL)
839   {
840    __ia_err(1415, "cannot open default key file %s - no key file",
841     DFLTKEYFNAM);
842    return;
843   }
844  __key_fnam = __my_malloc(strlen(DFLTKEYFNAM) + 1);
845  strcpy(__key_fnam, DFLTKEYFNAM);
846  --- */
847 }
848 
849 /*
850  * add a new entry to history queue - even if error entry must
851  * go in queue so can be edited
852  * this must be called after command read
853  *
854  * FIXME - ksh style editing not yet implemented
855  */
add_iahist(void)856 static void add_iahist(void)
857 {
858  struct iahist_t *iahp;
859 
860  if (++__iah_lasti >= __iahsiz) grow_iahtab();
861  iahp = &(__iahtab[__iah_lasti]);
862  iahp->iah_lp = __pv_stralloc(__iahwrkline);
863  iahp->iah_hcp = NULL;
864  iahp->iah_itp = NULL;
865 }
866 
867 /*
868  * check command number - message and F returned on error
869  * cannot use nd_ndxnum because no IS forms here and just need value
870  * notice both iahtab and command number start at 1 (0 unused)
871  */
get_iahcmdnum(void)872 static int32 get_iahcmdnum(void)
873 {
874  int32 base, cno;
875 
876  if (__itoklen > WBITS)
877   {
878    if (!vval_is0_(&(__acwrk[1]), __itoklen - WBITS)
879     || !vval_is0_(__bcwrk, __itoklen))
880     {
881      base = BHEX;
882 prt_err:
883      __ia_err(1418, "command history number %s invalid or out of range",
884       __regab_tostr(__xs, __acwrk, __bcwrk, __itoklen, base, FALSE));
885      return(-1);
886     }
887   }
888  else
889   {
890     if (!vval_is0_(__bcwrk, __itoklen)) { base = BHEX; goto prt_err; }
891   }
892  cno = (int32) __acwrk[0];
893  if (cno < 1 || cno - 1 > __iah_lasti) { base = BDEC; goto prt_err; }
894  return(cno);
895 }
896 
897 /*
898  * grow the interactive history table - no freeing and wrap for now
899  */
grow_iahtab(void)900 static void grow_iahtab(void)
901 {
902  register int32 i;
903  int32 old_iahsiz, osize, nsize;
904 
905  old_iahsiz = __iahsiz;
906  osize = old_iahsiz*sizeof(struct iahist_t);
907  __iahsiz = (3*__iahsiz)/2;
908  nsize = __iahsiz*sizeof(struct iahist_t);
909  __iahtab = (struct iahist_t *) __my_realloc((char *) __iahtab, osize,
910   nsize);
911  for (i = old_iahsiz; i < __iahsiz; i++)
912   { __iahtab[i].iah_lp = NULL; __iahtab[i].iah_hcp = NULL; }
913 }
914 /*
915  * ROUTINES TO IMPLMENT VERILOG STATEMENT EXECUTION DEBUGGER
916  */
917 
918 /* special external for setjmp environment - only used in v_ms.c */
919 jmp_buf __iact_jmpbuf;
920 jmp_buf __reset_jmpbuf;
921 
922 /*
923  * read and execute a Verilog interactive statement
924  * errors here go into total but maybe should not
925  *
926  * must execute statement with delay as named block with no vars
927  */
rd_exec_iact_stmt(int32 hist_rexec)928 static void rd_exec_iact_stmt(int32 hist_rexec)
929 {
930  int32 sav_err_cnt, sav_sfnam_ind, sav_slin_cnt, immed_exec;
931  int32 sav_itspi, sav_st_trace, sfnind, slcnt, first_stmt;
932  struct st_t *stp, *stp2, *stp3;
933  struct iahist_t *iahp;
934  struct hctrl_t *hcp;
935 
936  /* free any globals from immediate exec unless monitor/strobe sys task */
937  __iact_can_free = TRUE;
938 
939  /* DBG remove -- */
940  if (__iact_dcehdr != NULL) __misc_terr(__FILE__, __LINE__);
941  /* --- */
942 
943  sav_sfnam_ind = __sfnam_ind;
944  sav_slin_cnt = __slin_cnt;
945  __sfnam_ind = __cur_fnam_ind;
946  __slin_cnt = __lin_cnt;
947  sav_err_cnt = __pv_err_cnt;
948 
949  /* on setup returns 0, if get here from call to long jump, all done */
950  if (setjmp(__iact_jmpbuf) != 0)
951   {
952    /* get here only on error - must skip and read token or macro vinstk */
953    /* will not be popped back to 0 */
954    for (;;) { if (__toktyp == TEOF) break; __get_vtok(); }
955    /* possible that parse error occured with something pushed back */
956    __lasttoktyp = UNDEF;
957    /* LOOKATME - may be minor memory leak for compound stmt with errors */
958    goto free_ds;
959   }
960  __iact_stmt_err = FALSE;
961  first_stmt = TRUE;
962 more_stmts:
963  /* if error almost certainly with go to setdump code */
964  /* unless undeclared problem */
965  if ((stp = __rd_stmt()) == NULL) { __iact_stmt_err = TRUE; goto free_ds; }
966 
967  if (__pv_err_cnt != sav_err_cnt)
968   { __iact_stmt_err = TRUE; goto free_stmts_done; }
969 
970  /* since know syntax good errors here, do not return */
971  __cur_tsk = NULL;
972  __iact_must_sched = FALSE;
973  __chk_lstofsts(stp);
974  if (__pv_err_cnt != sav_err_cnt)
975   { __iact_stmt_err = TRUE; goto free_stmts_done; }
976  __nbsti = -1;
977  __task_has_delay = FALSE;
978  __task_has_tskcall = FALSE;
979  /* $stop or any loop in interactive requires scheduling */
980  __chk_nodel_lstofsts(stp);
981  if (__pv_err_cnt != sav_err_cnt)
982   { __iact_stmt_err = TRUE; goto free_stmts_done; }
983  if (__task_has_delay || __task_has_tskcall || __iact_must_sched)
984   immed_exec = FALSE;
985  else immed_exec = TRUE;
986 
987  /* notice always re-execing from history in current scope */
988  /* so to reenable an edge or change breakpoint user must insure either */
989  /* uses rooted names or scope is set to right place */
990  /* check and emit warning for non rooted interactive globals if from */
991  /* history re-exec since no way to tell if from same itree loc. */
992  chk_iact_grefs(hist_rexec);
993 
994  /* delay times are tfmt time units not time unit from current scope */
995  __sav_mtime_units = __inst_mod->mtime_units;
996  __inst_mod->mtime_units = __tfmt_units;
997  /* rest of fields used from curr scope itree location */
998  __prpsti = 0;
999  __nbsti = -1;
1000  __prpstk[0] = NULL;
1001  __iact_dcehdr = NULL;
1002  stp = __prep_lstofsts(stp, FALSE, FALSE);
1003 
1004  if (__pv_err_cnt != sav_err_cnt)
1005   {
1006    __iact_stmt_err = TRUE;
1007 free_stmts_done:
1008    /* interactive always exactly 1 inst. */
1009    if (__iact_can_free)
1010     {
1011      for (stp2 = stp; stp2 != NULL;)
1012       { stp3 = stp2->stnxt; __free_1stmt(stp2); stp2 = stp3; }
1013     }
1014 free_ds:
1015    /* SJM 01/02/03 - since never gening iops for interactive - ok because */
1016    /* only get here on error */
1017    if (__iact_can_free && __iact_dcehdr != NULL)
1018     {
1019      __free_dceauxlst(__iact_dcehdr, 1);
1020      __iact_dcehdr = NULL;
1021     }
1022 
1023    if (__grwrknum > 0)
1024     {
1025      register int32 gri;
1026      int32 osize, nsize;
1027      struct gref_t *grp;
1028 
1029      /* for monitor/strobe must add globals to iact mod table */
1030      if (__iact_can_free)
1031       {
1032        grp = &(__grwrktab[0]);
1033        for (gri = 0; gri < __grwrknum; gri++, grp++) __free_1glb_flds(grp);
1034       }
1035      else
1036       {
1037        /* need to copy grefs to iact module gr table so when interactive */
1038        /* scheduled statement executes can access grefs */
1039        if (__iact_mdp->mgrnum == 0)
1040         {
1041          __iact_mdp->mgrtab = (struct gref_t *)
1042            __my_malloc(__grwrknum*sizeof(struct gref_t));
1043          memcpy(__iact_mdp->mgrtab, __grwrktab,
1044           __grwrknum*sizeof(struct gref_t));
1045         }
1046        else
1047         {
1048          osize = __iact_mdp->mgrnum*sizeof(struct gref_t);
1049          nsize = (__iact_mdp->mgrnum + __grwrknum)*sizeof(struct gref_t);
1050          __iact_mdp->mgrtab = (struct gref_t *)
1051           __my_realloc((char *) __inst_mod->mgrtab, osize, nsize);
1052 
1053          memcpy(&(__iact_mdp->mgrtab[__iact_mdp->mgrnum]), __grwrktab,
1054           __grwrknum*sizeof(struct gref_t));
1055         }
1056        __iact_mdp->mgrnum += __grwrknum;
1057        /* then fix up expr ptrs for all */
1058        grp = &(__iact_mdp->mgrtab[0]);
1059        for (gri = 0; gri < __iact_mdp->mgrnum; gri++, grp++)
1060         { grp->gxndp->ru.grp = grp; }
1061       }
1062      __grwrknum = 0;
1063     }
1064    goto done;
1065   }
1066 
1067  if (immed_exec)
1068   {
1069    /* DBG remove -- */
1070    if (__iact_dcehdr != NULL) __misc_terr(__FILE__, __LINE__);
1071    /* --- */
1072 
1073    if (__history_on && !hist_rexec && first_stmt) add_iahist();
1074    /* in case exit with ^c (infinite loop?) restore entry itree loc. */
1075    sav_itspi = __itspi;
1076    /* must never trace immediate debugger commands */
1077    sav_st_trace = __st_tracing;
1078    __st_tracing = FALSE;
1079    /* notice normally no thread while in interactive mode */
1080    __cur_thd = bld_immed_iathrd(stp);
1081    __cur_thd->th_itp = __scope_ptr;
1082    for (;;)
1083     {
1084      stp = __brktr_exec_1stmt(stp);
1085      if (stp == NULL) break;
1086      if (__pending_enter_iact)
1087       {
1088        __cvsim2_msg(
1089         "\nInterrupt (^C) during immediate interactive execution, reenter debugger? (y/n) ");
1090        if (fgets(__xs, RECLEN, stdin) != NULL
1091         && (__xs[0] == 'y' || __xs[0] == 'Y'))
1092         {
1093          __pending_enter_iact = FALSE;
1094          /* may be executing xmr func. when ^c hit */
1095          __itspi = sav_itspi;
1096          break;
1097         }
1098       }
1099     }
1100    __st_tracing = sav_st_trace;
1101    /* DBG remove --- */
1102    if (__cur_thd == NULL) __misc_terr(__FILE__, __LINE__);
1103    /* ---*/
1104    /* notice thread just used as dummy place holder so nothing used */
1105    __my_free((char *) __cur_thd, sizeof(struct thread_t));
1106    __cur_thd = NULL;
1107    goto free_stmts_done;
1108   }
1109 
1110  /* build and link on to history list the ia statement */
1111  hcp = (struct hctrl_t *) __my_malloc(sizeof(struct hctrl_t));
1112  init_iahctrl(hcp);
1113 
1114  sfnind = __cmd_ifi;
1115  if (hist_rexec)
1116   {
1117    iahp = &(__iahtab[__lin_cnt]);
1118    hcp->hc_lini = __lin_cnt;
1119    iahp->iah_hcp = hcp;
1120    hcp->hc_ifi = __cmd_ifi;
1121    hcp->hc_iahp = iahp;
1122    slcnt = __lin_cnt;
1123   }
1124  else if (__history_on)
1125   {
1126    add_iahist();
1127    iahp = &(__iahtab[__iah_lasti]);
1128    hcp->hc_lini = __iah_lasti;
1129    iahp->iah_hcp = hcp;
1130    hcp->hc_ifi = __cmd_ifi;
1131    hcp->hc_iahp = iahp;
1132    slcnt = __iah_lasti;
1133   }
1134  else slcnt = 1;
1135 
1136  /* always put on end of doubly linked list */
1137  renumber_1stmt(stp, sfnind, slcnt);
1138 
1139  hcp->hc_stp = stp;
1140  hcp->hc_itp = __scope_ptr;
1141  if (__hctrl_hd == NULL) __hctrl_hd = __hctrl_end = hcp;
1142  else
1143   {
1144    __hctrl_end->hc_nxt = hcp;
1145    hcp->hc_prev = __hctrl_end;
1146    __hctrl_end = hcp;
1147   }
1148  hcp->hc_dcelst = __iact_dcehdr;
1149  __iact_dcehdr = NULL;
1150 
1151  /* allocate new gref table for later use if command in history list execed */
1152  /* only freed if statement removed from history list */
1153  if (__grwrknum > 0)
1154   {
1155    hcp->hc_grtab = __alloc_grtab(__grwrktab, __grwrknum);
1156    hcp->hc_numglbs = __grwrknum;
1157    __grwrknum = 0;
1158   }
1159 
1160  init_sched_iathd(hcp);
1161 
1162 done:;
1163  if (!__iact_stmt_err && !__chk_extra_atend(FALSE))
1164   {
1165    first_stmt = FALSE;
1166    __get_vtok();
1167    /* DBG remove --- */
1168    if (__toktyp == TEOF) __misc_terr(__FILE__, __LINE__);
1169    /* --- */
1170    goto more_stmts;
1171   }
1172  /* only way to exit exec iact stmt routine */
1173  __inst_mod->mtime_units = __sav_mtime_units;
1174  __sfnam_ind = sav_sfnam_ind;
1175  __slin_cnt = sav_slin_cnt;
1176 }
1177 
1178 /*
1179  * check all xmr's from this statement
1180  */
chk_iact_grefs(int32 hist_rexec)1181 static void chk_iact_grefs(int32 hist_rexec)
1182 {
1183  register int32 gri;
1184  register struct gref_t *grp;
1185 
1186  grp = &(__grwrktab[0]);
1187  for (gri = 0; gri < __grwrknum; gri++, grp++)
1188   {
1189    if (grp->gr_gone || grp->gr_err) continue;
1190    if (hist_rexec)
1191     {
1192      if (!grp->is_rooted)
1193       {
1194        __ia_warn(1601,
1195         "statement has non rooted global %s - scope instance %s may differ from original",
1196         grp->gnam, __msg2_blditree(__xs, __inst_ptr));
1197       }
1198     }
1199   }
1200 }
1201 
1202 /*
1203  * initialize an history suspended statement record
1204  */
init_iahctrl(struct hctrl_t * hcp)1205 static void init_iahctrl(struct hctrl_t *hcp)
1206 {
1207  hcp->hc_stp = NULL;
1208  hcp->hc_thp = NULL;
1209  hcp->hc_itp = NULL;
1210  hcp->hc_lini = 0;
1211  hcp->hc_ifi = 0;
1212  hcp->hc_nxt = hcp->hc_prev = NULL;
1213  hcp->hc_iahp = NULL;
1214  hcp->hc_dcelst = NULL;
1215  hcp->hc_grtab = NULL;
1216  hcp->hc_numglbs = 0;
1217 }
1218 
1219 /*
1220  * build the interactive statement thread and schedule event
1221  * this runs in current interactive scope itp
1222  * when finishes just terminates like any other thread - maybe in 0 time
1223  */
init_sched_iathd(struct hctrl_t * hcp)1224 static void init_sched_iathd(struct hctrl_t *hcp)
1225 {
1226  struct thread_t *thp;
1227  i_tev_ndx tevpi;
1228 
1229  /* allocate thread and event and fill links */
1230  alloc_tev_(tevpi, TE_THRD, hcp->hc_itp, __simtime);
1231  thp = __alloc_thrd();
1232  thp->th_hctrl = hcp;
1233  thp->thdtevi = tevpi;
1234  thp->thenbl_sfnam_ind = __cmd_ifi;
1235  thp->thenbl_slin_cnt = __iah_lasti;
1236  thp->th_itp = hcp->hc_itp;
1237  __tevtab[tevpi].tu.tethrd = thp;
1238  thp->thnxtstp = hcp->hc_stp;
1239  thp->thpar = NULL;
1240  hcp->hc_thp = thp;
1241 
1242  /* here can just add to front of event list - best to get started */
1243  /* LOOKATME - notice no longer need to add to front - just more coherent */
1244  __add_ev_to_front(tevpi);
1245 }
1246 
1247 /*
1248  * for immediate exec, allocate and set dummy current thread
1249  */
bld_immed_iathrd(struct st_t * stp)1250 static struct thread_t *bld_immed_iathrd(struct st_t *stp)
1251 {
1252  struct thread_t *thp;
1253 
1254  thp = __alloc_thrd();
1255  thp->thenbl_sfnam_ind = __cmd_ifi;
1256  thp->thenbl_slin_cnt = __iah_lasti;
1257  thp->thnxtstp = stp;
1258  thp->thpar = NULL;
1259  return(thp);
1260 }
1261 
1262 /*
1263  * free iact globals
1264  * notice caller sets iact gref table to empty
1265  */
free_iact_glbs(struct gref_t * grtab,int32 grnum)1266 static void free_iact_glbs(struct gref_t *grtab, int32 grnum)
1267 {
1268  register int32 gri;
1269  register struct gref_t *grp;
1270 
1271  for (gri = 0, grp = &(grtab[0]); gri < grnum; gri++, grp++)
1272   { __free_1glb_flds(grp); }
1273  __my_free((char *) grtab, grnum*sizeof(struct gref_t));
1274 }
1275 
1276 /*
1277  * free a list dce's (for monit/fmonit, qcaf and tf_ parameter change)
1278  * if optimized sim on and no syntax error, nd regen T else F
1279  * only called when free interactive dce list vpi_ call back lists
1280  *
1281  * caller may need to set header to nil
1282  * this works (does nothing) if called with nil dcehdr
1283  * LOOKATME - if doubly linked would be faster
1284  *
1285  * SJM 06/21/02 - now only PLI and reset call this to remove from dce list
1286  * LOOKATME - think assuming trigger set to regen iops called
1287  *
1288  * SJM 12/30/02 - must not call this routine except on interactive debugger
1289  * syntax error if -O on
1290  *
1291  * LOOKATME - here removing monit dce's because only freed if added
1292  * from interactive mode
1293  */
__free_dceauxlst(struct dceauxlst_t * dcehdr,int32 numinsts)1294 extern void __free_dceauxlst(struct dceauxlst_t *dcehdr, int32 numinsts)
1295 {
1296  register struct dceauxlst_t *dclp;
1297  register struct dcevnt_t *dcep2;
1298  struct dcevnt_t *dcep, *last_dcep;
1299  struct net_t *np;
1300 
1301   /* DBG remove -- must not call if -O used */
1302   if (__optimized_sim) __misc_terr(__FILE__, __LINE__);
1303   /* -- */
1304 
1305  /* remove all dc events that were added for this delay control event */
1306  for (dclp = dcehdr; dclp != NULL; dclp = dclp->dclnxt)
1307   {
1308    /* get the dce to free */
1309    dcep = dclp->ldcep;
1310 
1311    /* since list not doubly linked must search thru list saving last */
1312    /* BEWARE - except for dmpv on front removable dces can be put anywhere */
1313    /*          on list so can not optimize this */
1314    np = dcep->dce_np;
1315 
1316    last_dcep = NULL;
1317    for (dcep2 = np->dcelst; dcep2 != NULL; dcep2 = dcep2->dcenxt)
1318     {
1319      if (dcep == dcep2)
1320       {
1321        if (last_dcep == NULL)
1322         {
1323          np->dcelst = dcep->dcenxt;
1324          /* SJM - 06/30/00 - dce list now empty - deactivate ev ctrl wakeups */
1325          /* LOOKATME - can this really ever happen */
1326          if (np->dcelst == NULL)
1327           {
1328            /* SJM 07/24/00 - may be off if reg - turning off again ok */
1329            np->nchg_has_dces = FALSE;
1330            if (np->nlds == NULL && !np->n_hasdvars)
1331             np->nchg_nd_chgstore = FALSE;
1332            /* notice do not use all changed always on optimization here */
1333           }
1334         }
1335        else last_dcep->dcenxt = dcep->dcenxt;
1336 
1337        /* now that linked out, can regen net's list */
1338        /* for XMR, may need to move to different mod */
1339        /* if remove last, still regen to free and does not stop recording */
1340 
1341        /* if no dce value, does nothing */
1342        __free_dce_prevval(dcep, numinsts, __get_dcewid(dcep, np));
1343 
1344        /* SJM 10/06/06 - if free dce aux list, called from a vpi cb value */
1345        /* change and the a freed dce is the same as the one that caused the */
1346        /* value chg user c routine to run, must indicate the one dce */
1347        /* that caused the cbvc callback to be called has been freed */
1348        if (dcep == __cbvc_causing_dcep) __cbvc_causing_dcep = NULL;
1349 
1350        __my_free((char *) dcep, sizeof(struct dcevnt_t));
1351        dcep = NULL;
1352        goto nxt_dce;
1353       }
1354      last_dcep = dcep2;
1355     }
1356    __misc_terr(__FILE__, __LINE__);
1357 nxt_dce:;
1358   }
1359  /* finally free the dce list - know dce of element already freed */
1360  __free_dceauxs_only(dcehdr);
1361 }
1362 
1363 /*
1364  * free a dce list - know dce of each element already freed
1365  */
__free_dceauxs_only(struct dceauxlst_t * dcehdr)1366 extern void __free_dceauxs_only(struct dceauxlst_t *dcehdr)
1367 {
1368  register struct dceauxlst_t *dclp, *dclp2;
1369 
1370  for (dclp = dcehdr; dclp != NULL;)
1371   {
1372    dclp2 = dclp->dclnxt;
1373    __my_free((char *) dclp, sizeof(struct dceauxlst_t));
1374    dclp = dclp2;
1375   }
1376 }
1377 
1378 /*
1379  * free a dce previous value field
1380  * if none, does nothing
1381  */
__free_dce_prevval(struct dcevnt_t * dcep,int32 insts,int32 dcewid)1382 extern void __free_dce_prevval(struct dcevnt_t * dcep, int32 insts, int32 dcewid)
1383 {
1384  int32 totchars;
1385  struct net_t *np;
1386 
1387  /* SJM 05/05/03 - for rooted XMR dce - only 1 inst allocated */
1388  if (dcep->dce_1inst) insts = 1;
1389  if (dcep->dce_expr != NULL && dcep->dce_expr->mast_dcep == dcep)
1390   {
1391    totchars = __get_pcku_chars(dcewid, insts);
1392    __my_free((char *) dcep->dce_expr->bp, totchars);
1393    dcep->dce_expr->bp = NULL;
1394   }
1395 
1396  /* if dce on array or entire non wire (reg), will not have saved val. */
1397  if (dcep->prevval.wp == NULL) return;
1398 
1399  np = dcep->dce_np;
1400  if (np->n_stren) totchars = dcewid*insts;
1401  else totchars = __get_pcku_chars(dcewid, insts);
1402  __my_free((char *) dcep->prevval.bp, totchars);
1403  dcep->prevval.bp = NULL;
1404 }
1405 
1406 /*
1407  * ROUTINES TO RENUMBER STATEMENTS
1408  */
1409 
1410 /*
1411  * renumber a statement - for use when adding to commnd history
1412  * statement can be head of compound
1413  */
renumber_1stmt(struct st_t * stp,int32 sfnind,int32 slcnt)1414 static void renumber_1stmt(struct st_t *stp, int32 sfnind, int32 slcnt)
1415 {
1416  int32 fji;
1417  struct for_t *frp;
1418  struct st_t *fjstp;
1419 
1420  if (stp == NULL) return;
1421 
1422  /* always set statement body line */
1423  stp->stfnam_ind = (word32) sfnind;
1424  stp->stlin_cnt = slcnt;
1425 
1426  switch ((byte) stp->stmttyp) {
1427   /* simple statement just set number */
1428   case S_NULL: case S_STNONE:
1429   case S_PROCA: case S_FORASSGN: case S_RHSDEPROCA: case S_NBPROCA:
1430   case S_TSKCALL: case S_QCONTA: case S_QCONTDEA: case S_CAUSE:
1431   case S_DSABLE: case S_REPSETUP: case S_REPDCSETUP: case S_GOTO:
1432    break;
1433   case S_IF:
1434    renumber_stlst(stp->st.sif.thenst, sfnind, slcnt);
1435    renumber_stlst(stp->st.sif.elsest, sfnind, slcnt);
1436    break;
1437   case S_CASE:
1438    /* first always default or place holder for missing default */
1439    renumber_csitemlst(stp->st.scs.csitems->csinxt, sfnind, slcnt);
1440    /* if has default, know has default statement */
1441    if (stp->st.scs.csitems->csist != NULL)
1442     renumber_stlst(stp->st.scs.csitems->csist, sfnind, slcnt);
1443    break;
1444   case S_REPEAT:
1445    renumber_stlst(stp->st.srpt.repst, sfnind, slcnt);
1446    break;
1447   case S_FOREVER:
1448   case S_WHILE:
1449    renumber_stlst(stp->st.swh.lpst, sfnind, slcnt);
1450    break;
1451   case S_WAIT:
1452    /* LOOKATME - is there a action statement that needs to be renumbered */
1453    renumber_stlst(stp->st.swait.lpst, sfnind, slcnt);
1454    break;
1455   case S_FOR:
1456    frp = stp->st.sfor;
1457    /* notice for assign already freed */
1458    renumber_1stmt(frp->forinc, sfnind, slcnt);
1459    renumber_stlst(frp->forbody, sfnind, slcnt);
1460    break;
1461   case S_DELCTRL:
1462    if (stp->st.sdc->actionst != NULL)
1463     renumber_stlst(stp->st.sdc->actionst, sfnind, slcnt);
1464    break;
1465   case S_UNBLK:
1466    renumber_stlst(stp->st.sbsts, sfnind, slcnt);
1467    break;
1468   case S_UNFJ:
1469    /* renumber statement ptr table each of which may be st list */
1470    for (fji = 0;; fji++)
1471     {
1472      if ((fjstp = stp->st.fj.fjstps[fji]) == NULL) break;
1473      renumber_stlst(fjstp, sfnind, slcnt);
1474     }
1475    break;
1476   /* notice named block non freeable (at least for now) */
1477   default: __case_terr(__FILE__, __LINE__);
1478   }
1479 }
1480 
1481 /*
1482  * renumber case item list statements
1483  */
renumber_csitemlst(register struct csitem_t * csip,int32 sfnind,int32 slcnt)1484 static void renumber_csitemlst(register struct csitem_t *csip, int32 sfnind,
1485  int32 slcnt)
1486 {
1487  for (;csip != NULL; csip = csip->csinxt)
1488   { renumber_stlst(csip->csist, sfnind, slcnt); }
1489 }
1490 
1491 /*
1492  * renumber each statement of a list to same history statement list number
1493  */
renumber_stlst(register struct st_t * stp,int32 sfnind,int32 slcnt)1494 static void renumber_stlst(register struct st_t *stp, int32 sfnind, int32 slcnt)
1495 {
1496  for (; stp != NULL; stp = stp->stnxt) renumber_1stmt(stp, sfnind, slcnt);
1497 }
1498 
1499 /*
1500  * INTERACTIVE COMMAND EXECUTION ROUTINES
1501  */
1502 
1503 /*
1504  * escape from debugging environment to unix shell
1505  * for now no system task - can use $input
1506  *
1507  * know interactive environment always run with SIG_IGN but shell needs
1508  * default so ^c get out of shell
1509  */
__escape_to_shell(char * argchp)1510 extern void __escape_to_shell(char *argchp)
1511 {
1512  int32 rc, status, pid;
1513  char *chp, *usersh;
1514 
1515  /* signal(SIGINT, SIG_DFL); */
1516 
1517  if ((usersh = (char *) getenv ("SHELL")) == NULL) usersh = "/bin/sh";
1518  if ((chp = strrchr(usersh, '/')) == NULL) chp = usersh; else chp++;
1519  if ((pid = fork()) == 0)
1520   {
1521    if (*argchp == '\0') execl(usersh, chp, (char *) 0);
1522    else execl(usersh, chp, "-c", argchp, (char *) 0);
1523    if (__iact_state)
1524     __ia_err(983, "OS Failure - user shell escape execl system call failed");
1525    else __sgferr(983,
1526     "OS Failure - user shell escape execl system call failed");
1527    return;
1528   }
1529  if (pid != -1) { while ((rc = wait(&status)) != pid && rc != -1) ; }
1530  else
1531   {
1532    if (__iact_state)
1533     __ia_err(983, "OS Failure - user shell escape fork system call failed");
1534    else __sgferr(983,
1535     "OS Failure - user shell escape fork system call failed");
1536   }
1537 /* need to enable sim sigint32 handler even if called from :shell */
1538 /* ---
1539 #if defined(INTSIGS)
1540  signal(SIGINT, __sim_sigint_handler);
1541 #else
1542  signal(SIGINT, (void (*)()) __sim_sigint_handler);
1543 #endif
1544 --- */
1545 }
1546 
1547 /*
1548  * exec the $input for interactive command input source system task
1549  * here open cmd file and closes previous - new file is chained not nested
1550  * if this appears in source, just change for next time enter interactive
1551  */
__exec_input_fnamchg(struct expr_t * axp)1552 extern void __exec_input_fnamchg(struct expr_t *axp)
1553 {
1554  int32 slen;
1555  FILE *tmp_s;
1556  char *chp;
1557 
1558  /* msgexpr uses __exprline but if error not filled anyway */
1559  chp = __get_eval_cstr(axp->lu.x, &slen);
1560  if ((tmp_s = __tilde_fopen(chp, "r")) == NULL)
1561   {
1562    __sgferr(1241, "cannot open $input interactive command file %s", chp);
1563    goto done;
1564   }
1565  if (__cmd_s != NULL) __my_fclose(__cmd_s);
1566  __cmd_s = tmp_s;
1567  if (feof(__cmd_s))
1568   {
1569    __sgfwarn(610, "$input interactive command file %s empty", chp);
1570    /* here just go back to stdin */
1571    __cmd_s = NULL;
1572    __cmd_fnam = NULL;
1573    __cur_fnam = __in_fils[1];
1574    __cur_fnam_ind = __cmd_ifi;
1575    __lin_cnt = __iah_lasti;
1576    goto done;
1577   }
1578  __add_infil(chp);
1579  __cur_fnam_ind = __last_inf;
1580  __cmd_fnam = __in_fils[__cur_fnam_ind];
1581  __lin_cnt = 0;
1582  if (__verbose)
1583   __cv_msg("  Reading interactive commands from file \"%s\".\n", __cur_fnam);
1584 
1585 done:
1586  __my_free(chp, slen + 1);
1587 }
1588 
1589 /*
1590  * execute the $history list system task
1591  * extension allows optional number (how many to list) arg
1592  * prompt after 20 lines (including embedded new lines) except finish
1593  */
__exec_history_list(int32 num)1594 extern void __exec_history_list(int32 num)
1595 {
1596  register int32 i;
1597  int32 h_start, nlines;
1598  char s1[RECLEN];
1599 
1600  if (num == 0) h_start = 1;
1601  else { if ((h_start = __iah_lasti - num + 1) <= 1) h_start = 1; }
1602  for (nlines = 0, i = h_start; i <= __iah_lasti; i++)
1603   {
1604    nlines += prt1_iahist_cmd(i);
1605    if (nlines > __hist_cur_listnum)
1606     {
1607      nlines = 0;
1608      __cvsim2_msg("Press return to continue:");
1609      fgets(s1, RECLEN, stdin);
1610     }
1611   }
1612 }
1613 
1614 /*
1615  * print one history entry - may be muliple line (with embedded new lines)
1616  * returns number of lines listed (for mulitple line)
1617  */
prt1_iahist_cmd(int32 iahi)1618 static int32 prt1_iahist_cmd(int32 iahi)
1619 {
1620  int32 first_time, prmplen, numlines;
1621  struct iahist_t *iahp;
1622  char c, save_ch, *chp, *chp2, s1[RECLEN];
1623 
1624  numlines = 1;
1625  iahp = &(__iahtab[iahi]);
1626  /* notice when non immediate statement finishes, disable turned on */
1627  if (iahp->iah_hcp != NULL) c = '*'; else c = ' ';
1628  sprintf(s1, "C%d%c ", iahi, c);
1629  __cvsim_msg(s1);
1630 
1631  prmplen = strlen(s1);
1632  __blnkline[prmplen] = '\0';
1633  for (chp = iahp->iah_lp, first_time = TRUE;;)
1634   {
1635    if ((chp2 = strchr(chp, '\\')) != NULL)
1636     {
1637      chp2++;
1638      if (*chp2 == '\n')
1639       {
1640        chp2++;
1641        save_ch = *chp2;
1642        *chp2 = '\0';
1643        /* notice this has the \\\n */
1644        if (first_time) { __cvsim_msg("%s", chp); first_time = FALSE; }
1645        else __cvsim_msg("%s%s", __blnkline, chp);
1646        *chp2 = save_ch;
1647        chp = chp2;
1648        numlines++;
1649        continue;
1650       }
1651     }
1652    /* notice no ending \n */
1653    if (first_time) __cvsim_msg("%s\n", chp);
1654    else __cvsim_msg("%s%s\n", __blnkline, chp);
1655    break;
1656   }
1657  __blnkline[prmplen] = ' ';
1658  return(numlines);
1659 }
1660 
1661 /*
1662  * ROUTINES FOR INTERACTIVE DISABLE AND THREAD FREEING
1663  */
1664 
1665 /*
1666  * exec disable of interactive thread
1667  * this disables and free entire statement
1668  */
__do_iact_disable(struct hctrl_t * hcp,int32 lv_ctrl)1669 extern void __do_iact_disable(struct hctrl_t *hcp, int32 lv_ctrl)
1670 {
1671  struct thread_t *thp;
1672 
1673  thp = hcp->hc_thp;
1674  /* if any active down threads, task enables or fjs - free/disable all */
1675  if (thp->thofs != NULL) __free_thd_list(thp->thofs);
1676  free_done_iact_control(hcp, lv_ctrl);
1677  thp->th_dctp = NULL;
1678  /* thread frees cancel any pending events - no parent */
1679  __free_1thd(thp);
1680 }
1681 
1682 /*
1683  * remove interactive thread and statement list
1684  *
1685  * also removes any globals associated with statement
1686  */
free_done_iact_control(struct hctrl_t * hcp,int32 lv_ctrl)1687 static void free_done_iact_control(struct hctrl_t *hcp, int32 lv_ctrl)
1688 {
1689  register struct st_t *stp;
1690  struct st_t *stp2;
1691 
1692  /* free statements, if reenbled must parse again */
1693  __push_wrkitstk(__iact_mdp, 0);
1694  for (stp = hcp->hc_stp; stp != NULL;)
1695   { stp2 = stp->stnxt; __free_1stmt(stp); stp = stp2; }
1696  /* free any dces - know only 1 iact inst. */
1697  if (hcp->hc_dcelst != NULL)
1698   {
1699    /* know can only be called once sim started SIM STATE */
1700    __free_dceauxlst(hcp->hc_dcelst, 1);
1701    /* but always remove from list */
1702    hcp->hc_dcelst = NULL;
1703   }
1704  if (hcp->hc_numglbs > 0)
1705   {
1706    free_iact_glbs(hcp->hc_grtab, hcp->hc_numglbs);
1707    hcp->hc_grtab = NULL;
1708    hcp->hc_numglbs = 0;
1709   }
1710  __pop_wrkitstk();
1711 
1712  /* thread freed by caller, lv ctrl when all freed at once above */
1713  if (!lv_ctrl)
1714   {
1715    if (hcp->hc_nxt != NULL) hcp->hc_nxt->hc_prev = hcp->hc_prev;
1716    else
1717     {
1718      __hctrl_end = hcp->hc_prev;
1719      if (__hctrl_end != NULL) __hctrl_end->hc_nxt = NULL;
1720     }
1721    if (hcp->hc_prev != NULL) hcp->hc_prev->hc_nxt = hcp->hc_nxt;
1722    else
1723     {
1724      __hctrl_hd = hcp->hc_nxt;
1725      if (__hctrl_hd != NULL) __hctrl_hd->hc_prev = NULL;
1726     }
1727   }
1728 
1729  /* if on history, free and mark inactive */
1730  if (hcp->hc_iahp != NULL) hcp->hc_iahp->iah_hcp = NULL;
1731  if (!lv_ctrl) __my_free((char *) hcp, sizeof(struct hctrl_t));
1732 }
1733 
1734 /*
1735  * ROUTINES TO IMPLEMENTED EXTENDED : DEBUGGER COMMANDS
1736  */
1737 
1738 /* table of debugger commands values */
1739 #define DB_HELP 0
1740 #define DB_SH 1
1741 #define DB_QUIT 2
1742 #define DB_WHERE 3
1743 #define DB_PRINT 4
1744 #define DB_RESET 5
1745 #define DB_EXPRIS 6
1746 #define DB_VARIS 7
1747 #define DB_WHATIS 8
1748 #define DB_LIST 9
1749 #define DB_SET 10
1750 #define DB_INFO 11
1751 #define DB_SCOPE 12
1752 #define DB_BRKPT 13
1753 #define DB_IBRKPT 14
1754 #define DB_DELBRKDIS 15
1755 #define DB_BPDIS_ENABLE 16
1756 #define DB_BPDIS_DISABLE 17
1757 #define DB_STEP 18
1758 #define DB_ISTEP 19
1759 #define DB_HIST 20
1760 #define DB_EMPTHIST 21
1761 #define DB_DISPLAY 22
1762 #define DB_UNDISPLAY 23
1763 #define DB_TBRKPT 24
1764 #define DB_TIBRKPT 25
1765 #define DB_IGNORE 26
1766 #define DB_COND 27
1767 #define DB_SNAPSHOT 28
1768 #define DB_NEXTB 29
1769 
1770 /* debugger command name table (unordered) */
1771 static struct namlst_t dbcmds[] = {
1772  { DB_HELP, ":help" },
1773  { DB_SH, ":shell" },
1774  { DB_QUIT, ":quit" },
1775  { DB_WHERE, ":where" },
1776  { DB_PRINT, ":print" },
1777  { DB_RESET, ":reset" },
1778  { DB_EXPRIS, ":expris" },
1779  { DB_VARIS, ":varis" },
1780  { DB_WHATIS, ":whatis" },
1781  { DB_LIST, ":list" },
1782  { DB_SET, ":set" },
1783  { DB_INFO, ":info" },
1784  { DB_SCOPE, ":scope" },
1785  { DB_BRKPT, ":breakpoint" },
1786  { DB_IBRKPT, ":ibreakpoint" },
1787  { DB_DELBRKDIS, ":delete" },
1788  { DB_BPDIS_ENABLE, ":enable" },
1789  { DB_BPDIS_DISABLE, ":disabl" },
1790  { DB_STEP, ":step" },
1791  { DB_ISTEP, ":istep" },
1792  { DB_HIST, ":history" },
1793  { DB_EMPTHIST, ":emptyhistory" },
1794  { DB_DISPLAY, ":display" },
1795  { DB_UNDISPLAY, ":undisplay" },
1796  { DB_TBRKPT, ":tbreakpoint" },
1797  { DB_TIBRKPT, ":tibreakpoint" },
1798  { DB_IGNORE, ":ignore" },
1799  { DB_COND, ":cond" },
1800  { DB_SNAPSHOT, ":snapshot" },
1801  { DB_NEXTB, ":nextb" }
1802 };
1803 #define NDBCMDS (sizeof(dbcmds) / sizeof(struct namlst_t))
1804 
1805 /*
1806  * process a colon command
1807  *
1808  * this must handle history updating - returns F on exit interactive
1809  * know : followed by non white space to get here and command token read
1810  */
do_dbg_cmd(void)1811 static int32 do_dbg_cmd(void)
1812 {
1813  int32 rv, tmp;
1814  char s1[IDLEN];
1815 
1816  if (__toktyp != ID)
1817   {
1818    sprintf(s1, ":%s", __prt_vtok());
1819 bad_colon_cmd:
1820    __ia_err(1421, "undefined extended :[command] debugger command %s", s1);
1821    return(TRUE);
1822   }
1823 
1824  strcpy(s1, ":");
1825  strcat(s1, __token);
1826 
1827  rv = __get_dbcmdnum(s1, dbcmds, NDBCMDS);
1828  switch (rv) {
1829   case -1: goto bad_colon_cmd;
1830   case -2:
1831    __ia_err(1422, "%s ambiguous debugger command: %s", s1,
1832     __bld_ambiguous_list(__xs, s1, dbcmds, NDBCMDS));
1833    break;
1834   case DB_HELP:
1835    do_dbg_help();
1836 chk_end:
1837    __chk_extra_atend(TRUE);
1838    break;
1839   case DB_SH:
1840    if (__cmd_s != NULL)
1841     {
1842      __ia_err(1424,
1843       "debugger shell escape cannot be invoked from $input file");
1844      break;
1845     }
1846    /* must pass rest of line */
1847    __escape_to_shell(__visp->vichp);
1848    break;
1849   case DB_QUIT:
1850    __chk_extra_atend(TRUE);
1851 
1852    if (__tfrec_hdr != NULL) __call_misctfs_finish();
1853    if (__have_vpi_actions) __vpi_endsim_trycall();
1854    __my_exit(0, TRUE);
1855   case DB_WHERE:
1856    /* write the trace back using suspended thread */
1857    if (__suspended_thd == NULL)
1858     __ia_err(1496,
1859      ":where failed - no procedural context, single step and try again");
1860    else
1861     {
1862      __cvsim_msg("Procedural thread trace back:\n");
1863      __prt_where_msg(__suspended_thd);
1864     }
1865    goto chk_end;
1866   case DB_SNAPSHOT:
1867    __write_snapshot(5);
1868    goto chk_end;
1869   case DB_PRINT:
1870    dbg_print();
1871    break;
1872   case DB_RESET:
1873    /* here do not change reset count or value and only enter interactive */
1874    __get_vtok();
1875    __dbg_stop_before = 100;
1876    if (__toktyp != TEOF)
1877     {
1878      if (__toktyp == ID && (strcmp(__token, "s") == 0
1879       || strcmp(__token, "st") == 0 || strcmp(__token, "sto") == 0
1880       || strcmp(__token, "stop") == 0)) __dbg_stop_before = 101;
1881      else
1882       {
1883        __ia_err(1486, ":reset command argument %s not expected s or stop",
1884         __prt_vtok());
1885       }
1886     }
1887    __cvsim2_msg("Simulation begun, really reset to start over? (y/n) ");
1888    if (fgets(s1, RECLEN, stdin) == NULL || (s1[0] != 'y' && s1[0] != 'Y'))
1889     break;
1890    /* leaving interactive - and go back to compile ^c handler */
1891    __iact_state = FALSE;
1892    /* reenable the normal ^c signal handler */
1893 #if defined(INTSIGS)
1894    signal(SIGINT, __comp_sigint_handler);
1895 #else
1896    signal(SIGINT, (void (*)()) __comp_sigint_handler);
1897 #endif
1898    __pop_itstk();
1899    __reset_count--;
1900    longjmp(__reset_jmpbuf, 1);
1901    break;
1902   case DB_EXPRIS:
1903    do_dbg_expris();
1904    break;
1905   case DB_VARIS:
1906    do_dbg_varis();
1907    break;
1908   case DB_WHATIS:
1909    do_dbg_whatis();
1910    break;
1911   case DB_LIST:
1912    __do_dbg_list();
1913    break;
1914   case DB_SET:
1915    __do_dbg_set();
1916    break;
1917   case DB_INFO:
1918    __do_dbg_info();
1919    break;
1920   case DB_SCOPE:
1921    __do_dbg_scope();
1922    break;
1923   case DB_BRKPT:
1924    if (__optimized_sim)
1925     {
1926      /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
1927      cmd_illegal_msg(s1);
1928      break;
1929     }
1930    __do_dbg_brkpt(FALSE);
1931    break;
1932   case DB_TBRKPT:
1933    if (__optimized_sim)
1934     {
1935      /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
1936      cmd_illegal_msg(s1);
1937      break;
1938     }
1939    __do_dbg_brkpt(TRUE);
1940    break;
1941   case DB_IBRKPT:
1942    if (__optimized_sim)
1943     {
1944      /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
1945      cmd_illegal_msg(s1);
1946      break;
1947     }
1948    __do_dbg_ibrkpt(FALSE);
1949    break;
1950   case DB_TIBRKPT:
1951    if (__optimized_sim)
1952     {
1953      /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
1954      cmd_illegal_msg(s1);
1955      break;
1956     }
1957    __do_dbg_ibrkpt(TRUE);
1958    break;
1959   case DB_NEXTB:
1960    if (__optimized_sim)
1961     {
1962      /* SJM 02/03/03 - breakpoint commands illegal if optimizer on */
1963      cmd_illegal_msg(s1);
1964      break;
1965     }
1966    if (!__do_dbg_nextb()) return(FALSE);
1967    break;
1968   case DB_DELBRKDIS:
1969    __do_dbg_delbrkdis();
1970    break;
1971   case DB_BPDIS_DISABLE:
1972    __do_dbg_dis_enable(FALSE);
1973    break;
1974   case DB_BPDIS_ENABLE:
1975    __do_dbg_dis_enable(TRUE);
1976    break;
1977   case DB_DISPLAY:
1978    dbg_display();
1979    break;
1980   case DB_UNDISPLAY:
1981    __dbg_undisplay();
1982    break;
1983   case DB_STEP:
1984    __get_vtok();
1985    if (__toktyp == TEOF) __step_rep_cnt = 1;
1986    else
1987     {
1988      if ((tmp = __get_dbg_val()) == -1 || tmp < 1)
1989       {
1990        __ia_err(1470, ":istep command repeat count %s illegal", __prt_vtok());
1991        break;
1992       }
1993      __step_rep_cnt = tmp;
1994     }
1995    __single_step = TRUE;
1996    __verbose_step = TRUE;
1997    if (__iact_reason == IAER_CTRLC || __suspended_thd == NULL
1998     || __suspended_thd->thnxtstp == NULL) __step_from_thread = FALSE;
1999    __chk_extra_atend(TRUE);
2000    return(FALSE);
2001   case DB_ISTEP:
2002    if (__optimized_sim)
2003     {
2004      /* SJM 02/03/03 - breakpoint and ste cmds illegal if optimizer on */
2005      cmd_illegal_msg(s1);
2006      break;
2007     }
2008    __get_vtok();
2009    if (__toktyp == TEOF) __step_rep_cnt = 1;
2010    else
2011     {
2012      if ((tmp = __get_dbg_val()) == -1 || tmp < 1)
2013       {
2014        __ia_err(1470, ":step command repeat count %s illegal", __prt_vtok());
2015        break;
2016       }
2017      __step_rep_cnt = tmp;
2018     }
2019    __single_step = TRUE;
2020    __verbose_step = TRUE;
2021    if (__iact_reason == IAER_CTRLC || __suspended_thd == NULL
2022     || __suspended_thd->thnxtstp == NULL) __step_from_thread = FALSE;
2023    __step_match_itp = __scope_ptr;
2024    __chk_extra_atend(TRUE);
2025    return(FALSE);
2026   case DB_HIST:
2027    __do_dbg_history();
2028    break;
2029   case DB_EMPTHIST:
2030    __do_dbg_emptyhistory();
2031    break;
2032   case DB_IGNORE:
2033    __dbg_brk_ignore();
2034    break;
2035   case DB_COND:
2036    __dbg_brk_cond();
2037    break;
2038   default: __case_terr(__FILE__, __LINE__);
2039  }
2040  return(TRUE);
2041 }
2042 
2043 /*
2044  * find a db style command
2045  * algorithm is that any unique prefix is sufficient
2046  * also need algorithm that does not require full table search each time
2047  *
2048  * this needs alias mechanism ala gdb
2049  */
__get_dbcmdnum(char * aval,struct namlst_t * cmdtab,int32 cmdnum)2050 extern int32 __get_dbcmdnum(char *aval, struct namlst_t *cmdtab, int32 cmdnum)
2051 {
2052  register int32 i;
2053  int32 alen, alen2;
2054 
2055  /* first search for normal option (if arg white space separated) */
2056  alen = strlen(aval);
2057  for (i = 0; i < cmdnum; i++)
2058   {
2059    alen2 = strlen(cmdtab[i].lnam);
2060    if (alen2 > alen) alen2 = alen;
2061    if (strncmp(aval, cmdtab[i].lnam, alen2) == 0)
2062     {
2063      if (dbcmd_prefix_rep(i + 1, aval, alen2, cmdtab, cmdnum)) return(-2);
2064      return(cmdtab[i].namid);
2065     }
2066   }
2067  return(-1);
2068 }
2069 
2070 /*
2071  * return T if find match in remaining part of db command table
2072  */
dbcmd_prefix_rep(register int32 i,char * aval,int32 alen,struct namlst_t * cmdtab,int32 cmdnum)2073 static int32 dbcmd_prefix_rep(register int32 i, char *aval, int32 alen,
2074  struct namlst_t *cmdtab, int32 cmdnum)
2075 {
2076  for (; i < cmdnum; i++)
2077   { if (strncmp(aval, cmdtab[i].lnam, alen) == 0) return(TRUE); }
2078  return(FALSE);
2079 }
2080 
2081 /*
2082  * given a comman prefix where know ambiguous, built table of all possibilities
2083  */
__bld_ambiguous_list(char * s,char * aval,struct namlst_t * cmdtab,int32 cmdnum)2084 extern char *__bld_ambiguous_list(char *s, char *aval, struct namlst_t *cmdtab,
2085  int32 cmdnum)
2086 {
2087  register int32 i;
2088  int32 first_time, alen;
2089 
2090  alen = strlen(aval);
2091  for (first_time = TRUE, i = 0; i < cmdnum; i++)
2092   {
2093    if (strncmp(aval, cmdtab[i].lnam, alen) == 0)
2094     {
2095      if (first_time) { strcpy(s, cmdtab[i].lnam); first_time = FALSE; }
2096      else { strcat(s, ", "); strcat(s, cmdtab[i].lnam); }
2097     }
2098   }
2099  return(s);
2100 }
2101 
2102 /*
2103  * emit message for command illegal when running with -O
2104  *
2105  * all traces and steps
2106  */
cmd_illegal_msg(char * s)2107 static void cmd_illegal_msg(char *s)
2108 {
2109  __ia_err(1417,
2110   "%s illegal when -O optimized (compiled) simulation selected", s);
2111 }
2112 
2113 /*
2114  * DEBUGGER HELP SCREEN LINE TABLES
2115  */
2116 
2117 /*
2118  * define debugger general topic help screen
2119  */
2120 static char *dbg_topic_hlp[] = {
2121  "Type ':help [topic]' or ':help :[debugger command]' to print specific help",
2122  "message.  Any name can be abbreviated by a unique prefix within : debugger.",
2123  "Colon is required for command name help but not allowed for help topics.",
2124  " ",
2125  "Help topics:",
2126  "  debugging:  Entering and supplying input for interactive debugging.",
2127  "  optimizer: debugging limitations when -O optimized simulation selected",
2128  "  tracing:  Separate batch tracing system for debugging.",
2129  "  differences:  Debugger differences from Verilog standard.",
2130  "  statements:  Using traditional interactive Verilog statement debugger.",
2131  "  data:  Examining variables and expressions.",
2132  "  source:  Listing source and navigating between files.",
2133  "  scope:  Setting and navigating between instance and task scopes.",
2134  "  break points:  Behavioral statement breakpoints and single stepping.",
2135  "  changes breaking:  Breaking on net changes and edges.",
2136  "  history:  Command history and history number command enable/disable.",
2137  "  info:  Determining and setting debugger status and settings.",
2138  "  tasks:  System task and functions useful for interactive debugging.",
2139  "  commands:  A list of :[command] debugger commands.",
2140  ""
2141 };
2142 
2143 static char *dbg_dbg_hlp[] = {
2144  "Debugging:",
2145  "  Both the standard Verilog statement debugger and a command based debugger",
2146  "  are supported.  Input is typed from the terminal or read from a file.",
2147  "  Input is terminated with a new line.  For multi-line commands, all",
2148  "  but the last line ends with a back slash escaped new line.  The new",
2149  "  command debugger commands begin with a colon as part of the name and",
2150  "  cannot be executed from Verilog source.  All interactive commands are",
2151  "  echoed to the log file unless ':set noecholog' is used to to suppress log",
2152  "  file command echoing (':set echolog' re-enables).",
2153  " ",
2154  "  The debugger is entered by pressing the interrupt key (^c), by calling",
2155  "  the $stop system task, by the -s command line option, by completing a",
2156  "  step command, or by hitting a breakpoint.",
2157  " ",
2158  "  The $input(\"[file]\") system task causes debugger commands to be read",
2159  "  from [file] the first time interactive mode is entered (by -s?).  $input",
2160  "  files do not nest, instead $input in a file causes $input to chain to the",
2161  "  new file.  Output is written to the screen and the log file.  stderr is",
2162  "  not used.  All typed user input including command prompts and $input",
2163  "  commands is written to the log file.  $nolog and $log plus",
2164  "  $nokeepcommands and $keepcommands can minimize $input script output.",
2165  "  +nokeepcommands option disables history saving.  It is useful if",
2166  "  simulation is run from a shell script.",
2167  ""
2168 };
2169 
2170 static char *dbg_optimizer_hlp[] = {
2171  "Optimizer:",
2172  "  When -O optimized simulation (compiled byte code simulation) is used,",
2173  "  breakpoints and single stepping is not possible because statements",
2174  "  are converted to basic blocks, i.e. statement separation is lost.",
2175  "  Even when optimizatin is on, you still can use the debugger because",
2176  "  the byte code compiler is incremental and recompiles code required",
2177  "  by debugger Verilog statements.  The debugger can be entered by executing",
2178  "  $stop system task either from Verilog source or from statements",
2179  "  entered as debugger commands, i.e. debugger can be entered by $stop",
2180  "  system task, -s command option, or $stop entered as debugger command",
2181  "  (such as '@(posedge clk) $stop;' statement), or by pressing ^c (interrupt",
2182  "  key).  All printing, scope and info commands work.  Also, $input",
2183  "  system task and -i command line options to load commands into debugger",
2184  "  are legal when debugger is used with optimized simulation.",
2185  " ",
2186  "  For designs that do not move time (mostly procedural without time",
2187  "  movement and event scheduling), there may be a delay after interrupt",
2188  "  key is pressed before interactive debugger is entered.",
2189  " ",
2190  "  Debugger can only be exited by the dot ('.') continue command when used",
2191  "  with optimized simulation.  Use of step (';' or ',') and all break point",
2192  "  commands are illegal.  Error message is emitted and command is ignored.",
2193  "  Also, $dumpvars can not be called from interactive mode during optimized",
2194  "  simulation.",
2195  ""
2196 };
2197 
2198 static char *dbg_trc_hlp[] = {
2199  "Debugging using the tracing mechanism:",
2200  "  An alternative non interactive tracing mechanism is supported.",
2201  "  Behavioral statement tracing is started with the -t option or $settrace",
2202  "  system task and stopped by calling $cleartrace.  Event tracing is started",
2203  "  with the -et option or $setevtrace system task and stopped by calling",
2204  "  $clearevtrace.  The -et option allows pre time 0 initialization events",
2205  "  to be traced.  Trace output is written to stdout and the log file unless",
2206  "  the +tracefile [file name] option or $settracefile([string]) system task",
2207  "  are used to direct trace output to a separate file.  The trace mechanism",
2208  "  is intended to allow debugging of parallel activity by searching trace",
2209  "  output with a debugger.",
2210  " ",
2211  "  Trace statements and gates are reconstructed source with parameters",
2212  "  replaced by numeric values.  Interactive debugger breakpoint and step",
2213  "  tracing also emit source lines.  To avoid duplicate output if tracing",
2214  "  and the interactive debugger are used, redirect trace output.",
2215  ""
2216 };
2217 
2218 static char *dbg_dif_hlp[] =  {
2219  "Debugger differences from standard:",
2220  "  1) Multiple line interactive debugger commands must end with escaped new",
2221  "  lines.  Verilog statements still require the ending semicolon.",
2222  "  2) The standard $settrace system task (also -t) are divided into the two",
2223  "  tracing classes: $settrace and $setevtrace (-t and -et).",
2224  "  3) By default when interactive mode is entered the $scope interactive",
2225  "  scope is set to the current scope.  This allows examination of local",
2226  "  variables on step or break but may require entering $scope command on",
2227  "  every interactive entry to run standard scripts.  In functions, named",
2228  "  blocks do not have scope so function scope remains.  Interactivbe variable",
2229  "  access in function named block must use qualified reference from function",
2230  "  scope.  To duplicate standard behavior in which interactive scope can only",
2231  "  be changed by $scope system task, type: ':set noscopechange' inside the",
2232  "  interactive debugger.  When re-enabling commands from the history list,",
2233  "  either the command must use rooted names or the scope must be the same",
2234  "  as the scope when the command was originally entered.",
2235  "  4) Delay back annotation by specparam assignments not supported, and",
2236  "  $updatetiming, but similar standard SDF (LABEL form and PLI 2.0 assignment",
2237  "  to defparams and specparam before delay elaboration supported.",
2238  ""
2239 };
2240 
2241 static char *dbg_stmt_hlp[] =  {
2242  "Interactive Verilog statement execution:",
2243  "  Any Verilog statement can be entered at the interactive mode prompt (or",
2244  "  in an $input file) except named blocks and initial or always statements.",
2245  "  No new variables can be declared and all identifiers are accessed using",
2246  "  the current scope (entry scope or change $scope location).  Compound",
2247  "  statements and statements with delay or event controls are legal.",
2248  "  Commands are:",
2249  " ",
2250  "   '.'   Exit the debugger and continue execution (event processing).",
2251  "   ':'   Print the current instance and possibly task scope plus location",
2252  "         of scope and current :list current location.  Prints scope and",
2253  "         listing location, use :where for procedural execution location.",
2254  "   ';'   Silently step through next procedural statement and process all",
2255  "         events and time movement up to the next procedural statement. The",
2256  "         current location for the :list command is not changed.  Tasks and",
2257  "         functions are stepped into.",
2258  "   ','   Step through next statement and print next source statement.  Same",
2259  "         as ';' except the next source line to execute is printed.",
2260  "   -[number]  Disable history command [number] if it has not yet completed.",
2261  "         The $history task indicates commands that are active with a '*'",
2262  "   [number]  Re-execute command [number] from the history list only if the",
2263  "         command has finished (no '*' mark when printed with $history).",
2264  "         Commands are re-executed in the current scope so if a command sets",
2265  "         a change or edge breakpoint, it must contain rooted names or be",
2266  "         executed from the same scope as it's original entry.",
2267  ""
2268 };
2269 
2270 static char *dbg_data_hlp[] =  {
2271  "Displaying internal circuit values:",
2272  "  In addition to the normal $display (or $write) system tasks to display",
2273  "  values use :print to override declared expression base or width (type",
2274  "  ':help :print' for legal values). Use :display to define expressions that",
2275  "  are printed whenever interactive mode is entered.  :display and :print",
2276  "  take same format and width modifiers.  :expris [expr] to determine the",
2277  "  width and type of an expression.  Use :varis [var.] to determine type,",
2278  "  width and declaration keywords of a variable.  Use :whatis [name] to",
2279  "  determine all uses of an identifier name.  Entire qualified path from",
2280  "  function scope required for accessing variables in named blocks in",
2281  "  functions.",
2282  ""
2283 };
2284 
2285 static char *dbg_src_hlp[] =  {
2286  "Listing source statements:",
2287  "  The normal $list([scope]) system task can list all of any task or module.",
2288  "  The :list command lists 10 lines from a selected location that can be",
2289  "  a scope or a [file:][line] reference or argument relative to last listed",
2290  "  line.  Type ':set listsize [number]' to change the number of lines listed.",
2291  "  The current listing location is independent of current scope except when",
2292  "  :scope or $scope is executed, the current list line is set to the first",
2293  "  line of the scope.  Also since ',' and :[i]step and hitting a breakpoint",
2294  "  print a source line, those commands change the current list line.",
2295  "  The explicit [file:][line] list command lists in a new file and :list ++",
2296  "  lists the beginning of the next source file (:list -- the previous end).",
2297  "  Only these three commands can change listing file.  Type ':help :list'",
2298  "  for the format of the various :list command options.",
2299  ""
2300 };
2301 
2302 static char *dbg_scope_hlp[] =  {
2303  "Setting interactive scope:",
2304  "  The $scope([scope xmr]) system task changes interactive scope.  The :scope",
2305  "  command also changes scope but allows a more general reference.  The",
2306  "  :breakpoint command takes a scope reference argument.  Format is:",
2307  " ",
2308  "  [file:][line] - first instance of scope determined by [file:][line].",
2309  "       [file] can be source file, -y or -v path or any path tail if it is",
2310  "       unique.  [line] must be between module - endmodule.  Any ':' in",
2311  "       [file] name must be escaped with a back slash.  Scope set to type or",
2312  "       first instance but other command argument may select instance for",
2313  "       :breakpoint.  Scope list line set to first line of scope not [line].",
2314  "       [line] is same as [file:][line] where [file] is current file.",
2315  " .. or .u - upward scope first line - if scope in task - one up task or",
2316  "       instance containing task (not up instance).",
2317  " .d - first line of scope of first contained instance (not contained task).",
2318  " [module name]  - first instance of module unless name declared as instance",
2319  "       in current scope, then normal downward hierarchical reference.",
2320  " [hierarchical ref.] - first line of instance - same as $scope argument.",
2321  ""
2322 };
2323 
2324 static char *dbg_brkpt_hlp[] = {
2325  "Behavioral statement breakpoints:",
2326  "  Use the :breakpoint or :ibreakpoint commands to set a breakpoint at a",
2327  "  specific source statement.  The break occurs before statement execution.",
2328  "  :breakpoint breaks in all instances and :ibreakpoint breaks only in the",
2329  "  specified instance.  The :breakpoint argument can be any scope or line",
2330  "  reference.  If no line reference is given the break is at the first",
2331  "  initial, always or task statement of the scope.  For :ibreakpoint the",
2332  "  argument must be an instance reference that may optionally be followed by",
2333  "  a ',' and a line reference.  For a line reference, the breakpoint is set",
2334  "  at the first procedural statement at or following the line in the scope.",
2335  " ",
2336  "  Type ':help :breakpoint' or ':help :ibreakpoint' for other options and",
2337  "  argument format.  Use ':info breakpoints' to print a list of breakpoints",
2338  "  ':delete [number]' to delete breakpoint [number] (no argument deletes all),",
2339  "  ':disabl [number]' to temporarily disable breakpoint and ':enable [number]'",
2340  "  to re-enable.  :tbreakpoint and :tibreakpoint are identical to :ibreak",
2341  "  and :break except breakpoint removed when hit.  :cond adds expression to",
2342  "  breakpoint that must be true to cause stop. :ignore adds count of how many",
2343  "  hits to ignore before halting.",
2344  ""
2345 };
2346 
2347 static char *dbg_chgbrk_hlp[] = {
2348  "Breaking on net changes:",
2349  "  Enter a delay or event control followed by the $stop system task to",
2350  "  enter interactive mode on value change.  Normally the event control",
2351  "  statement will be in a loop (probably a forever) because otherwise the",
2352  "  break is disabled after each trigger.  Also when interactive mode is",
2353  "  entered from an interactive $stop, a step (',', ':', :step, or :istep)",
2354  "  command must be entered before using [number] to re-enable a history",
2355  "  statement.  For example: 'forever @(posedge clock) $stop;' is usually",
2356  "  better than '@(posedge clock) $stop;'",
2357  ""
2358 };
2359 
2360 static char *dbg_hist_hlp[] = {
2361  "History mechanism:",
2362  "  A command is re-executed by entering its history number.  A uncompleted",
2363  "  command (such as a Verilog wait or delay control) is disabled by entering",
2364  "  -[number] where [number] is command's assigned number in history list.",
2365  " ",
2366  "  The $history system task prints the most recent 20 (or histlistsize if",
2367  "  different) history entries.  The debugger :history [optional number]",
2368  "  command is more flexible because if an optional number argument appears,",
2369  "  that many elements are printed (0 for all).  The interactive command",
2370  "  prompt is 'C[number] >' where [number] is a command's history number.",
2371  "  The one character, [number] to execute, [-][number] to disable and",
2372  "  incorrect (such as mistyped Verilog statement entered interactively)",
2373  "  commands are not added to the history list.",
2374  " ",
2375  "  All commands input during a run are retained.  Use $nokeepcommands to",
2376  "  suppress history accumulation and $keepcommands to re-enable in $input",
2377  "  scripts.  +nokeepcomands command line option disables history saving for",
2378  "  programs that run a simulation by supplying command input through a pipe.",
2379  "  :emptyhistory command discards all retained history commands and resets",
2380  "  command number to one.  If any history commands are enabled (have not yet",
2381  "  completed or been disabled), :emptyhistory will fail.  When an interactive",
2382  "  Verilog statement is executed, if it can be executed immediately (no",
2383  "  delays, events or tasks enables), it is executed from inside debugger and",
2384  "  control remains in interactive mode.  Non immediate statements are",
2385  "  scheduled after already scheduled events and resumes.  $stop or the",
2386  "  interrupt signal (^c) must then be used to reenter interactive mode.  Use",
2387  "  ':set histlistsize' to set default number of history commands to list and",
2388  " ':info histlistsize' to see current number.",
2389  ""
2390 };
2391 
2392 static char *dbg_info_hlp[] = {
2393  "Determining and setting internal debugger state values:",
2394  "  The ':info [debugger value name]' command prints the current value of",
2395  "  a debugger value.  The ':set [debugger value name] [value]' command",
2396  "  changes a debugger value.  Type ':help :info' or ':help :set' for the list",
2397  "  of debugger info value names.",
2398  ""
2399 };
2400 
2401 static char *dbg_stsks_hlp[] = {
2402  "The following system tasks may be useful during interactive debugging:",
2403  "   $finish;  Terminate simulation.",
2404  "   $list([scope reference]);  list source lines of scope (:list is",
2405  "      alternative).  $list does not print variables values, use $showvars",
2406  "      or :print <expr> for that.  Also $list does not mark source lines",
2407  "      with pending events.",
2408  "   $system(\"[OS command string]\");  Escape to a sub shell and execute the",
2409  "      command string (alternative is :shell [command string]).  Use empty",
2410  "      string (\"\") to invoke an interactive sub-shell.",
2411  "   $flushlog;  Call OS flush of buffers for log file and trace file.  Can",
2412  "      then use :shell to invoke your editor to inspect output.",
2413  "   $history;  Print history list to stdout and log file.  Contrary to XL,",
2414  "      '$history;' prints last 20 (or histlistsize) commands.  Use",
2415  "      ':history <num>' to print <num> commands.  <num> 0 prints all. :set",
2416  "      sets and :info prints debugger histlistsize parameter that determines",
2417  "      number of commands to list.",
2418  " $keepcommands;, $nokeepcommands;  Enable (or disable) saving of commands",
2419  "      entered interactively to history list.  Default is $keepcommands.",
2420  "      Use the +nokeepcommands command line option to disable saving of",
2421  "      commands to the history list unless '$keepcommands;' is executed.",
2422  "   $input([string]);  Process interactive commands from [string] file.",
2423  "   $nolog;, $log;  All commands in $input scripts will be copied to the",
2424  "      log file unless $nolog is used.  To re-enable log file output, use",
2425  "      $log; with no argument.  To change log file use $log([string]).",
2426  "   $reset;, $reset_count;, $reset_value;  During debugging reset to start",
2427  "      of simulation.  :reset command is better during debugging since it",
2428  "      returns to time 0 leaving the reset count unaffected and allows stop.",
2429  "   $scope;  Change interactive environment scope to avoid a need to type",
2430  "      full paths for variable names.  :scope and automatic scope tracking",
2431  "      are intended to lessen need to set explicit interactive scopes.",
2432  "      $scope can set scope to function named block but next ineractive entry",
2433  "      (from step?) will change scope to function body scope.",
2434  "   $showallinstances;  Print all instances in design with source file and",
2435  "      line location.  Useful to find module whose name is forgotten.",
2436  "      +printstats and +printallstats give more detailed information.",
2437  "      If no other window is available, use $flushlog; and :shell to view.",
2438  "   $showscopes;  Used to show scopes in current interactive scope.  Can be",
2439  "      called with non zero argument to list entire design scope map.",
2440  "   $showvariables;, $showvars  Print all variables in current scope. :print",
2441  "      is more terse but $showvars prints more for multiple fan-in wires.",
2442  "   $shapshot; print up to 5 pending procedural and 5 pending declarative",
2443  "      events and status of every interactive thread.  Same as :snapshot.",
2444  "   $display, $write  Write values.  Alternative :print is more flexible but",
2445  "      these tasks allow formatted output.",
2446  ""
2447 };
2448 
2449 /* table of debugger help topic values */
2450 #define HLP_DBG 0
2451 #define HLP_OPTIM 1
2452 #define HLP_TRC 2
2453 #define HLP_DIF 3
2454 #define HLP_STMT 4
2455 #define HLP_DAT 5
2456 #define HLP_SRC 6
2457 #define HLP_SCP 7
2458 #define HLP_BP 8
2459 #define HLP_CHGBP 9
2460 #define HLP_HIST 10
2461 #define HLP_INF 11
2462 #define HLP_TSK 12
2463 #define HLP_CMD 13
2464 
2465 /* debugger help topic name table */
2466 /* index and pos. in this table must be identical */
2467 static struct namlst_t hlptoptab[] = {
2468  { HLP_DBG, "debugging" },
2469  { HLP_OPTIM, "optimizer" },
2470  { HLP_TRC, "tracing" },
2471  { HLP_DIF, "differences" },
2472  { HLP_STMT, "statements" },
2473  { HLP_DAT, "data" },
2474  { HLP_SRC, "source" },
2475  { HLP_SCP, "scope" },
2476  { HLP_BP, "breakpoints" },
2477  { HLP_CHGBP, "changes" },
2478  { HLP_HIST, "history" },
2479  { HLP_INF, "info" },
2480  { HLP_TSK, "tasks" },
2481  { HLP_CMD, "commands" }
2482 };
2483 #define NHLPTOPS (sizeof(hlptoptab) / sizeof(struct namlst_t))
2484 
2485 /* per help topic line tables - size is same help topices */
2486 /* index and pos. in this table must be identical */
2487 static struct hlplst_t hlp_topics[] = {
2488  { HLP_DBG, dbg_dbg_hlp },
2489  { HLP_OPTIM, dbg_optimizer_hlp },
2490  { HLP_TRC, dbg_trc_hlp },
2491  { HLP_DIF, dbg_dif_hlp },
2492  { HLP_STMT, dbg_stmt_hlp },
2493  { HLP_DAT, dbg_data_hlp },
2494  { HLP_SRC, dbg_src_hlp },
2495  { HLP_SCP, dbg_scope_hlp },
2496  { HLP_BP, dbg_brkpt_hlp },
2497  { HLP_CHGBP, dbg_chgbrk_hlp },
2498  { HLP_HIST, dbg_hist_hlp },
2499  { HLP_INF, dbg_info_hlp },
2500  { HLP_TSK, dbg_stsks_hlp },
2501  /* here must call special command list routine */
2502  { HLP_CMD, NULL, }
2503 };
2504 
2505 /*
2506  * DEBUGGER INDIVIDUAL COMMAND HELP SCREEN LINE TABLES
2507  */
2508 
2509 static char *help_msg[] = {
2510  ":help [optional topic or :[command] name prefix]",
2511  "   Print help message.",
2512  ""
2513 };
2514 
2515 static char *shell_msg[] = {
2516  ":shell [rest of line is OS command]",
2517  "   Execute rest of line as OS command in sub-shell.  Notice no quotes needed.",
2518  "   Empty rest of line to spawn interactive shell.  Equivalent to",
2519  "   '$system([quotes OS command string]);' system task.",
2520  ""
2521 };
2522 
2523 static char *snapshot_msg[] = {
2524  ":snapshot",
2525  "   Print snapshot of current procedural location and list of statement at",
2526  "   which each procedural (per instance) thread suspended at.  Also lists",
2527  "   pending events on head of event list.  May be long so one way to view it",
2528  "   is to type: $flushlog; then ':sh [evoke editor on verilog.log file]'.",
2529  ""
2530 };
2531 
2532 static char *where_msg[] = {
2533  ":where",
2534  "   Print back trace of most recently suspended control thread including all",
2535  "   upward thread enables with source and scope locations.  To see a listing",
2536  "   of all pending scheduled event activity and thread states use $snapshot;",
2537  "   or :snapshot.  :where corresponds as closely as possible to normal",
2538  "   call stack trace back.  ':' prints instance scope and last source",
2539  "   listing location.  If :where fails, suspension was from declarative code.",
2540  "   Try single step and entering :where again.",
2541  ""
2542 };
2543 
2544 static char *quit_msg[] = {
2545  ":quit",
2546  "   Exit.  Equivalent to $finish;",
2547  ""
2548 };
2549 
2550 static char *print_msg[] = {
2551  ":print [/format][#width] [expression]",
2552  "   Evaluate and print expression.  If [/format] is present, interpret the",
2553  "   value according to format.  Formats are:  'd' (decimal), 'u' (unsigned),",
2554  "   'b' (binary), 'h' or 'x' (hex), 's' (string), or 'c' (1 character).  If",
2555  "   the [/format] is omitted, use current default unless the expression is a",
2556  "   string or real.  Starting default base is hex, but use ':set printbase'",
2557  "   to set different default base.  /u format prints bit pattern as unsigned.",
2558  "   If [#width] value is present, interpret as [width] wide, instead of width",
2559  "   computed from operator width rules.  Any format or width are ignored for",
2560  "   reals, use $realtobits to view bit pattern.",
2561  ""
2562 };
2563 
2564 static char *reset_msg[] = {
2565  ":reset [stop]",
2566  "   Reset simulation back to time 0 and restart simulation.  Interactive mode",
2567  "   must be explicitly entered by interrupt (^c), calling $stop or [stop]",
2568  "   option.  If a -i startup file was given it is executed on interactive",
2569  "   entry.  $reset_count and $reset_value are not changed.  If optional",
2570  "   :reset stop argument is present, stop just before simulation, else rerun",
2571  "   without stopping even if -s option was given on command line.  Equivalent",
2572  "   to $reset system task but can be used to restart for debugging models",
2573  "   that use the $reset system task.  The $reset system task uses the -s",
2574  "   option unless the first argument is non zero and stops before simulation.",
2575  "   All uncompleted interactive statements are disabled by either :reset",
2576  "   or $reset.  They are re-enabled by typing history command number or",
2577  "   running -i start up interactive file.  Debugger state : breakpoints",
2578  "   (left enabled) and history are preserved.",
2579  ""
2580 };
2581 
2582 static char *expris_msg[] = {
2583  ":expris [expression]",
2584  "   Print type and width of expression.  Use to determine Verilog width and",
2585  "   property rules for complex expressions.",
2586  ""
2587 };
2588 
2589 static char *varis_msg[] = {
2590  ":varis [variable]",
2591  "   Print type and width and declaration keywords of variable.",
2592  ""
2593 };
2594 
2595 static char *whatis_msg[] = {
2596  ":whatis [identifier]",
2597  "   Print symbol information for every use of identifier.  Also, emits one",
2598  "   instance reference for each use, so a breakpoint can be set.",
2599  ""
2600 };
2601 
2602 static char *list_msg[] = {
2603  ":list [range]",
2604  "   List source within [range] lines.  Some [range]s are relative to last",
2605  "   printed line.  Any scope change or $list or previous :list command",
2606  "   changes the last printed line.  Legal [range]s are:",
2607  " ",
2608  "     + or [empty]             10 lines starting with last printed.",
2609  "     +0                       10 lines around current line.",
2610  "     -                        10 lines ending 1 before previous first line.",
2611  "     ++                       First 10 lines of next file.",
2612  "     --                       Last 10 lines of previous file.",
2613  "     [file]:[number]          10 lines around [number] in file [file].",
2614  "     [number]                 10 lines around [number] in current file.",
2615  "     [+/-][offset]            10 lines starting [offset] from current.",
2616  "     [+/-][num1],[+/-][num2]  Range, if [+/-] offset from current line.",
2617  "     [scope reference]        First 10 lines starting at [scope].",
2618  " ",
2619  "   By default 10 lines are list, use ':set listsize [number]' to change",
2620  "   number of printed lines to [number].  Notice stepping with ';' does not",
2621  "   change last printed line.  Use [file]:[number] to list inside `include",
2622  "   files.  ++ and -- exit to file and line of first inclusion of file.",
2623  "   Read library files are same as source files.",
2624  ""
2625 };
2626 
2627 static char *set_msg[] = {
2628  ":set [debugger parameter] [value]",
2629  "   Set debugger internal parameter to [value].  Legal set parameters are:",
2630  " ",
2631  "   :set listsize [number]     Default is 10 lines to list.",
2632  "   :set histlistsize [number] Default is 20 history commands to list.",
2633  "   :set noscopechange         Disable automatic scope setting on entry to",
2634  "                              interactive mode.",
2635  "   :set scopechange           Re-enable automatic scope setting on.  Scope",
2636  "                              not set to named blocks in functions.",
2637  "   :set printbase [base]      Set default :print command base, values: hex",
2638  "                              (default), decimal, octal binary.",
2639  "   :set nologecho             Turn off writing of input interactive commands",
2640  "                              the log file (default).",
2641  "   :set logecho               Turn on writing of input commands.",
2642  ""
2643 };
2644 
2645 static char *info_msg[] = {
2646  ":info [debugger parameter]",
2647  "   Show value of debugger state or parameter setting.  Legal info parameters",
2648  "   are: listsize, histlistsize, scopechange, breakpoints, displays,",
2649  "   printbase and logecho.  For breakpoints and auto-display expressions",
2650  "   prints status information for each.",
2651  ""
2652 };
2653 
2654 static char *scope_msg[] = {
2655  ":scope [scope reference]",
2656  "   Change interactive scope to [scope reference] location.  Type",
2657  "   ':help scope' for list of legal scope selection forms.  Any [line] is",
2658  "   used only to determine surrounding scope.  Scope only applies to",
2659  "   interactive mode and system tasks that explicitly are defined to use the",
2660  "   interactive scope.   Extended version of $scope system task.  If scope",
2661  "   set to function named block scope, next interactive entry will change",
2662  "   scope to function body scope (assuming scopechange mode active).",
2663  ""
2664 };
2665 
2666 static char *breakpoint_msg[] = {
2667  ":breakpoint [scope reference] or none",
2668  "   Set statement breakpoint at all instances of [scope reference].  Type",
2669  "   ':help scope' for a list of legal [scope reference] forms.  If the",
2670  "   reference selects an instance, only the type of the instance is used.",
2671  "   If the [scope reference] is not a [file:][line] reference, use first",
2672  "   initial, always or task statement of scope.  If no argument, set at",
2673  "   last :list argument (first if range, closest if backward) that must be",
2674  "   within task, function or initial or always block.  Setting a breakpoint",
2675  "   at a line means the first procedural statement at or after the line (but",
2676  "   must be within scope).  Type ':help breakpoints' for discussion of other",
2677  "   breakpoint commands.",
2678  "",
2679 };
2680 
2681 static char *ibreakpoint_msg[] = {
2682  ":ibreakpoint [scope reference][,[file:][line]] or none",
2683  "   Set statement breakpoint at instances of [scope reference] file [file]",
2684  "   and [line] line.  Type ':help scope' for a list of legal [scope ref.]s,",
2685  "   but here only explicit instance scope references are legal.  If the",
2686  "   ',[file:][line]' argument is omitted, use first statement of first",
2687  "   initial, always, or task (for task scope).  If ',[line]' but no [file]",
2688  "   is given, use first or only file of scope.  If no scope reference and",
2689  "   only ',[file:][line]' is given, use current scope.  No argument means",
2690  "   set at last :list argument (first if range, closest if backward)",
2691  "   that must be within task, function, or initial or always block.",
2692  "   Type ':help breakpoints' for discussion of other breakpoint commands.",
2693  "",
2694 };
2695 
2696 static char *delete_msg[] = {
2697  ":delete [optional type] [number]",
2698  "   Delete breakpoint or display expression with number [number] or all if",
2699  "   number is omitted.  [optional type] is breakpoints or displays (default",
2700  "   if omitted is breakpoints).  Type 'info breakpoints' or 'info displays'",
2701  "   to determine breakpoint or auto-display number.  If [number] is omitted,",
2702  "   delete all breakpoints or auto-display expressions.",
2703  ""
2704 };
2705 
2706 static char *disable_msg[] = {
2707  ":disabl [optional type] [number]",
2708  "   Temporarily disable breakpoint or display with number [number].",
2709  "   [optional type] is breakpoints or displays (breakpoints is default if",
2710  "   omitted) and can be abbreviated to first letter. Type 'info breakpoints'",
2711  "   or 'info displays' to determine breakpoint or auto-display number and",
2712  "   enable state.  Notice final e must not appear to avoid conflict with",
2713  "   Verilog disable keyword (any unique prefix such as 'disa' works).  Also",
2714  "   notice that :disabl disables an added : debugger breakpoint, but disable",
2715  "   statement or -[number] disables simulation of a Verilog statement.",
2716  ""
2717 };
2718 
2719 static char *enable_msg[] = {
2720  ":enable [optional type] [number]",
2721  "   Enable breakpoint or display with number [number].  [optional type]",
2722  "   is either breakpoints or displays (breakpoints is default if omitted) and",
2723  "   can be abbreviated to first letter.  Type 'info breakpoints' or",
2724  "   'info displays' to determine breakpoint or auto-display expression",
2725  "   number and enable state.",
2726  ""
2727 };
2728 
2729 static char *step_msg[] = {
2730  ":step [optional repeat count]",
2731  "   Step to next procedural line.  Execute one statement or statements on",
2732  "   current line, stop before first statement of next line.  May process",
2733  "   pending declarative events before stepping.  Execution steps into any",
2734  "   task or function.  Equivalent to ',' interactive Verilog command.",
2735  "   Always prints location after stopping.  if optional repeat count, step",
2736  "   that many times before stopping and printing message.  If interrupt (^c)",
2737  "   or breakpoint hit during stepping, stop stepping and enter interactive",
2738  "   mode.",
2739  ""
2740 };
2741 
2742 static char *istep_msg[] = {
2743  ":istep [optional repeat count]",
2744  "   Step to next procedural statement that is in same instance tree location.",
2745  "   Otherwise identical to :step.  If debugger entered by interrupt, use one",
2746  "   :step before :istep since scope may have been in module without any",
2747  "   procedural statements.  :istep uses currently executing instance not",
2748  "   interactive scope set by $scope.",
2749  ""
2750 };
2751 
2752 static char *hist_msg[] = {
2753  ":history [optional number]",
2754  "   Print 20 (or value of histlistsize info debugger parameter) commands.",
2755  "   If [number] appears, print [number] (0 means all) history commands.",
2756  "   Pauses and prompts for CR every histlistsize lines.",
2757  ""
2758 };
2759 
2760 static char *empthist_msg[] = {
2761  ":emptyhistory",
2762  "   If all history commands have completed or are disabled with (-[number]",
2763  "   command), discard retained history and set next history command to 1.",
2764  ""
2765 };
2766 
2767 static char *disp_msg[] = {
2768  ":display [/format][#width] [expression]",
2769  "   Set up [expression] in display table so that it is displayed on every",
2770  "   entry to interactive mode.  Arguments are identical to :print command.",
2771  "   Use ':delete display' or ':undisplay' to delete all auto-display",
2772  "   expressions.  If either is followed by a number, delete that numbered",
2773  "   display only.  Use ':info display' to list current displays.  ':display'",
2774  "   with no arguments displays all current auto-display expressions.",
2775  "   Use 'enable display' and 'disabl display' to temporarily turn off or on",
2776  "   an auto-display expression.",
2777  ""
2778 };
2779 
2780 static char *undisp_msg[] = {
2781  ":undisplay [optional number]",
2782  "   Delete [number] auto-display expression or all current if [number] is",
2783  "   not present.  Same as ':delete display' command.",
2784  ""
2785 };
2786 
2787 static char *tbreakpoint_msg[] = {
2788  ":tbreakpoint [scope reference] or none",
2789  "   Command identical to :breakpoint except breakpoint is temporary and",
2790  "   removed after it is hit the first time.  To avoid tracing in task or",
2791  "   function (approximate DBX/GDB next command), use the :nextb command.",
2792  "   It sets a :tibreak at the next line and executes a '.' command.  Because",
2793  "   of delay and event controls, other threads may be executed before break",
2794  "   is hit.  The :ignore command can be used with :tbreakpoint.  After",
2795  "   ignore count hits, the break point is taken and then removed.",
2796  ""
2797 };
2798 
2799 static char *tibreakpoint_msg[] = {
2800  ":tibreakpoint [scope reference][,[file:][line]] or none",
2801  "   Command identical to :ibreakpoint except breakpoint is temporary and",
2802  "   removed after it his the first time (see :tbreakpoint help).  Only",
2803  "   stops in instance that is same as scope reference instance.",
2804  ""
2805 };
2806 
2807 static char *nextb_msg[] = {
2808  ":nextb",
2809  "   Abbreviation for :tibreak [line number of next thread statement]",
2810  "   followed by '.'.  Analog of DBX/GDB next command steps over current",
2811  "   statement.  Break point is visible and can be removed before it is hit.",
2812  "   If no next statement in thread, temporary break point not set and error",
2813  "   message emitted.  :nextb over task enable may execute other threads",
2814  "   before stopping if the task contains event or delay controls.  :nextb",
2815  "   and for that matter any temporary break point do not use up a break",
2816  "   point number unless a new break point is set before temporary break",
2817  "   point is hit.  See ':help :tbreakpoint' and ':help statements' for",
2818  "   more information.",
2819  ""
2820 };
2821 
2822 static char *ignorebrk_msg[] = {
2823  ":ignore [breakpoint number] [ignore count]",
2824  "   Do not stop at break point [number] until [ignore count] hits of the",
2825  "   break point have occurred.  Ignore count assumes last hit was 0th.",
2826  "   To remove an :ignore count, use 'ignore [break number] 0'.  Use",
2827  "   ':info breakpoints' to determine number of hits and any pending ignore",
2828  "   count.",
2829  ""
2830 };
2831 
2832 static char *condbrk_msg[] = {
2833  ":cond [breakpoint number] [optional condition expression]",
2834  "   Do not stop at break point [number] unless [expression] evaluates to",
2835  "   a positive non x/z value (i.e. true).  Expression will be checked and",
2836  "   evaluated in instance and task/function or named block scope of break",
2837  "   point.  Since Verilog variables persist, :cond expression variable always",
2838  "   have values.  Conditions are evaluated before ignore counts so if",
2839  "   condition is false hit count does not rise.  Use ':cond [break number]'",
2840  "   to remove condition.",
2841  ""
2842 };
2843 
2844 /* per command help line tables - size is same as dbcmds */
2845 /* this table must have value and index same (same order as constants) */
2846 static struct hlplst_t hlpcmds[] = {
2847  { DB_HELP, help_msg },
2848  { DB_SH, shell_msg },
2849  { DB_QUIT, quit_msg },
2850  { DB_WHERE, where_msg },
2851  { DB_PRINT, print_msg },
2852  { DB_RESET, reset_msg },
2853  { DB_EXPRIS, expris_msg },
2854  { DB_VARIS, varis_msg },
2855  { DB_WHATIS, whatis_msg },
2856  { DB_LIST, list_msg },
2857  { DB_SET, set_msg },
2858  { DB_INFO, info_msg },
2859  { DB_SCOPE, scope_msg },
2860  { DB_BRKPT, breakpoint_msg },
2861  { DB_IBRKPT, ibreakpoint_msg },
2862  { DB_DELBRKDIS, delete_msg },
2863  { DB_BPDIS_ENABLE, enable_msg },
2864  { DB_BPDIS_DISABLE, disable_msg },
2865  { DB_STEP, step_msg },
2866  { DB_ISTEP, istep_msg },
2867  { DB_HIST, hist_msg },
2868  { DB_EMPTHIST, empthist_msg },
2869  { DB_DISPLAY, disp_msg },
2870  { DB_UNDISPLAY, undisp_msg },
2871  { DB_TBRKPT, tbreakpoint_msg },
2872  { DB_TIBRKPT, tibreakpoint_msg },
2873  { DB_IGNORE, ignorebrk_msg },
2874  { DB_COND, condbrk_msg },
2875  { DB_SNAPSHOT, snapshot_msg },
2876  { DB_NEXTB, nextb_msg }
2877 };
2878 
2879 /*
2880  * ROUTINES TO IMPLEMENT DEBUGGER HELP SYSTEM
2881  */
2882 
2883 /*
2884  * write the debugger help screens
2885  * format is :help or :help [topic] where [topic] is special topic or
2886  * :[command]
2887  */
do_dbg_help(void)2888 static void do_dbg_help(void)
2889 {
2890  int32 rv;
2891  char s1[RECLEN];
2892 
2893  /* number error here, but make sure not allocated */
2894  __get_vtok();
2895  /* case 1: no argument, emit topic list */
2896  if (__toktyp == TEOF) { wr_dbg_hlpmsg(dbg_topic_hlp); return; }
2897  /* case 2: argument is : debugger command */
2898  if (__toktyp == COLON)
2899   {
2900    __get_vtok();
2901    if (__toktyp != ID || strlen(__token) > 40)
2902     {
2903 bad_cmd:
2904      __ia_err(1438,
2905       ":help argument :%s illegal - not a : debugger command", __prt_vtok());
2906      return;
2907     }
2908    strcpy(s1, ":");
2909    strcat(s1, __token);
2910    rv = __get_dbcmdnum(s1, dbcmds, NDBCMDS);
2911    if (rv == -1) goto bad_cmd;
2912    if (rv == -2)
2913     {
2914      __ia_err(1422, ":help %s - ambiguous : debugger command: %s", s1,
2915       __bld_ambiguous_list(__xs, s1, dbcmds, NDBCMDS));
2916      return;
2917     }
2918    /* notice rv is found in command table but indexes hlpcmds table */
2919    /* therefore the 2 tables must be kept in indentical order */
2920    wr_dbg_hlpmsg(hlpcmds[rv].hmsgtab);
2921    goto done;
2922   }
2923  /* case 3: argument is help topic */
2924  if (__toktyp != ID)
2925   {
2926 bad_topic:
2927    __ia_err(1439, ":help topic %s unrecognized", __prt_vtok());
2928    goto done;
2929   }
2930  rv = __get_dbcmdnum(__token, hlptoptab, NHLPTOPS);
2931  if (rv == -1) goto bad_topic;
2932  if (rv == -2)
2933   {
2934    __ia_err(1422, ":help %s - ambiguous topic: %s", s1,
2935     __bld_ambiguous_list(__xs, s1, hlptoptab, NHLPTOPS));
2936    goto done;
2937   }
2938  /* for help command topic, routine to list all commands */
2939  /* hlptoptab and hlp_topics tables must be kept in identical order */
2940  if (rv == HLP_CMD) wr_dbg_lstofcmds(dbcmds, NDBCMDS);
2941  else wr_dbg_hlpmsg(hlp_topics[rv].hmsgtab);
2942 
2943 done:
2944  __chk_extra_atend(TRUE);
2945 }
2946 
2947 /*
2948  * write a debugger help message to standard output and log file
2949  */
wr_dbg_hlpmsg(char ** dbgmsg)2950 static void wr_dbg_hlpmsg(char **dbgmsg)
2951 {
2952  register int32 i;
2953 
2954  for (i = 0; *dbgmsg[i] != '\0'; i++) __cvsim_msg("%s\n", dbgmsg[i]);
2955 }
2956 
2957 /*
2958  * write the list of debugger commands
2959  */
wr_dbg_lstofcmds(struct namlst_t * cmdtab,int32 cmdnum)2960 static void wr_dbg_lstofcmds(struct namlst_t *cmdtab, int32 cmdnum)
2961 {
2962  register int32 i;
2963 
2964  if (__outlinpos != 0) __misc_terr(__FILE__, __LINE__);
2965  __pv_stlevel = 0;
2966  __wrap_puts(":[command] debugger commands:  ", stdout);
2967  for (i = 0; i < cmdnum; i++)
2968   {
2969    __wrap_puts(cmdtab[i].lnam, stdout);
2970    if (i != cmdnum - 1) __wrap_puts(", ", stdout);
2971   }
2972  if (__outlinpos != 0) __wrap_putc('\n', stdout);
2973  __outlinpos = 0;
2974 }
2975 
2976 /*
2977  * ROUTINES TO IMPLEMENT DEBUGGER EXPRESSION EVALUATION
2978  */
2979 
2980 /*
2981  * print an expression value - know :print read
2982  *
2983  * format - :print/[d,u,b,h(x),s,c]#[bits] <expr> - default h and expr width
2984  * p#42 - p/d#52
2985  * notice no f - since will always print real as real
2986  */
dbg_print(void)2987 static void dbg_print(void)
2988 {
2989  int32 prtfmt, prtwidth, force_unsign;
2990  struct expr_t *prtx;
2991 
2992  prtfmt = BNONE;
2993  prtwidth = -1;
2994  force_unsign = FALSE;
2995  /* handle optional /[format letter] */
2996  __get_vtok();
2997  if (__toktyp == DIV)
2998   {
2999    __get_vtok();
3000    if (__toktyp == ID)
3001     {
3002      if (strlen(__token) > 1)
3003       {
3004 bad_prt_typ:
3005        __ia_err(1425, ":print type selector /%s illegal", __token);
3006        return;
3007       }
3008      switch (__token[0]) {
3009       case 'd': prtfmt = BDEC; break;
3010       case 'u': prtfmt = BDEC; force_unsign = TRUE; break;
3011       case 'o': prtfmt = BOCT; break;
3012       case 'b': prtfmt = BBIN; break;
3013       case 'h': case 'x': prtfmt = BHEX; break;
3014       case 's': prtfmt = BSTR; break;
3015       case 'c': prtfmt = BCHAR; break;
3016       default: goto bad_prt_typ;
3017      }
3018     }
3019    else
3020     {
3021      __ia_err(1426,
3022       ":print type selector / not followed by format letter - %s read",
3023       __prt_vtok());
3024      return;
3025     }
3026    __get_vtok();
3027   }
3028  /* handle optional #<width> */
3029  if (__toktyp == SHARP)
3030   {
3031    __get_vtok();
3032    if (__toktyp != NUMBER || __itoklen > WBITS || __bcwrk[0] != 0L)
3033     {
3034      __ia_err(1427, ":print width override # not followed by legal number");
3035      return;
3036     }
3037    prtwidth = (int32) __acwrk[0];
3038    __get_vtok();
3039   }
3040  /* if collect returns F, if NULL, know error emitted in routine */
3041  /* notice here if value, cannot free - need the iatok ptr allocated value */
3042  if ((prtx = __rd_iact_expr()) == NULL) return;
3043  /* know this will fit in RECLEN and truncates for readabililty for */
3044  /* very wide values */
3045  dbg_bld_expr_val(__xs, prtx, prtfmt, prtwidth, force_unsign);
3046  __cvsim_msg("%s\n", __xs);
3047 
3048  /* can free expr. */
3049  __free_xtree(prtx);
3050  __chk_extra_atend(TRUE);
3051 }
3052 
3053 /*
3054  * print an expression value for :print or :display commands
3055  */
dbg_bld_expr_val(char * s,struct expr_t * prtx,int32 prtfmt,int32 prtwidth,int32 force_unsign)3056 static char *dbg_bld_expr_val(char *s, struct expr_t *prtx, int32 prtfmt,
3057  int32 prtwidth, int32 force_unsign)
3058 {
3059  int32 blen;
3060  word32 av, bv;
3061  double d1;
3062  struct xstk_t *xsp;
3063  char s1[IDLEN];
3064 
3065  /* strength only emitted if no strength override */
3066  if (prtx->x_stren && prtfmt == BNONE && prtwidth == -1)
3067   { __strenexpr_tostr(s, prtx); return(s); }
3068 
3069  xsp = __eval_xpr(prtx);
3070  /* always print real as double - can use system task to get bit pattern */
3071  if (prtx->is_real)
3072   {
3073    memmove(&d1, xsp->ap, sizeof(double));
3074    sprintf(s, "%g", d1);
3075    goto do_prt;
3076   }
3077 
3078  /* print as character ignore any print width */
3079  if (prtfmt == BCHAR)
3080   {
3081    /* if has x/z, print as 8 bit binary x/z value */
3082    av = xsp->ap[0] & 0xff;
3083    bv = xsp->bp[0] & 0xff;
3084    if (bv != 0)
3085     {
3086      __regab_tostr(s1, &av, &bv, 8, BBIN, FALSE);
3087      sprintf(s, "char: [%s]", s1);
3088     }
3089    /* if non printable, print as escaped */
3090    /* SJM 09/19/03 - must also print new line and tab - isprint does */
3091    /* not include new line and tab etc. */
3092    else if (isprint(av) || av == '\n' || av == '\r' || av == '\t')
3093     sprintf(s, "\\%x", (int32) av);
3094    else sprintf(s, "%c", (char) av);
3095    goto do_prt;
3096   }
3097  /* force print as string */
3098  if (prtfmt == BSTR)
3099   {
3100    /* if explicit width use it and do not trim, else trim leading 0's */
3101    if (prtwidth == -1) blen = __trim1_0val(xsp->ap, xsp->xslen);
3102    else blen = prtwidth;
3103    /* convert to string with escape octal for non printable */
3104    __strab_tostr(s, xsp->ap, blen, FALSE, FALSE);
3105    goto do_prt;
3106   }
3107  /* finally print according to values */
3108  if (prtwidth == -1) blen = xsp->xslen; else blen = prtwidth;
3109  if (prtfmt == BNONE) prtfmt = __dbg_dflt_base;
3110  __regab2_tostr(s, xsp->ap, xsp->bp, blen, prtfmt,
3111   (!force_unsign) ? TRUE : FALSE, (prtwidth == -1) ? TRUE : FALSE);
3112 
3113 do_prt:
3114  __pop_xstk();
3115  return(s);
3116 }
3117 
3118 /*
3119  * read and parse an interactive debugger expression
3120  * expects first token to have been read
3121  * this must be run in right scope
3122  */
__rd_iact_expr(void)3123 extern struct expr_t *__rd_iact_expr(void)
3124 {
3125  int32 sav_err_cnt;
3126  struct expr_t *xp;
3127 
3128  if (!__colto_eol()) return(NULL);
3129  /* LOOKATME - needed because iact errors counted - maybe should not */
3130  sav_err_cnt = __pv_err_cnt;
3131  __bld_xtree(0);
3132  xp = __root_ndp;
3133  /* if already error, do not check expr. */
3134  if (__pv_err_cnt == sav_err_cnt) __chk_rhsexpr(xp, 0);
3135  if (__pv_err_cnt != sav_err_cnt)
3136   {
3137    __ia_err(1423, "invalid syntax in debugger expression");
3138    return(NULL);
3139   }
3140  return(xp);
3141 }
3142 
3143 /*
3144  * for debugger collect expression to end of line
3145  * expects 1st token to have been read
3146  * if in file or interactive tty, same eof on end of line
3147  */
__colto_eol(void)3148 extern int32 __colto_eol(void)
3149 {
3150  for (__last_xtk = -1;;)
3151   {
3152    if (__toktyp == TEOF) return(TRUE);
3153    if (__toktyp == SEMI)
3154     {
3155      __ia_err(1487, "semicolon illegal end of interactive expression");
3156      goto bad_end;
3157     }
3158    if (!__bld_expnode()) goto bad_end;
3159    __get_vtok();
3160   }
3161 
3162 bad_end:
3163  __set_xtab_errval();
3164  return(FALSE);
3165 }
3166 
3167 /*
3168  * ROUTINES TO IMPLEMENT DISPLAY COMMANDS
3169  */
3170 
3171 /*
3172  * set up display of expr on any interactive entry - know :display read
3173  *
3174  * always print on start
3175  * format - :display/[d,u,b,h(x),s,c]#[bits] <expr>
3176  */
dbg_display(void)3177 static void dbg_display(void)
3178 {
3179  int32 prtfmt, prtwidth, force_unsign;
3180  struct expr_t *prtx;
3181  struct dispx_t *dxp;
3182 
3183  __get_vtok();
3184  if (__toktyp == TEOF)
3185   {
3186    /* display all current non disable display expressions */
3187    prt_all_disp_exprs();
3188    return;
3189   }
3190 
3191  prtfmt = BNONE;
3192  prtwidth = -1;
3193  force_unsign = FALSE;
3194  if (__toktyp == DIV)
3195   {
3196    __get_vtok();
3197    if (__toktyp == ID)
3198     {
3199      if (strlen(__token) > 1)
3200       {
3201 bad_prt_typ:
3202        __ia_err(1425, ":display type selector /%s illegal", __token);
3203        return;
3204       }
3205      switch (__token[0]) {
3206       case 'd': prtfmt = BDEC; break;
3207       case 'u': prtfmt = BDEC; force_unsign = TRUE; break;
3208       case 'o': prtfmt = BOCT; break;
3209       case 'b': prtfmt = BBIN; break;
3210       case 'h': case 'x': prtfmt = BHEX; break;
3211       case 's': prtfmt = BSTR; break;
3212       case 'c': prtfmt = BCHAR; break;
3213       default: goto bad_prt_typ;
3214      }
3215     }
3216    else
3217     {
3218      __ia_err(1426,
3219       ":display type selector / not followed by format letter - %s read",
3220       __prt_vtok());
3221      return;
3222     }
3223    __get_vtok();
3224   }
3225  /* handle optional #<width> */
3226  if (__toktyp == SHARP)
3227   {
3228    __get_vtok();
3229    if (__toktyp != NUMBER || __itoklen > WBITS || __bcwrk[0] != 0L)
3230     {
3231      __ia_err(1427, ":display width override # not followed by legal number");
3232      return;
3233     }
3234    prtwidth = (int32) __acwrk[0];
3235    __get_vtok();
3236   }
3237  /* if collect returns F, if NULL, know error emitted in routine */
3238  /* notice here if value, cannot free - need the iatok ptr allocated value */
3239  if ((prtx = __rd_iact_expr()) == NULL) return;
3240 
3241  /* add to display list but do not print anything */
3242  dxp = (struct dispx_t *) __my_malloc(sizeof(struct dispx_t));
3243  dxp->dsp_enable = TRUE;
3244  dxp->dsp_frc_unsign = force_unsign;
3245  dxp->dsp_num = __nxt_dispxnum++;
3246  dxp->dsp_prtfmt = prtfmt;
3247  dxp->dsp_prtwidth = prtwidth;
3248  dxp->dsp_xp = prtx;
3249  /* need to eval. in this instance (or use as start pt. for xmr) */
3250  dxp->dsp_itp = __inst_ptr;
3251  dxp->dsp_tskp = __scope_tskp;
3252  /* behavior is to print last first so need to put on front */
3253  dxp->dsp_nxt = __dispxhdr;
3254  __dispxhdr = dxp;
3255  __chk_extra_atend(TRUE);
3256 }
3257 
3258 /*
3259  * print all expressions for display - prints nothing if none
3260  */
prt_all_disp_exprs(void)3261 static void prt_all_disp_exprs(void)
3262 {
3263  struct dispx_t *dxp;
3264  char s1[RECLEN];
3265 
3266  for (dxp = __dispxhdr; dxp != NULL; dxp = dxp->dsp_nxt)
3267   {
3268    /* if disabled, do not print anything */
3269    if (!dxp->dsp_enable) continue;
3270 
3271    __push_itstk(dxp->dsp_itp);
3272    dbg_bld_expr_val(__xs, dxp->dsp_xp, dxp->dsp_prtfmt,
3273     dxp->dsp_prtwidth, (dxp->dsp_frc_unsign) ? TRUE : FALSE);
3274    __cvsim_msg("%d:%s %s = %s\n", dxp->dsp_num,
3275     bld_prtbasecode(s1, dxp->dsp_prtfmt, (dxp->dsp_frc_unsign) ? TRUE : FALSE,
3276     dxp->dsp_prtwidth), __msgexpr_tostr(__xs2, dxp->dsp_xp), __xs);
3277    __pop_itstk();
3278   }
3279 }
3280 
3281 /*
3282  * convert debug base code and width to string or empty string if none
3283  */
bld_prtbasecode(char * s,int32 bcod,int32 force_unsign,int32 prtwidth)3284 static char *bld_prtbasecode(char *s, int32 bcod, int32 force_unsign, int32 prtwidth)
3285 {
3286  char s1[RECLEN];
3287 
3288  switch ((byte) bcod) {
3289   case BBIN: strcpy(s, " /b"); break;
3290   case BHEX: strcpy(s, " /x"); break;
3291   case BDEC:
3292    if (force_unsign) strcpy(s, " /u");
3293    else strcpy(s, " /d"); break;
3294   case BOCT: strcpy(s, " /o"); break;
3295   case BSTR: strcpy(s, " /s"); break;
3296   case BCHAR: strcpy(s, " /c"); break;
3297   case BNONE: strcpy(s, ""); break;
3298   default: strcpy(s, "?"); __case_terr(__FILE__, __LINE__);
3299  }
3300  if (prtwidth == -1) return(s);
3301  strcpy(s1, s);
3302  sprintf(s, "%s #%d", s1, prtwidth);
3303  return(s);
3304 }
3305 
3306 /*
3307  * MISCELLANEOUS DEBUGGER EXPRESSION ROUTINES
3308  */
3309 
3310 /*
3311  * emit description of expression information
3312  * notice expression must be variable not scope - no way to parse and
3313  * distinguish case where numeric expr. or scope can be mixed in Verilog
3314  */
do_dbg_expris(void)3315 static void do_dbg_expris(void)
3316 {
3317  struct expr_t *prtx;
3318  char s1[RECLEN];
3319 
3320  __get_vtok();
3321  if ((prtx = __rd_iact_expr()) == NULL) return;
3322  __cvsim_msg("%s\n", bld_expr_telltale(s1, prtx));
3323  __chk_extra_atend(TRUE);
3324 }
3325 
3326 /*
3327  * build an expression tell tale
3328  */
bld_expr_telltale(char * s,struct expr_t * xp)3329 static char *bld_expr_telltale(char *s, struct expr_t *xp)
3330 {
3331  sprintf(s, "<top operator %s width %d", __to_opname(xp->optyp),
3332   xp->szu.xclen);
3333  if (xp->has_sign) strcat(s, " signed");
3334  if (xp->optyp == NUMBER || xp->optyp == ISNUMBER)
3335   {
3336    if (xp->is_string) strcat(s, " string");
3337    if (!xp->unsiznum) strcat(s, " explicit width");
3338    if (xp->sizdflt) strcat(s, " default width");
3339   }
3340  if (xp->is_real) strcat(s, " real");
3341  if (xp->x_multfi) strcat(s, " fi>1 or tran wire");
3342  if (xp->x_stren) strcat(s, " has strength wire");
3343  if (xp->tf_isrw) strcat(s, " tf_ argument lvalue");
3344  if (xp->locqualnam) strcat(s, " local qualified name");
3345  strcat(s, ">");
3346  return(s);
3347 }
3348 
3349 /*
3350  * emit description of variable information
3351  */
do_dbg_varis(void)3352 static void do_dbg_varis(void)
3353 {
3354  struct net_t *np;
3355  struct expr_t *prtx;
3356  struct sy_t *scope_syp;
3357 
3358  __get_vtok();
3359  if ((prtx = __rd_iact_expr()) == NULL) return;
3360  if (prtx->optyp != ID)
3361   {
3362    __ia_err(1465, ":varis argument %s illegal - must be variable name",
3363     __msgexpr_tostr(__xs, prtx));
3364    return;
3365   }
3366  np = prtx->lu.sy->el.enp;
3367  if (__last_iasytp == NULL) __misc_terr(__FILE__, __LINE__);
3368  scope_syp = __last_iasytp->sypofsyt;
3369  print_iddecl_ref(np->nsym, scope_syp);
3370  __chk_extra_atend(TRUE);
3371 }
3372 
3373 /*
3374  * print out a variable information line
3375  *
3376  * for module or system tf, scope is nil
3377  * for variable, scope is declaration symbol table (mod or task)
3378  * for user task/funct, scope is containing module (or task/func/named block)
3379  * for symbol declared in named block
3380  */
print_iddecl_ref(struct sy_t * syp,struct sy_t * scope_syp)3381 static void print_iddecl_ref(struct sy_t *syp, struct sy_t *scope_syp)
3382 {
3383  int32 nd_inst;
3384  struct net_t *np;
3385  struct mod_t *mdp;
3386  struct symtab_t *sytp;
3387  struct task_t *tskp;
3388  char s1[RECLEN], s2[RECLEN], s3[RECLEN];
3389 
3390  mdp = NULL;
3391  np = NULL;
3392  tskp = NULL;
3393  nd_inst = TRUE;
3394  switch ((byte) syp->sytyp) {
3395   case SYM_M: case SYM_PRIM: case SYM_UDP: case SYM_STSK: case SYM_SF:
3396    /* DBG remove --- */
3397    if (scope_syp != NULL) __arg_terr(__FILE__, __LINE__);
3398    /* --- */
3399    nd_inst = FALSE;
3400    sprintf(s1, "%s %s", __to_sytyp(s2, syp->sytyp), syp->synam);
3401    if (syp->sy_giabase) strcat(s1, " (array of primitives base)");
3402    break;
3403   case SYM_I: case SYM_TSK: case SYM_F:
3404    /* DBG remove --- */
3405    if (scope_syp == NULL) __arg_terr(__FILE__, __LINE__);
3406    /* --- */
3407    sprintf(s1, "%s %s", __to_sytyp(s2, syp->sytyp), syp->synam);
3408    if (syp->sy_giabase) strcat(s1, " (instance array base)");
3409    if (scope_syp->sytyp == SYM_M) mdp = scope_syp->el.emdp;
3410    else mdp = scope_syp->el.eip->imsym->el.emdp;
3411    break;
3412   case SYM_LB:
3413    /* DBG remove --- */
3414    if (scope_syp == NULL) __arg_terr(__FILE__, __LINE__);
3415    /* --- */
3416    sprintf(s1, "%s %s", __to_sytyp(s2, syp->sytyp), syp->synam);
3417    /* for named block, can be inside task or other named block */
3418    if (scope_syp->sytyp == SYM_M) mdp = scope_syp->el.emdp;
3419    else
3420     {
3421      tskp = scope_syp->el.etskp;
3422      for (sytp = tskp->tsksymtab;; sytp = sytp->sytpar)
3423       {
3424        /* DBG remove --- */
3425        if (sytp == NULL) __misc_terr(__FILE__, __LINE__);
3426        /* --- */
3427        if (sytp->sypofsyt->sytyp == SYM_M) break;
3428       }
3429      mdp = sytp->sypofsyt->el.emdp;
3430     }
3431    break;
3432   case SYM_N:
3433    /* DBG remove --- */
3434    if (scope_syp == NULL) __arg_terr(__FILE__, __LINE__);
3435    /* --- */
3436    np = syp->el.enp;
3437    __bld_showvars_prefix(s1, np, NULL);
3438    if (scope_syp->sytyp == SYM_M) mdp = scope_syp->el.emdp;
3439    else
3440     {
3441      tskp = scope_syp->el.etskp;
3442      for (sytp = tskp->tsksymtab;; sytp = sytp->sytpar)
3443       {
3444        /* DBG remove --- */
3445        if (sytp == NULL) __misc_terr(__FILE__, __LINE__);
3446        /* --- */
3447        if (sytp->sypofsyt->sytyp == SYM_M) break;
3448       }
3449      mdp = sytp->sypofsyt->el.emdp;
3450     }
3451    break;
3452   default: __case_terr(__FILE__, __LINE__);
3453  }
3454  if (scope_syp == NULL) { __cvsim_msg(" %s (top level object)\n", s1); }
3455  else
3456   {
3457    __cvsim_msg("%s in %s %s %s\n", s1,
3458     __to_sytyp(s2, scope_syp->sytyp), scope_syp->synam,
3459     __bld_lineloc(s3, syp->syfnam_ind, syp->sylin_cnt));
3460    if (nd_inst)
3461     {
3462      __cvsim_msg("  [one instance: %s.%s]\n",
3463       __msg_blditree(s2, mdp->moditps[0], tskp), syp->synam);
3464     }
3465   }
3466 }
3467 
3468 /*
3469  * emit information on every declaration of variable
3470  */
do_dbg_whatis(void)3471 static void do_dbg_whatis(void)
3472 {
3473  register struct mod_t *mdp;
3474  register struct task_t *tskp;
3475  int32 not_defed;
3476  struct sy_t *syp;
3477 
3478  not_defed = TRUE;
3479  __get_vtok();
3480  if (__toktyp != ID)
3481   {
3482    __ia_err(1465, ":whatis argument %s illegal - must be legal identifier",
3483     __prt_vtok());
3484    return;
3485   }
3486  /* first look in top level symbol tables (top level object) */
3487  if ((syp = __get_sym(__token, __modsyms)) != NULL)
3488   { print_iddecl_ref(syp, (struct sy_t *) NULL); not_defed = FALSE; }
3489 
3490  /* look in system functions and tasks */
3491  if ((syp = __get_sym(__token, __syssyms)) != NULL)
3492   { print_iddecl_ref(syp, (struct sy_t *) NULL); not_defed = FALSE; }
3493 
3494  /* next look in each module's symbol table */
3495  for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
3496   {
3497    if ((syp = __get_sym(__token, mdp->msymtab)) != NULL)
3498     {
3499      print_iddecl_ref(syp, mdp->msym);
3500      not_defed = FALSE;
3501     }
3502   }
3503  /* finally look at tasks and functions in every module */
3504  for (mdp = __modhdr; mdp != NULL; mdp = mdp->mnxt)
3505   {
3506    for (tskp = mdp->mtasks; tskp != NULL; tskp = tskp->tsknxt)
3507     {
3508      if ((syp = __get_sym(__token, tskp->tsksymtab)) != NULL)
3509       {
3510        print_iddecl_ref(syp, tskp->tsksyp);
3511        not_defed = FALSE;
3512       }
3513     }
3514   }
3515  if (not_defed) __cvsim_msg("%s undefined\n", __token);
3516  __chk_extra_atend(TRUE);
3517 }
3518 
3519 /*
3520  * ROUTINES TO IMPLEMENT VPI_ SIM CONTROL INTERACTIVE ROUTINES
3521  */
3522 
3523 /*
3524  * execute $stop (schedule it) from user vpi_ code
3525  */
__do_vpi_stop(int32 diag_level)3526 extern int32 __do_vpi_stop(int32 diag_level)
3527 {
3528  if (__no_iact)
3529   {
3530    __emit_vpi_noiact_warn();
3531    return(TRUE);
3532   }
3533  if (__iact_state)
3534   {
3535    __emit_vpi_iniact_warn();
3536    return(FALSE);
3537   }
3538  if (diag_level >= 1)
3539   {
3540    if (!__quiet_msgs) __cv_msg("\n");
3541    __cv_msg("vpi_control vpiStop executed at time %s.\n",
3542     __to_timstr(__xs, &__simtime));
3543   }
3544  if (diag_level >= 2) __emit_stsk_endmsg();
3545 
3546  /* must leave signal on - if ^c hit before stop, same effect */
3547  /* but entry reason different and lost */
3548  __pending_enter_iact = TRUE;
3549  __iact_reason = IAER_STOP;
3550  return(TRUE);
3551 }
3552 
3553 /*
3554  * do a reset from user vpi_ code (it's immediate)
3555  */
__do_vpi_reset(int32 stop_val,int32 reset_val,int32 diag_level)3556 extern void __do_vpi_reset(int32 stop_val, int32 reset_val, int32 diag_level)
3557 {
3558  int32 enter_iact;
3559 
3560  if (diag_level >= 1)
3561   {
3562    if (!__quiet_msgs) __cv_msg("\n");
3563    __cv_msg("vpi_control vpiReset executed at time %s.\n",
3564     __to_timstr(__xs, &__simtime));
3565   }
3566  if (diag_level >= 2) __emit_stsk_endmsg();
3567 
3568  /* enter interactive unless reset value non zero */
3569  if (stop_val != 0) enter_iact = FALSE; else enter_iact = TRUE;
3570  if (enter_iact) __stop_before_sim = TRUE; else __stop_before_sim = FALSE;
3571 
3572  /* record state changes caused by arguments */
3573  __reset_value = reset_val;
3574 
3575  /* reenable the normal ^c signal handler - when variables reset */
3576  /* sim will replace with sim handler for entering interactive */
3577 #if defined(INTSIGS)
3578  signal(SIGINT, __comp_sigint_handler);
3579 #else
3580  signal(SIGINT, (void (*)()) __comp_sigint_handler);
3581 #endif
3582 
3583  /* this does not return - uses lng jmp */
3584  longjmp(__reset_jmpbuf, 1);
3585 }
3586