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