1 /*
2 * test of get delays vpi_ tasks (some commented out but all cases)
3 */
4
5 #include <stdio.h>
6 #include <string.h>
7
8 #include "vpi_user.h"
9 #include "cv_vpi_user.h"
10
11 #define TRUE 1
12 #define FALSE 0
13
14 int (*iproc_rtn)();
15
16 /* local function prototypes */
17 static void process_inst(vpiHandle);
18 static char *get_tchknam(char *, int);
19
20 /* global function prototypes */
21 extern int process_all_insts(struct t_cb_data *);
22 extern int prt_inst_delays(vpiHandle);
23 extern int my_error_handler(struct t_cb_data *);
24 extern void register_scan_cb(void);
25
26 /*
27 * routine to get and zero all delays in design
28 */
process_all_insts(struct t_cb_data * cbp)29 int process_all_insts(struct t_cb_data *cbp)
30 {
31 int isiz, tunit, tprec;
32 vpiHandle topiter, topiref;
33
34 /* should convert these into unit names */
35 tunit = vpi_get(vpiTimeUnit, NULL);
36 tprec = vpi_get(vpiTimePrecision, NULL);
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 (timescale %d / %d).\n", isiz,
42 tunit, tprec);
43 for (;;)
44 {
45 if ((topiref = vpi_scan(topiter)) == NULL) break;
46 process_inst(topiref);
47 }
48 vpi_printf(" All instances processed.\n");
49 /* notice Verilog model is not run, just data for PLI */
50 vpi_sim_control(vpiFinish, 0);
51 return(0);
52 }
53
54 /*
55 * process one instance and recursively process all under instances
56 * processing is top down depth first
57 */
process_inst(vpiHandle up_ihref)58 static void process_inst(vpiHandle up_ihref)
59 {
60 int isiz, tunit, tprec;
61 vpiHandle iter, ihref;
62
63 iproc_rtn(up_ihref);
64 iter = vpi_iterate(vpiModule, up_ihref);
65 if (iter == NULL) isiz = 0; else isiz = vpi_get(vpiSize, iter);
66
67 tunit = vpi_get(vpiTimeUnit, up_ihref);
68 tprec = vpi_get(vpiTimePrecision, up_ihref);
69
70 vpi_printf(" There are %d instances in %s (timescale: %d / %d).\n", isiz,
71 vpi_get_str(vpiFullName, up_ihref), tunit, tprec);
72 if (iter == NULL) return;
73 for (;;)
74 {
75 if ((ihref = vpi_scan(iter)) == NULL) break;
76 process_inst(ihref);
77 }
78 }
79
80 /*
81 * simplest processing routine - just print full path name
82 */
prt_inst_delays(vpiHandle ihref)83 int prt_inst_delays(vpiHandle ihref)
84 {
85 vpiHandle iter, href;
86 s_vpi_delay drec;
87 s_vpi_time delarr[12];
88 char s1[1024], s2[1024];
89
90 drec.da = &(delarr[0]);
91 /* drec.time_type = vpiSimTime; */
92 drec.time_type = vpiScaledRealTime;
93 drec.mtm_flag = FALSE;
94 drec.append_flag = FALSE;
95 drec.pulsere_flag = FALSE;
96 /* gates - use scan returns nil, nil iterator pattern */
97 drec.no_of_delays = 2;
98 iter = vpi_iterate(vpiPrimitive, ihref);
99 for (;;)
100 {
101 if ((href = vpi_scan(iter)) == NULL) break;
102 if (vpi_iterate(vpiDelay, href) == NULL) continue;
103
104 vpi_get_delays(href, &drec);
105 /* expect delays to always fit in 31 bits */
106 if (vpi_get(vpiType, href) == vpiUdp) strcpy(s1, "udp");
107 else strcpy(s1, "gate");
108 strcpy(s2, vpi_get_str(vpiDefName, href));
109 vpi_printf(" %s %s %s has delay #(%g, %g).\n",
110 s2, s1, vpi_get_str(vpiFullName, href), drec.da[0].real, drec.da[1].real);
111 }
112 /* contas */
113 iter = vpi_iterate(vpiContAssign, ihref);
114 for (;;)
115 {
116 if ((href = vpi_scan(iter)) == NULL) break;
117 if (vpi_iterate(vpiDelay, href) == NULL) continue;
118
119 vpi_get_delays(href, &drec);
120 /* expect delays to always fit in 31 bits */
121 vpi_printf(" continuous assign at **%s(%d) has delay #(%g, %g).\n",
122 vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
123 drec.da[0].real, drec.da[1].real);
124 }
125 /* paths */
126 drec.no_of_delays = 6;
127 drec.time_type = vpiScaledRealTime;
128 iter = vpi_iterate(vpiModPath, ihref);
129 for (;;)
130 {
131 if ((href = vpi_scan(iter)) == NULL) break;
132
133 vpi_get_delays(href, &drec);
134 /* expect delays to always fit in 31 bits */
135 vpi_printf(" path at **%s(%d) has delay #(%g, %g, %g, %g, %g, %g).\n",
136 vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href),
137 drec.da[0].real, drec.da[1].real, drec.da[2].real, drec.da[3].real,
138 drec.da[4].real, drec.da[5].real);
139 }
140 /* timing checks */
141 /* paths */
142 /* drec.no_of_delays = 2; */
143 drec.no_of_delays = 1;
144 /* drec.time_type = vpiSimTime; */
145 drec.time_type = vpiScaledRealTime;
146 iter = vpi_iterate(vpiTchk, ihref);
147 for (;;)
148 {
149 if ((href = vpi_scan(iter)) == NULL) break;
150 vpi_get_delays(href, &drec);
151 get_tchknam(s1, vpi_get(vpiTchkType, href));
152 vpi_printf(" %s timing check at **%s(%d) limit %g.\n",
153 s1, vpi_get_str(vpiFile, href), vpi_get(vpiLineNo, href), drec.da[0].real);
154 }
155 return(0);
156 }
157
158 /*
159 * notice need user routine - no str property
160 */
get_tchknam(char * s,int ttyp)161 static char *get_tchknam(char *s, int ttyp)
162 {
163 switch (ttyp) {
164 case vpiSetup: strcpy(s, "$setup"); break;
165 case vpiHold: strcpy(s, "$hold"); break;
166 case vpiPeriod: strcpy(s, "$period"); break;
167 case vpiWidth: strcpy(s, "$width"); break;
168 case vpiSkew: strcpy(s, "$skew"); break;
169 case vpiRecovery: strcpy(s, "$recovery"); break;
170 case vpiNoChange: strcpy(s, "$nochange"); break;
171 case vpiSetupHold: strcpy(s, "$setuphold"); break;
172 default: strcpy(s, "**out of range**"); break;
173 }
174 return(s);
175 }
176
177 /*
178 * routine to build an error indication string
179 */
my_error_handler(struct t_cb_data * cbp)180 int my_error_handler(struct t_cb_data *cbp)
181 {
182 struct t_vpi_error_info einfotab;
183 struct t_vpi_error_info *einfop;
184 char s1[128];
185
186 einfop = &einfotab;
187 vpi_chk_error(einfop);
188
189 if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
190 else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
191 else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
192 else strcpy(s1, "**unknown**");
193
194 vpi_printf("**ERR(%s) %s (level %d) at **%s(%d):\n %s\n",
195 einfop->code, s1, einfop->level, einfop->file, einfop->line,
196 einfop->message);
197
198 /* if serious error give up */
199 if (einfop->level == vpiError || einfop->level == vpiSystem
200 || einfop->level == vpiInternal)
201 {
202 vpi_printf("**FATAL: encountered error - giving up\n");
203 vpi_sim_control(vpiFinish, 0);
204 }
205 return(0);
206 }
207
208
209 /* Template functin table for added user systf tasks and functions.
210 See file vpi_user.h for structure definition
211 Note only vpi_register_systf and vpi_ or tf_ utility routines that
212 do not access the simulation data base may be called from these routines
213 */
214
215 /* all routines are called to register cbs */
216 /* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
217 /* before source is read */
218 void (*vlog_startup_routines[]) () =
219 {
220 register_scan_cb,
221 0
222 };
223
224 /* routine to do the systf registering - probably should go in other file */
225 /* usually only vpi_ PLI 2.0 systf or cb registering is done here */
226
227 /*
228 * register the start of sim scan call back and set up error handling
229 *
230 * notice making version of Cver that prints some stuff to start but
231 * is a normal Cver
232 *
233 * since handle not save (passed back?), no way to find out cb info
234 */
register_scan_cb(void)235 void register_scan_cb(void)
236 {
237 vpiHandle href, href2;
238 struct t_cb_data *ecbp, *cbp;
239 struct t_cb_data cbrec;
240
241 /* notice cb records must be in global storage */
242 ecbp = &cbrec;
243 ecbp->reason = cbPLIError;
244 ecbp->cb_rtn = my_error_handler;
245 ecbp->obj = NULL;
246 ecbp->time = NULL;
247 ecbp->value = NULL;
248 ecbp->user_data = NULL;
249
250 /* probably should check for error here */
251 if ((href = vpi_register_cb(ecbp)) == NULL)
252 vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
253
254 cbp = &cbrec;
255 cbp->reason = cbStartOfSimulation;
256 cbp->cb_rtn = process_all_insts;
257 cbp->obj = NULL;
258 cbp->time = NULL;
259 cbp->value = NULL;
260 cbp->user_data = NULL;
261
262 /* probably should check for error here */
263 if ((href2 = vpi_register_cb(cbp)) == NULL)
264 vpi_printf(
265 "**ERR: PLI 2.0 can not register start of sim setup callback.\n");
266 /* if not registered will be no call backs */
267
268 /* set the processing routine */
269 iproc_rtn = prt_inst_delays;
270 }
271
272 /* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
273 /* in standard PLI vlog_startup_routines table */
vpi_compat_bootstrap(void)274 void vpi_compat_bootstrap(void)
275 {
276 int i;
277
278 for (i = 0;; i++)
279 {
280 if (vlog_startup_routines[i] == NULL) break;
281 vlog_startup_routines[i]();
282 }
283 }
284