/* Copyright (c) 1995-2003 Pragmatic C Software Corp. */ /* * test of continous assign (decomposition and handle by lookup routines) * * unit test of various ways to process lavlue expressions * test does nothing */ #include #include #include "vpi_user.h" #include "cv_vpi_user.h" #define TRUE 1 #define FALSE 0 int (*iproc_rtn)(); /* local function prototypes */ static void process_inst(vpiHandle); static int decompose_expr(vpiHandle, int); /* global function prototypes */ extern void register_scan_cb(); extern int process_contas(vpiHandle); extern int my_error_handler(struct t_cb_data *); extern void register_scan_cb(void); /* * process all instances calling processing routine for each */ int process_all_insts(struct t_cb_data *cbp) { int isiz; vpiHandle topiter, topiref; /* build the iterator for each module */ topiter = vpi_iterate(vpiModule, NULL); isiz = vpi_get(vpiSize, topiter); vpi_printf(" There are %d top level modules.\n", isiz); for (;;) { if ((topiref = vpi_scan(topiter)) == NULL) break; process_inst(topiref); } vpi_printf(" >>> All instances processed - continuing with simulation.\n"); return(0); } /* * process one instance and recursively process all under instances * processing is top down depth first */ static void process_inst(vpiHandle up_ihref) { int isiz; vpiHandle iter, ihref; iproc_rtn(up_ihref); if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return; isiz = vpi_get(vpiSize, iter); vpi_printf(" There are %d instances in %s.\n", isiz, vpi_get_str(vpiFullName, up_ihref)); for (;;) { if ((ihref = vpi_scan(iter)) == NULL) break; process_inst(ihref); } } /* * process all continuous assignments */ int process_contas(vpiHandle ihref) { vpiHandle iter, caref, lhsref, rhsref; if ((iter = vpi_iterate(vpiContAssign, ihref)) == NULL) return(0); for (;;) { if ((caref = vpi_scan(iter)) == NULL) break; lhsref = vpi_handle(vpiLhs, caref); if (!decompose_expr(lhsref, TRUE)) vpi_printf(" Why is concatenate left hand side not lvalue at **%s(%d)\n", vpi_get_str(vpiFile, caref), vpi_get(vpiLineNo, caref)); rhsref = vpi_handle(vpiRhs, caref); decompose_expr(rhsref, FALSE); } return(0); } /* * process an expression - build most decomposed handles and print each * also look up names and compare to original handle */ static int decompose_expr(vpiHandle xref, int islhs) { register int i; int xtyp, otyp, bad_lvalue, ps1, ps2, i2; vpiHandle varef, varef2, iter, scopref, ndxref, href, xref2; s_vpi_value tmpval; char nam[1025]; xtyp = vpi_get(vpiType, xref); /* case 1: all lvalues except concatenate */ if (xtyp != vpiOperation && xtyp != vpiConstant) { varef = xref; /* get scope for selects, need to get scope from parent */ if (xtyp == vpiNetBit || xtyp == vpiRegBit || xtyp == vpiPartSelect) { varef = vpi_handle(vpiParent, varef); scopref = vpi_handle(vpiScope, varef); strcpy(nam, vpi_get_str(vpiName, varef)); } else { scopref = vpi_handle(vpiScope, varef); /* test handle by name */ /* strcpy(nam, vpi_get_str(vpiName, varef)); */ strcpy(nam, vpi_get_str(vpiName, varef)); } /* if ((varef2 = vpi_handle_by_name(nam, NULL)) == NULL) */ if ((varef2 = vpi_handle_by_name(nam, scopref)) == NULL) { vpi_printf("--- why is variable %s not in scope %s?\n", nam, vpi_get_str(vpiFullName, scopref)); return(TRUE); } if (!vpi_compare_objects(varef, varef2)) vpi_printf("--- why did handle by name not return same object (%s)?\n", vpi_get_str(vpiFullName, varef)); if (xtyp == vpiPartSelect) { ndxref = vpi_handle(vpiLeftRange, xref); tmpval.format = vpiIntVal; vpi_get_value(ndxref, &tmpval); ps1 = tmpval.value.integer; ndxref = vpi_handle(vpiRightRange, xref); tmpval.format = vpiIntVal; vpi_get_value(ndxref, &tmpval); ps2 = tmpval.value.integer; /* notice not normalized to h:0 form */ if (ps1 > ps2) { i2 = ps1; ps1 = ps2; ps2 = i2; } for (i = ps2; i >= ps1; i--) { /* notice must index variable part selected from not part select */ href = vpi_handle_by_index(varef, i); ndxref = vpi_handle(vpiIndex, href); tmpval.format = vpiIntVal; vpi_get_value(ndxref, &tmpval); i2 = tmpval.value.integer; if (i2 != i) { vpi_printf( "--- part select index of %s by one method %d and by other %d\n", vpi_get_str(vpiFullName, varef), i2, i); } else { vpi_printf(" Part select %s index %d processed.\n", vpi_get_str(vpiFullName, varef), i2); } } } else if (xtyp == vpiNetBit || xtyp == vpiRegBit) { ndxref = vpi_handle(vpiIndex, xref); tmpval.format = vpiIntVal; vpi_get_value(ndxref, &tmpval); i = tmpval.value.integer; href = vpi_handle_by_index(varef, i); ndxref = vpi_handle(vpiIndex, href); tmpval.format = vpiIntVal; vpi_get_value(ndxref, &tmpval); i2 = tmpval.value.integer; if (i2 != i) { vpi_printf("--- index of %s by one method %d and by other %d\n", vpi_get_str(vpiFullName, varef)); } else { vpi_printf(" Bit select %s index %d processed.\n", vpi_get_str(vpiFullName, varef), i2); } } else vpi_printf(" Variable %s processed.\n", vpi_get_str(vpiFullName, varef), i2); return(TRUE); } /* non lvalue expression just ignore */ if (xtyp != vpiOperation) return(FALSE); otyp = vpi_get(vpiOpType, xref); if (otyp != vpiConcatOp) return(FALSE); vpi_printf(" --- processing a concatenate:\n"); /* case 2: concatenate - notice use expr. handle not concat operator */ iter = vpi_iterate(vpiOperand, xref); for (bad_lvalue = FALSE;;) { if ((xref2 = vpi_scan(iter)) == NULL) break; if (!decompose_expr(xref2, islhs)) bad_lvalue = TRUE; } vpi_printf(" === end of concatenate\n"); return(!bad_lvalue); } /* * 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 == vpiError || einfop->level == vpiSystem || einfop->level == vpiInternal) { vpi_printf("**FATAL: encountered error - giving up\n"); vpi_sim_control(vpiFinish, 0); } return(0); } /* 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 cbs */ /* called just after all PLI 1.0 tf_ veriusertfs table routines are set up */ /* before source is read */ void (*vlog_startup_routines[]) () = { register_scan_cb, 0 }; /* routine to do the systf registering - probably should go in other file */ /* usually only vpi_ PLI 2.0 systf or cb registering is done here */ /* * register the start of sim scan call back and set up error handling * * notice making version of Cver that prints some stuff to start but * is a normal Cver * * since handle not save (passed back?), no way to find out cb info */ void register_scan_cb(void) { vpiHandle href, href2; struct t_cb_data *ecbp, *cbp; 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"); cbp = &cbrec; cbp->reason = cbStartOfSimulation; cbp->cb_rtn = process_all_insts; cbp->obj = NULL; cbp->time = NULL; cbp->value = NULL; cbp->user_data = NULL; /* probably should check for error here */ if ((href2 = vpi_register_cb(cbp)) == NULL) vpi_printf( "**ERR: PLI 2.0 can not register start of sim setup callback.\n"); /* if not registered will be no call backs */ /* set the processing routine */ iproc_rtn = process_contas; } /* 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](); } }