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