1 /* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
2 
3 /*
4  * print out all drives and loads for wire and regs
5  *
6  * this shows the advantage of type information carrying handles - values
7  * can be printed without knowing much about Verilog constructs
8  */
9 
10 #include <stdio.h>
11 #include <string.h>
12 
13 #include "vpi_user.h"
14 #include "cv_vpi_user.h"
15 
16 int (*iproc_rtn)();
17 
18 /* local function prototypes */
19 static void process_inst(vpiHandle);
20 static void prt_1iter_drvlds(vpiHandle, vpiHandle);
21 static void prt_iter(vpiHandle, vpiHandle);
22 static void prt_1task_drvlds(vpiHandle);
23 
24 /* global function prototypes */
25 extern int my_prt_vchg();
26 extern int prt_drvlds(vpiHandle);
27 extern int my_error_handler(struct t_cb_data *);
28 extern void register_scan_cb(void);
29 
30 /*
31  * routine to get and zero all delays in design
32  */
process_all_insts(struct t_cb_data * cbp)33 int process_all_insts(struct t_cb_data *cbp)
34 {
35  int isiz;
36  vpiHandle topiter, topiref;
37 
38  /* build the iterator for each module */
39  topiter = vpi_iterate(vpiModule, NULL);
40  isiz = vpi_get(vpiSize, topiter);
41  vpi_printf("  There are %d top level modules.\n", isiz);
42  for (;;)
43   {
44    if ((topiref = vpi_scan(topiter)) == NULL) break;
45    process_inst(topiref);
46   }
47  vpi_printf("  >>> All instances processed - continuing with simulation.\n");
48  return(0);
49 }
50 
51 /*
52  * process one instance and recursively process all under instances
53  * processing is top down depth first
54  */
process_inst(vpiHandle up_ihref)55 static void process_inst(vpiHandle up_ihref)
56 {
57  int isiz;
58  vpiHandle iter, ihref;
59 
60  iproc_rtn(up_ihref);
61  if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return;
62  isiz = vpi_get(vpiSize, iter);
63  vpi_printf("  There are %d instances in %s.\n", isiz,
64   vpi_get_str(vpiFullName, up_ihref));
65   for (;;)
66   {
67    if ((ihref = vpi_scan(iter)) == NULL) break;
68    process_inst(ihref);
69   }
70 }
71 
72 /*
73  * print the loads and drivers for all nets in instance ihref
74  */
prt_drvlds(vpiHandle ihref)75 int prt_drvlds(vpiHandle ihref)
76 {
77  vpiHandle iter, thref;
78 
79  /* first all instance regs, wires, and variables */
80  iter = vpi_iterate(vpiNet, ihref);
81  if (iter != NULL) prt_1iter_drvlds(iter, ihref);
82  iter = vpi_iterate(vpiReg, ihref);
83  if (iter != NULL) prt_1iter_drvlds(iter, ihref);
84  iter = vpi_iterate(vpiVariables, ihref);
85  if (iter != NULL) prt_1iter_drvlds(iter, ihref);
86 
87  /* also monitor in scopes */
88  iter = vpi_iterate(vpiInternalScope, ihref);
89  for (;;)
90   {
91    if ((thref = vpi_scan(iter)) == NULL) break;
92    prt_1task_drvlds(thref);
93   }
94  return(0);
95 }
96 
97 /*
98  * print all loads and drivers for nets in one iterator
99  */
prt_1iter_drvlds(vpiHandle iter,vpiHandle ihref)100 static void prt_1iter_drvlds(vpiHandle iter, vpiHandle ihref)
101 {
102  register int bi;
103  int ntyp;
104  vpiHandle href, bref, bititer, lditer, drviter, ndxref;
105  s_vpi_value tmpval;
106 
107  for (;;)
108   {
109    if ((href = vpi_scan(iter)) == NULL) break;
110    /* can not pass real variable to load/driver iterator or will get err */
111    /* bits selects form real illegal in Verilog */
112    if ((ntyp = vpi_get(vpiType, href)) == vpiRealVar) continue;
113 
114    /* for this test ignore scalars */
115    if (vpi_get(vpiScalar, href)) continue;
116 
117    /* should never be nil */
118    if ((bititer = vpi_iterate(vpiBit, href)) == NULL) continue;
119    for (;;)
120     {
121      if ((bref = vpi_scan(bititer)) == NULL) break;
122 
123      ndxref = vpi_handle(vpiIndex, bref);
124      tmpval.format = vpiIntVal;
125      /* need to evalate expr. even though since from iter know constant */
126      vpi_get_value(ndxref, &tmpval);
127      bi = tmpval.value.integer;
128 
129      /* print the drives and loads for 1 net */
130      vpi_printf("... printing drivers and loads for %s[%d]:\n",
131       vpi_get_str(vpiFullName, bref), bi);
132 
133      lditer = vpi_iterate(vpiLocalLoad, bref);
134      if (lditer != NULL)
135       {
136        vpi_printf("  Loads:\n");
137        prt_iter(lditer, ihref);
138       }
139 
140      /* regs can only have loads because in Cver force/assign properties */
141      /* not drivers */
142      if (ntyp != vpiNetBit) continue;
143 
144      drviter = vpi_iterate(vpiLocalDriver, bref);
145      if (drviter != NULL)
146       {
147        vpi_printf("  Drivers:\n");
148        prt_iter(drviter, ihref);
149       }
150 
151      lditer = vpi_iterate(vpiPathTerm, bref);
152      if (lditer != NULL)
153       {
154        vpi_printf("  Path terminals:\n");
155        prt_iter(lditer, ihref);
156       }
157 
158      lditer = vpi_iterate(vpiTchkTerm, bref);
159      if (lditer != NULL)
160       {
161        vpi_printf("  Timing check terminals:\n");
162        prt_iter(lditer, ihref);
163       }
164     }
165   }
166 }
167 
168 /*
169  * print contents of one iterator (any? non NULL)
170  */
prt_iter(vpiHandle iter,vpiHandle ihref)171 static void prt_iter(vpiHandle iter, vpiHandle ihref)
172 {
173  int htyp;
174  vpiHandle href, portihref;
175  char *chp, s1[1025];
176 
177  for (;;)
178   {
179    if ((href = vpi_scan(iter)) == NULL) break;
180 
181    htyp = vpi_get(vpiType, href);
182    /* must handle port as special case because can be module port */
183    /* or up instance port connection */
184    if (htyp == vpiModPathIn || htyp == vpiModPathOut) strcpy(s1, "**NONE(0)");
185    else
186     {
187      if ((chp = vpi_get_str(vpiFile, href)) == NULL)
188       strcpy(s1, "**NONE(0)");
189      else sprintf(s1, "**%s(%d)", chp, vpi_get(vpiLineNo, href));
190     }
191    if (htyp == vpiPort)
192     {
193      /* if ld/drv net in same instance as port then module port */
194      /* else up instance connection */
195      portihref = vpi_handle(vpiModule, href);
196      if (vpi_compare_objects(ihref, portihref))
197       {
198        vpi_printf("   Port (vpiLowConn) object at %s\n", s1);
199       }
200      else
201       {
202        sprintf(s1, "**%s(%d)", vpi_get_str(vpiFile, portihref),
203         vpi_get(vpiLineNo, portihref));
204        vpi_printf("   Port (vpiHighConn) object at %s\n", s1);
205       }
206     }
207    else vpi_printf("    %s object at %s\n", vpi_get_str(vpiType, href), s1);
208   }
209 }
210 
211 /*
212  * print the drivers and loads for one task (should be no drivers?)
213  *
214  * drive and load print iterator routines passed nil instance context
215  * because only needed for ports that are impossible in tasks
216  */
prt_1task_drvlds(vpiHandle thref)217 static void prt_1task_drvlds(vpiHandle thref)
218 {
219  vpiHandle iter;
220 
221  iter = vpi_iterate(vpiReg, NULL);
222  if (iter != NULL) prt_1iter_drvlds(iter, NULL);
223  iter = vpi_iterate(vpiVariables, thref);
224  if (iter != NULL) prt_1iter_drvlds(iter, NULL);
225 
226  /* include all contained named blocks */
227  iter = vpi_iterate(vpiInternalScope, thref);
228  for (;;)
229   {
230    if ((thref = vpi_scan(iter)) == NULL) break;
231    prt_1task_drvlds(thref);
232   }
233 }
234 
235 /*
236  * routine to build an error indication string
237  */
my_error_handler(struct t_cb_data * cbp)238 int my_error_handler(struct t_cb_data *cbp)
239 {
240  struct t_vpi_error_info einfotab;
241  struct t_vpi_error_info *einfop;
242  char s1[128];
243 
244  einfop = &einfotab;
245  vpi_chk_error(einfop);
246 
247  if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
248  else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
249  else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
250  else strcpy(s1, "**unknown**");
251 
252  vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n  %s\n",
253   einfop->code, s1, einfop->level, einfop->file, einfop->line,
254   einfop->message);
255 
256  /* if serious error give up */
257  if (einfop->level == vpiError || einfop->level == vpiSystem
258   || einfop->level == vpiInternal)
259   {
260    vpi_printf("**FATAL: encountered error - giving up\n");
261    vpi_sim_control(vpiFinish, 0);
262   }
263  return(0);
264 }
265 
266 
267 /* Template functin table for added user systf tasks and functions.
268    See file vpi_user.h for structure definition
269    Note only vpi_register_systf and vpi_ or tf_ utility routines that
270    do not access the simulation data base may be called from these routines
271 */
272 
273 /* all routines are called to register cbs */
274 /* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
275 /* before source is read */
276 void (*vlog_startup_routines[]) () =
277 {
278  register_scan_cb,
279  0
280 };
281 
282 /* routine to do the systf registering - probably should go in other file */
283 /* usually only vpi_ PLI 2.0 systf or cb registering is done here */
284 
285 /*
286  * register the start of sim scan call back and set up error handling
287  *
288  * notice making version of Cver that prints some stuff to start but
289  * is a normal Cver
290  *
291  * since handle not save (passed back?), no way to find out cb info
292  */
register_scan_cb(void)293 void register_scan_cb(void)
294 {
295  vpiHandle href, href2;
296  struct t_cb_data *ecbp, *cbp;
297 struct t_cb_data cbrec;
298 
299  /* notice cb records must be in global storage */
300  ecbp = &cbrec;
301  ecbp->reason = cbPLIError;
302  ecbp->cb_rtn = my_error_handler;
303  ecbp->obj = NULL;
304  ecbp->time = NULL;
305  ecbp->value = NULL;
306  ecbp->user_data = NULL;
307 
308  /* probably should check for error here */
309  if ((href = vpi_register_cb(ecbp)) == NULL)
310   vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
311 
312  cbp = &cbrec;
313  cbp->reason = cbStartOfSimulation;
314  cbp->cb_rtn = process_all_insts;
315  cbp->obj = NULL;
316  cbp->time = NULL;
317  cbp->value = NULL;
318  cbp->user_data = NULL;
319 
320  /* probably should check for error here */
321  if ((href2 = vpi_register_cb(cbp)) == NULL)
322   vpi_printf(
323    "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
324  /* if not registered will be no call backs */
325 
326  /* set the processing routine */
327  iproc_rtn = prt_drvlds;
328 }
329 
330 /* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
331 /* in standard PLI vlog_startup_routines table */
vpi_compat_bootstrap(void)332 void vpi_compat_bootstrap(void)
333 {
334  int i;
335 
336  for (i = 0;; i++)
337   {
338    if (vlog_startup_routines[i] == NULL) break;
339    vlog_startup_routines[i]();
340   }
341 }
342