/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */ /* implement Verilog $fopen using PLI 2.0 vpi_ routines */ #include #include #include "vpi_user.h" #include "cv_vpi_user.h" /* local function prototypes */ /* global function prototypes */ extern int vpi_fopen_task(void); extern int my_error_handler(struct t_cb_data *); extern void register_cbs(void); extern void register_my_systfs(void); /* * ignore the user data field * this needs error messages */ int vpi_fopen_task(void) { int mcdhtyp; unsigned int mcd; vpiHandle href, iter, a1ref, a2ref; struct t_vpi_value valrec; struct t_vpi_time tmptim; s_vpi_value tmpval; href = vpi_handle(vpiSysTfCall, NULL); if ((iter = vpi_iterate(vpiArgument, href)) == NULL) return(0); if (vpi_get(vpiSize, iter) != 2) return(0); if ((a1ref = vpi_scan(iter)) == NULL) return(0); /* get the 2nd argument vpiReg handle */ if ((a2ref = vpi_scan(iter)) == NULL) return(0); mcdhtyp = vpi_get(vpiType, a2ref); if ((mcdhtyp != vpiReg && mcdhtyp != vpiIntegerVar) || vpi_get(vpiSize, a2ref) != 32) return(0); valrec.format = vpiIntVal; valrec.value.integer = (int) 0; /* if error after here will return 0 */ vpi_put_value(a2ref, &valrec, NULL, vpiNoDelay); tmpval.format = vpiStringVal; /* evaluate expression */ vpi_get_value(a1ref, &tmpval); mcd = vpi_mcd_open(tmpval.value.str); if (mcd != 0) valrec.value.integer = (int) mcd; /* Changed in 1.52 to allow NULL for ignored time field */ tmptim.type = vpiSuppressTime; vpi_put_value(a2ref, &valrec, &tmptim, vpiNoDelay); return(0); } /* * routine to build an error indication string */ int my_error_handler(struct t_cb_data *cbp) { struct t_vpi_error_info einfotab; struct t_vpi_error_info *einfop; char s1[128]; einfop = &einfotab; vpi_chk_error(einfop); 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("**ERR(%s) %s (level %d) at **%s(%d):\n %s\n", einfop->code, s1, einfop->level, einfop->file, einfop->line, einfop->message); /* if serious error give up */ if (einfop->level == vpiSystem || einfop->level == vpiInternal) { vpi_printf("**FATAL: encountered error - giving up\n"); vpi_sim_control(vpiFinish, 0); } /* will just return and leave 0 in vpi_fopen return 2nd argument */ return(0); } /* * register call backs */ void register_cbs(void) { vpiHandle href; struct t_cb_data *ecbp; struct t_cb_data cbrec; /* notice cb records must be in global storage */ ecbp = &cbrec; ecbp->reason = cbPLIError; ecbp->cb_rtn = my_error_handler; ecbp->obj = NULL; ecbp->time = NULL; ecbp->value = NULL; ecbp->user_data = NULL; /* probably should check for error here */ if ((href = vpi_register_cb(ecbp)) == NULL) vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n"); } /* 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, register_cbs, 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, "$vpi_fopen_task", vpi_fopen_task, 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](); } }