1 /* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
2 /*
3  * example to find cause statements only in top module initial/always
4  *
5  * real program would descend to all instances to find all modules
6  * and keep track of seen module types to not repeat search
7  */
8 
9 #include <stdio.h>
10 
11 #include "vpi_user.h"
12 #include "cv_vpi_user.h"
13 #include <string.h>
14 
15 static int num_causes;
16 
17 /* local prototypes */
18 static void blk_findcaus(vpiHandle);
19 static void blk_findcaus(vpiHandle);
20 
21 /* global prototypes */
22 extern int findcaus(struct t_cb_data *);
23 extern int my_error_handler(struct t_cb_data *);
24 extern void register_scan_cb(void);
25 
findcaus(struct t_cb_data * cbp)26 int findcaus(struct t_cb_data *cbp)
27 {
28  int iatyp, sttyp, isiz;
29  vpiHandle href, href2, href3;
30  vpiHandle modiref, ia_iref;
31 
32  /* build the iterator for each module */
33  modiref = vpi_iterate(vpiModule, NULL);
34  isiz = vpi_get(vpiSize, modiref);
35  vpi_printf("module iterator has size %d.\n", isiz);
36 
37  for (num_causes = 0;;)
38   {
39    if ((href = vpi_scan(modiref)) == NULL) break;
40    vpi_printf("... processing instance %s\n", vpi_get_str(vpiFullName, href));
41 
42    /* build the initial/always process iterator */
43    ia_iref = vpi_iterate(vpiProcess, href);
44    isiz = vpi_get(vpiSize, ia_iref);
45    vpi_printf("init/always iterator has size %d.\n", isiz);
46    for (;;)
47     {
48      if ((href2 = vpi_scan(ia_iref)) == NULL) break;
49      iatyp = vpi_get(vpiType, href2);
50      if (iatyp == vpiInitial) vpi_printf("... processing initial\n");
51      else if (iatyp == vpiAlways) vpi_printf("...processing always\n");
52      else vpi_printf("... expected initial/always not found");
53 
54      href3 = vpi_handle(vpiStmt, href2);
55      sttyp = vpi_get(vpiType, href3);
56      vpi_printf("... processing %d type.\n", sttyp);
57      switch (sttyp) {
58       case vpiEventStmt: num_causes++; break;
59       case vpiBegin: case vpiFork: case vpiNamedBegin: case vpiNamedFork:
60        blk_findcaus(href3);
61        break;
62       default: ; /* anything else just ignored */
63      }
64     }
65   }
66  vpi_printf("There were %d total cause statements in top modules.\n",
67   num_causes);
68  return(0);
69 }
70 
71 /*
72  * find causes in blocks (maybe named and can be nested)
73  */
blk_findcaus(vpiHandle blkhref)74 static void blk_findcaus(vpiHandle blkhref)
75 {
76  int sttyp, isiz;
77  vpiHandle ihref, href;
78 
79  /* build the list of statements in block iterator */
80  ihref = vpi_iterate(vpiStmt, blkhref);
81  isiz = vpi_get(vpiSize, ihref);
82  vpi_printf("block stmt iterator has size %d.\n", isiz);
83  for (;;)
84   {
85    if ((href = vpi_scan(ihref)) == NULL) break;
86    sttyp = vpi_get(vpiType, href);
87    vpi_printf("... processing %d type.\n", sttyp);
88    switch (sttyp) {
89     case vpiEventStmt: num_causes++; break;
90     case vpiBegin: case vpiFork: case vpiNamedBegin: case vpiNamedFork:
91      blk_findcaus(href);
92      break;
93     default: ; /* anything else just ignored */
94    }
95   }
96 }
97 
98 /*
99  * routine to build an error indication string
100  */
my_error_handler(struct t_cb_data * cbp)101 int my_error_handler(struct t_cb_data *cbp)
102 {
103  struct t_vpi_error_info einfotab;
104  struct t_vpi_error_info *einfop;
105  char s1[128];
106 
107  einfop = &einfotab;
108  vpi_chk_error(einfop);
109 
110  if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
111  else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
112  else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
113  else strcpy(s1, "**unknown**");
114 
115  vpi_printf("%s: %s error (level %d) at **%s(%d):\n  %s\n",
116   einfop->code, s1, einfop->level, einfop->file, einfop->line,
117   einfop->message);
118 
119  /* if serious error give up */
120  if (einfop->level == vpiError || einfop->level == vpiSystem
121   || einfop->level == vpiInternal)
122   {
123    vpi_printf("**FATAL: encountered error - giving up\n");
124    vpi_sim_control(vpiFinish, 0);
125   }
126  return(0);
127 }
128 
129 /* Template functin table for added user systf tasks and functions.
130    See file vpi_user.h for structure definition
131    Note only vpi_register_systf and vpi_ or tf_ utility routines that
132    do not access the simulation data base may be called from these routines
133 */
134 
135 /* all routines are called to register cbs */
136 /* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
137 /* before source is read */
138 void (*vlog_startup_routines[]) () =
139 {
140  register_scan_cb,
141  0
142 };
143 
144 /* routine to do the systf registering - probably should go in other file */
145 /* usually only vpi_ PLI 2.0 systf or cb registering is done here */
146 
147 /*
148  * register the start of sim scan call back and set up error handling
149  *
150  * notice making version of Cver that prints some stuff to start but
151  * is a normal Cver
152  *
153  * since handle not saved (passed back?), no way to find out cb info
154  */
register_scan_cb(void)155 void register_scan_cb(void)
156 {
157  vpiHandle href, href2;
158  struct t_cb_data *ecbp, *cbp;
159  struct t_cb_data cbrec, cbrec2;
160 
161  /* notice cb records must be in global storage */
162  ecbp = &cbrec;
163  ecbp->reason = cbPLIError;
164  ecbp->cb_rtn = my_error_handler;
165  ecbp->obj = NULL;
166  ecbp->time = NULL;
167  ecbp->value = NULL;
168  ecbp->user_data = NULL;
169 
170  /* probably should check for error here */
171  if ((href = vpi_register_cb(ecbp)) == NULL)
172   vpi_printf(
173    "**ERR: $hello PLI 2.0 task cannot register end of compile check routine");
174 
175  cbp = &cbrec2;
176  cbp->reason = cbStartOfSimulation;
177  cbp->cb_rtn = findcaus;
178  cbp->obj = NULL;
179  cbp->time = NULL;
180  cbp->value = NULL;
181  cbp->user_data = NULL;
182 
183  /* probably should check for error here */
184  if ((href2 = vpi_register_cb(cbp)) == NULL)
185   vpi_printf(
186    "**ERR: $hello PLI 2.0 task cannot register end of compile check routine");
187  /* if not registered will be no call backs */
188 }
189 
190 /* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
191 /* in standard PLI vlog_startup_routines table */
vpi_compat_bootstrap(void)192 void vpi_compat_bootstrap(void)
193 {
194  int i;
195 
196  for (i = 0;; i++)
197   {
198    if (vlog_startup_routines[i] == NULL) break;
199    vlog_startup_routines[i]();
200   }
201 }
202