/* * routine to setup memory filling routine - set param to 0 on error else 1 * function: $plisetupmemfill(memsiz, memwid) */ static void plisetupmemfill(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); tf_putp(0, 1); /* assume memory goes from 1 to size */ last_i = 0; }
/*---------------------------------------------------------------------------- * int * do_ch_dispmon() * entry point for $ch_dispmon * * int * ch_dispmon() * Return Value -- * always 0 * * Design -- * Error check V-side arguments, modify hash table entries * - Set all tags >= l_tag on/off * - Set default if "all" is specified so later initialized units may * use the 'all' setting too. * * Side effects -- * modifies hash table entries and default ms entries .. *---------------------------------------------------------------------------- */ int do_ch_dispmon(void) { if (tf_nump() < 3) { printf("ERROR(ch_dispmon): Usage: " "$ch_dispmon(unit, tag, value(1 = on, 0 = off))\n"); } else { char *l_unit_name=tf_getcstringp(1); int l_tag= tf_getp(2); int l_value=tf_getp(3); return(ch_dispmon(l_unit_name, l_tag, l_value)); } return 0; }
/*---------------------------------------------------------------------------- * int * enable_dispmon_finish() * entry point for $enable_dispmon_finish * * Return Value -- * always 0 * * Design -- * parameter to syscall is 1=let dispmon finish * 0=let external prog finish * This is exactly the opposite of what we're tracking * Side effects -- * none *---------------------------------------------------------------------------- */ int enable_dispmon_finish() { ms.external_finish=tf_getp(1); ms.external_finish=!ms.external_finish; return 0; }
int fseq_calltf() { int N, result; N = tf_getp(1); result = fibonacci(N); tf_putp(0, result); return(0); }
static int calltf(int user_data, int reason) { // char *inst = tf_getinstance(); (void)user_data; /* Parameter is not used. */ (void)reason; /* Parameter is not used. */ tf_putp (0, tf_getp(1)); return 0; }
/* * routine to set memory * function: $pli_memfill(mem[i], i) */ static void plimemfill(int data, int reason) { int i; char memval[1024]; 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, "%s", 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; /* this is #0, in CVC you would use extension routine tf_strputp */ /* it is identical to tf_strdelputp except string assignment immediate */ #ifdef __HAS_STRPUTP__ /* notice need final delay type parameter since may need to cancel */ /* events if delay form used elsewhere */ printf("*** using tf_strputp\n"); if (tf_strputp(1, memwid, 'b', memval) == 0) #else if (tf_strdelputp(1, memwid, 'b', memval, 0, 0) == 0) #endif { tf_error("strdelput of index memory failed"); tf_putp(0, 0); return; } tf_putp(0, 1); }
/* * 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); }
int pliread_call () { char line[200]; int fhandle; char * fmt; int value; FILE * fp; /* Get the handle */ fhandle = tf_getp (1); /* Check it out first */ if (fhandle < 0 || fhandle >= MAX_FILES) { printf ("\nPLIREAD: Invalid file handle. Aborting read."); return 1; } /* Handle is used to look up actual FILE pointer */ fp = fptab[fhandle]; if (fp == 0) { printf ("\nPLIREAD: File appears to be closed. Aborting read."); return 1; } /* OK. Try and read a line, check for EOFs.. */ if (!feof(fp)) { fgets (line, sizeof(line), fp); if (!feof(fp)) { if (strlen(line) > 0) { /* Got a promising line. Get format string from user */ fmt = tf_getcstringp(2); if (PLIREAD_VERBOSE) printf ("\nPLIREAD: Using format string of <%s>.", fmt); /* Here is the actual read */ sscanf (line, fmt, &value); if (PLIREAD_VERBOSE) printf ("\nPLIREAD: Read integer value of %d (0x%X).", value, value); /* That's it. Stick value back into caller's 3rd argument */ tf_putp(3, value); } } } return 0; }
/*---------------------------------------------------------------------------- * static void * do_mon(int p_add_newline) * error check Verilog side arguments, generate then print line * * Return Value -- * none * * Design -- * * Side effects --1H * possible death, modifies global_errors *---------------------------------------------------------------------------- */ static int do_mon(int p_add_newline) { char *unit_name_arg = tf_getcstringp(1); char *l_unit; int l_tag = tf_getp(2); int l_mon_type; if(!unit_name_arg) { char *mipname = tf_mipname(); printf("ERROR: failed to read first argument to $dispmon or " "$writemon, in 'do_mon()'. Hierarchy is '%s'\n", mipname ? mipname : "NULL"); return 0; } else { l_unit = strdup(unit_name_arg); if(!l_unit) { printf("ERROR: strdup failed in 'do_mon()'\n"); return 0; } } if(!ms.unit_tbl) init_unit_tbl(); l_mon_type=mon_type_for(l_unit, l_tag); if(l_mon_type!=NO_MON_TYPE) { int l_input_parms = tf_nump(); char *l_output=dispmon_parse(tf_getcstringp(3), l_input_parms, 4, l_unit); if (0!=l_output) { print_tagged_line("", l_unit, l_output, l_mon_type, p_add_newline); free(l_output); } } free(l_unit); return 0; }
void info_call(int data, int reason) { char *ptr_mipname; int i, level; int ms, us, ns, ps; get_time (&ms, &us, &ns, &ps); ptr_mipname = tf_mipname(); /* Requires at least two arguments */ if (tf_nump() < ARG2) { tf_error("$info requires at least two arguments, info-level and format-string"); tf_dofinish(); return; } /* First argument to $info() must be a value */ if (tf_typep(ARG1) != tf_readonly) { tf_error("First argument to $info must be a value"); tf_dofinish(); } /* Second argument to $info() must be a string */ if (tf_typep(ARG2) != tf_string) { tf_error("Second argument to $info must be a formating string"); tf_dofinish(); } level = tf_getp(ARG1); if (level == 0) { io_printf ("%05d.%03d.%03d.%03d: INFO(%d): %s:%s\n", ms,us,ns,ps, level, ptr_mipname, format(ptr_mipname)); } else { for (i = 0; i < mon_path_num; i++) { if ((level <= mon_level[i]) && (strmatch (mon_inst_path[i], ptr_mipname) == 0) ) { io_printf ("%05d.%03d.%03d.%03d: INFO(%d): %s:%s\n", ms,us,ns,ps, level, ptr_mipname, format(ptr_mipname)); } } } return; }
static int calltf(int ud, int reason) { int i; PLI_BYTE8 *inst = tf_getinstance(); (void)ud; /* Parameter is not used. */ (void)reason; /* Parameter is not used. */ for (i = 1; i < 5; i++) { io_printf("tf_getp(%d)\t\t-> %d\n", i, (int)tf_getp(i)); io_printf("tf_igetp(%d,inst)\t-> %d\n", i, (int)tf_igetp(i,inst)); io_printf("tf_getrealp(%d)\t\t-> %f\n", i, tf_getrealp(i)); io_printf("tf_igetrealp(%d,inst)\t-> %f\n", i, tf_igetrealp(i,inst)); } return 0; }
int pliclose_call () { int fhandle; /* Get handle from 1st argument */ fhandle = tf_getp(1); /* Check it out a little bit */ if (fhandle < 0 || fhandle >= MAX_FILES) { printf ("\nPLICLOSE: Error, invalid file handle %d.", fhandle); return 1; } /* Close the file. Get actual FILE pointer from our little local table. */ fclose (fptab[fhandle]); /* Clear our table entry so we can reuse */ fptab[fhandle] = 0; return 0; }
/* Set the current calue of the modulo used to wrap the counter. 1st argument to PLI call should be the modulo value. */ int mypli_setmodulo_call () { modulo = tf_getp (1); printf ("\nMYPLI_GETCOUNT: Set modulo to %d\n", modulo); return 0; }