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