/* Copyright (c) 1994-2003 Pragmatic C Software Corp. */ /* * example illustrating using PLI tf_ utility routines to fill memory */ #include #include #include #include "veriuser.h" #include "cv_veriuser.h" int memsiz, memwid, last_i; FILE *memval_s; struct t_tfnodeinfo ninfo; struct t_tfexprinfo xinfo; /* static prototypes */ static int intsize(int, int); static void plisetupmemfil2(int, int); static void check_plimemfil2(int, int); static void plimemfil2(int, int); static int intsize(int data, int reason) { return(32); } /* * routine to setup memory filling routine - set param to 0 on error else 1 * function: $plisetupmemfill(memsiz, memwid) */ static void plisetupmemfil2(int data, int reason) { char *chp; /* get file name as + verilog argument */ if ((chp = mc_scan_plusargs("memfile+")) == NULL || strcmp(chp, "") == 0) { tf_error("missing or empty +memfile+[file name] memory file argument"); tf_putp(0, 0); return; } /* open the file */ if ((memval_s = fopen(chp, "r")) == NULL) { tf_error("unable to open +memfile+ memory file %s", chp); tf_putp(0, 0); return; } /* need memory size for checking */ memsiz = tf_getp(1); memwid = tf_getp(2); if (memwid > 32) { tf_error("for tf_propagatep routine can only use scanf for < 32 bits"); tf_putp(0, 0); return; } tf_putp(0, 1); /* assume memory goes from 1 to size */ last_i = 0; } /* * check the fill memory user PLI function * notice calling tf_error here will inhibit simulation * probably sould also check 2nd index argument */ static void check_plimemfil2(int data, int reason) { if (tf_nump() != 2) { tf_error("$pli_memfil2 has %d arguments - 2 required", tf_nump()); return; } /* this associates nodeinfo struct with argument */ tf_nodeinfo(1, &ninfo); if (ninfo.node_type != TF_MEMORY_NODE) { tf_error("$pli_memfil2 first argument not read/write memory select"); return; } } /* * routine to set memory using tf_propagatep method * * must be 32 bits or less otherwise would need to write vecval manipulation * routines * * function: $pli_memfil2(mem[i], i) * here tfputp would be better choice since only allows non x/z forms */ static void plimemfil2(int data, int reason) { int i; unsigned memval; struct t_vecval *vecp; i = tf_getp(2); if (i < 0 || i > memsiz) { tf_error("cannot fill memory location %d - memory has only %d cells"); tf_putp(0, 0); return; } if (fscanf(memval_s, "%u", &memval) != 1) { /* problably should access OS error name here */ tf_error("error reading memory value for cell %d", i); tf_putp(0, 0); return; } /* probably should add code to check for memval as legal binary number */ /* but can be any width since putp assignment will widen or truncate */ /* make sure index i is legal - since must have used i in memory select */ /* only for checking */ if (i != last_i + 1) { tf_error("memory index %d non in sequence - %d expected", i, last_i + 1); tf_putp(0, 0); return; } last_i = i; tf_exprinfo(1, &xinfo); /* set value - using 32 bit value else would need string to 0*/ vecp = xinfo.expr_value_p; vecp[0].avalbits = (int) memval; vecp[0].bvalbits = 0; /* do assign - notice this forces re-evaluate of argument during assign */ /* SJM 12/20/02 - following LRM, fail is 1 not 0 */ if (tf_propagatep(1) == 1) { tf_error("tf_propagatep of indexed memory failed"); tf_putp(0, 0); } else tf_putp(0, 1); } /* example that goes in user code */ s_tfcell veriusertfs[] = { { userfunction, 0, 0, (int (*)()) intsize, (int (*)()) plisetupmemfil2, 0, "$pli_setupmemfil2", 0}, { userfunction, 0, (int (*)()) check_plimemfil2, (int (*)()) intsize, (int (*)()) plimemfil2, 0, "$pli_memfil2", 0}, /* -- add extra entries here -- */ {0} /* -- this line must always be last -- */ }; /* dummy +loadpli1 boostrap routine - return old style veriusertfs tab */ s_tfcell *pli1_compat_bootstrap(void) { return(veriusertfs); }