1 /* Copyright (c) 1995-2003 Pragmatic C Software Corp. */
2 
3 /* version of hello that does not work */
4 /* shows problem with tf_ style checking in vpi_ */
5 
6 #include <stdio.h>
7 #include <string.h>
8 
9 #include "vpi_user.h"
10 #include "cv_vpi_user.h"
11 
12 /* local prototypes */
13 static void prtvpiemsg(struct t_vpi_error_info *);
14 static int count_systf_args(vpiHandle);
15 
16 /* global prototypes */
17 extern PLI_INT32 hello_setup(char *);
18 extern PLI_INT32 hello_chk(struct t_cb_data *);
19 extern void register_my_systfs(void);
20 
21 /*
22  * possible pattern for register vpi_ system tasks and functions
23  */
24 
25 /*
26  * this is routine to implement registered systf call back
27  *
28  * notice vpi_user.h requires function return int so using dummy 0
29  */
hello(void)30 PLI_INT32 hello(void)
31 {
32  vpi_printf("hello world\n");
33  return(0);
34 }
35 
36 /*
37  * check each hello call, in struct as short but passed as int
38  *
39  * dynamic nature of PLI 2.0 requires checking just before simulation
40  * because need to wait until simulation data structure is built
41  */
hello_setup(char * data)42 PLI_INT32 hello_setup(char *data)
43 {
44  vpiHandle href;
45  struct t_cb_data *cbp;
46  struct t_cb_data cbrec;
47 
48  vpi_printf("... executing vpi_ systf compiletf routine.\n");
49  cbp = &cbrec;
50  cbp->reason = cbEndOfCompile;
51  cbp->cb_rtn = hello_chk;
52  cbp->obj = NULL;
53  cbp->time = NULL;
54  cbp->value = NULL;
55  cbp->user_data = NULL;
56 
57  /* probably should check for error here */
58  if ((href = vpi_register_cb(cbp)) == NULL)
59   vpi_printf(
60    "**ERR: $hello PLI 2.0 task cannot register end of compile check routine");
61  /* if not registered will be no call backs */
62  return(0);
63 }
64 
65 /*
66  * check - must be at end of compile after sim data structure set up
67  */
hello_chk(struct t_cb_data * cbp)68 PLI_INT32 hello_chk(struct t_cb_data *cbp)
69 {
70  vpiHandle href, iref;
71  struct t_vpi_error_info einfotab;
72 
73  vpi_printf("... executing EndOfCompile callback for checking.\n");
74  href = vpi_handle(vpiSysTfCall, NULL);
75  if (vpi_chk_error(&einfotab))
76   {
77    if (href != NULL) vpi_printf("... why is handle not nil\n");
78    vpi_printf("** ERR: $hello PLI 2.0 can not access systf call handle\n");
79    prtvpiemsg(&einfotab);
80    /* vpi_sim_control(vpiFinish, 0); */
81   }
82  iref = vpi_iterate(vpiArgument, href);
83  if (vpi_chk_error(&einfotab))
84   {
85    vpi_printf("** ERR: vpi_iterate error:\n");
86    prtvpiemsg(&einfotab);
87    vpi_sim_control(vpiFinish, 0);
88   }
89  if (iref != NULL)
90   {
91    vpi_printf(
92     "** ERR: $hello PLI 2.0 task called with %d arguments but none allowed",
93     count_systf_args(iref));
94    vpi_free_object(iref);
95    vpi_sim_control(vpiFinish, 0);
96   }
97  return(0);
98 }
99 
100 /*
101  * routine to build an error indication string
102  */
prtvpiemsg(struct t_vpi_error_info * einfop)103 static void prtvpiemsg(struct t_vpi_error_info *einfop)
104 {
105  char s1[128];
106 
107  if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile");
108  else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI");
109  else if (einfop->state == vpiRun) strcpy(s1, "vpiRun");
110  else strcpy(s1, "**unknown**");
111 
112  vpi_printf("%s: %s error (level %d) at **%s(%d):\n  %s\n",
113   einfop->code, s1, einfop->level, einfop->file, einfop->line,
114   einfop->message);
115 }
116 
117 /*
118  * count arguments
119  */
count_systf_args(vpiHandle iref)120 static int count_systf_args(vpiHandle iref)
121 {
122  int anum = 0;
123 
124  while (vpi_scan(iref) != NULL) anum++;
125  return(anum);
126 }
127 
128 /* Template functin table for added user systf tasks and functions.
129    See file vpi_user.h for structure definition
130    Note only vpi_register_systf and vpi_ or tf_ utility routines that
131    do not access the simulation data base may be called from these routines
132 */
133 
134 /* all routines are called to register system tasks */
135 /* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */
136 /* before source is read */
137 void (*vlog_startup_routines[]) () =
138 {
139  register_my_systfs,
140  0
141 };
142 
143 /* routine to do the systf registering - probably should go in other file */
144 /* usually only vpi_ PLI 2.0 systf registering is done here */
145 
146 /*
147  * register all vpi_ PLI 2.0 style user system tasks and functions
148  */
register_my_systfs(void)149 void register_my_systfs(void)
150 {
151  p_vpi_systf_data systf_data_p;
152 
153  /* use predefined table form - could fill systf_data_list dynamically */
154  static s_vpi_systf_data systf_data_list[] = {
155   { vpiSysTask, 0, "$hello", hello, hello_setup, NULL, NULL },
156   { 0, 0, NULL, NULL, NULL, NULL, NULL }
157  };
158 
159  systf_data_p = &(systf_data_list[0]);
160  while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
161 }
162 
163 /* dummy +loadvpi= boostrap routine - mimics old style exec all routines */
164 /* in standard PLI vlog_startup_routines table */
vpi_compat_bootstrap(void)165 void vpi_compat_bootstrap(void)
166 {
167  int i;
168 
169  for (i = 0;; i++)
170   {
171    if (vlog_startup_routines[i] == NULL) break;
172    vlog_startup_routines[i]();
173   }
174 }
175