/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */ /* simple hello world pli 2.0 task and real function */ #include #include #include "vpi_user.h" #include "cv_vpi_user.h" /* local prototypes */ static void print_systfs(void); static int count_systf_args(vpiHandle); static void vpiset_to_real(vpiHandle, double); static void prtvpiemsg(struct t_vpi_error_info *); /* global prototypes */ extern PLI_INT32 hello(void); extern void register_my_systfs(void); /* * this is routine to implement registered systf call back * * notice vpi_user.h requires function return int so using dummy 0 */ PLI_INT32 hello(void) { vpiHandle href, iref; /* quick test of systf iterator */ print_systfs(); href = vpi_handle(vpiSysTfCall, NULL); if (href == NULL) { vpi_printf("**ERR: $hello PLI 2.0 task registeration problem\n"); return(0); } if ((iref = vpi_iterate(vpiArgument, href)) != NULL) { vpi_printf( "**ERR: $hello PLI 2.0 task called with %d arguments but none allowed\n", count_systf_args(iref)); return(0); } vpi_printf("hello world\n"); return(0); } /* * print a list of register systf routines */ static void print_systfs(void) { vpiHandle iter, tfref; s_vpi_systf_data systf_inf; p_vpi_systf_data tfinfp; vpi_printf("--------------------------------------------------------------\n"); if ((iter = vpi_iterate(vpiUserSystf, NULL)) == NULL) { vpi_printf(" No registers vpi_ system tasks or functions.\n"); vpi_printf( "--------------------------------------------------------------\n"); return; } /* user provides record that is filled but following current semantics */ /* values pointed to by contents are shared (i.e. must be left as is) */ tfinfp = &systf_inf; for (;;) { if ((tfref = vpi_scan(iter)) == NULL) break; vpi_get_systf_info(tfref, tfinfp); if (tfinfp->type == vpiSysTask) vpi_printf("vpi_ system task %s registered.\n", tfinfp->tfname); else { vpi_printf("vpi_ system function %s (ret. type %d) registered.\n", tfinfp->tfname, tfinfp->sysfunctype); } } vpi_printf( "--------------------------------------------------------------\n"); } /* * count arguments */ static int count_systf_args(vpiHandle iref) { int anum = 0; while (vpi_scan(iref) != NULL) anum++; return(anum); } /* * real function that returns something and prints hello world * * should probably call vpi_chk_error - not just check for null handle * returns 0 because vpi_user.h requires register funcs be int returning */ PLI_INT32 realfhello(void) { vpiHandle href, iref; href = vpi_handle(vpiSysTfCall, NULL); if (href == NULL) { vpi_printf("** ERR: $realfhello PLI 2.0 can not access sysf call handle\n"); return(0); } if ((iref = vpi_iterate(vpiArgument, href)) != NULL) { vpi_printf( "**ERR: $realfhello PLI 2.0 task called with %d arguments but none allowed\n", count_systf_args(iref)); return(0); } vpiset_to_real(href, 19.0); vpi_printf("hello world\n"); return(0); } /* * set a handle to a real value * * user must make sure href can have have a value put into it * notice the key to vpi_ processing is to save and pass handles */ static void vpiset_to_real(vpiHandle href, double d1) { struct t_vpi_value valrec; struct t_vpi_error_info einfotab; valrec.format = vpiRealVal; valrec.value.real = d1; vpi_put_value(href, &valrec, NULL, vpiNoDelay); if (vpi_chk_error(&einfotab)) { vpi_printf("** ERR: vpi_put_value of real error:\n"); prtvpiemsg(&einfotab); } } /* * routine to build an error indication string */ static void prtvpiemsg(struct t_vpi_error_info *einfop) { char s1[128]; if (einfop->state == vpiCompile) strcpy(s1, "vpiCompile"); else if (einfop->state == vpiPLI) strcpy(s1, "vpiPLI"); else if (einfop->state == vpiRun) strcpy(s1, "vpiRun"); else strcpy(s1, "**unknown**"); vpi_printf("%s: %s error (level %d) at **%s(%d):\n %s\n", einfop->code, s1, einfop->level, einfop->file, einfop->line, einfop->message); } /* Template functin table for added user systf tasks and functions. See file vpi_user.h for structure definition Note only vpi_register_systf and vpi_ or tf_ utility routines that do not access the simulation data base may be called from these routines */ /* all routines are called to register system tasks */ /* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */ /* before source is read */ void (*vlog_startup_routines[]) () = { register_my_systfs, 0 }; /* routine to do the systf registering - probably should go in other file */ /* usually only vpi_ PLI 2.0 systf registering is done here */ /* * register all vpi_ PLI 2.0 style user system tasks and functions */ void register_my_systfs(void) { p_vpi_systf_data systf_data_p; /* use predefined table form - could fill systf_data_list dynamically */ static s_vpi_systf_data systf_data_list[] = { { vpiSysTask, 0, "$hello", hello, NULL, NULL, NULL }, { vpiSysFunc, vpiRealFunc, "$realfhello", realfhello, NULL, NULL, NULL }, { 0, 0, NULL, NULL, NULL, NULL, NULL } }; systf_data_p = &(systf_data_list[0]); while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++); } /* dummy +loadvpi= boostrap routine - mimics old style exec all routines */ /* in standard PLI vlog_startup_routines table */ void vpi_compat_bootstrap(void) { int i; for (i = 0;; i++) { if (vlog_startup_routines[i] == NULL) break; vlog_startup_routines[i](); } }