/************************************************* lxt2_recordsetup - specify options ************************************************/ int lxt2_recordsetup( int data, int reason ) { int i; acc_initialize(); switch( reason ) { case reason_checktf: if( tf_nump() == 0 ) { tf_error( "not enough arguments to recordsetup" ); tf_dofinish(); } goto DONE; case reason_calltf: if( lxt.inited ) { tf_error( "recording has already started" ); tf_dofinish(); } break; default: goto DONE; } for( i = 1; i <= tf_nump(); ++i ) { lxt2_option( acc_fetch_tfarg_str(i) ); } DONE: acc_close(); return 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; } }
int monitor_checktf(void) { int nump=tf_nump(); if (nump < 3) { cDispmon("disp", MON_ERR, "Usage: $dispmon(\"unit\", tag, " "\"printf-style-format\", modulename, reg-or-int, " "reg-or-int);\nin instance %s", tf_mipname()); } else if (tf_typep(1) != tf_string) { cDispmon("disp", MON_ERR,"dispmon unit name is not a string\n" "in instance %s",tf_mipname()); } else if (tf_typep(3) != tf_string) { cDispmon("disp", MON_ERR, "dispmon format field is not a string\n" "in instance %s", tf_mipname()); } else { size_t nargs=monitor_nfmtargs(tf_getcstringp(3)); if(nargs+3!=nump) { cDispmon("disp",MON_ERR, "wrong number of parameters for format string \"%s\"\n" "in instance %s", tf_getcstringp(3), tf_mipname()); } } return 0; }
/************************************************* lxt2_recordclose - close lxt file and stop recording ************************************************/ int lxt2_recordclose( int data, int reason ) { acc_initialize(); switch( reason ) { case reason_checktf: if( tf_nump() != 0 ) { tf_error( "too many arguments to recordclose" ); tf_dofinish(); } goto DONE; case reason_calltf: if( !lxt.inited ) { tf_error( "recording has not started" ); tf_dofinish(); goto DONE; } break; default: goto DONE; } lxt2_close(); DONE: acc_close(); return 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_plimemfill(int data, int reason) { struct t_tfexprinfo xinfo; if (tf_nump() != 2) { tf_error("$pli_memfill has %d arguments - 2 required", tf_nump()); return; } tf_exprinfo(1, &xinfo); if (xinfo.expr_type != TF_RWMEMSELECT) { tf_error("$pli_memfill first argument not read/write memory select"); return; } }
int util_get_plus_args_num() { /* Example use integer num_vectors; // number of test vectors integer MAX_FAILURES; // max failed vectors before aborting initial begin // get integers from plus argument values num_vectors = $util_get_plus_args_num("num_vectors"); MAX_FAILURES = $util_get_plus_args_num("max_failures"); $display("%d VECTORS IN TEST FILE.", num_vectors); $display("Maximum number of failures is %d", MAX_FAILURES); end */ /* Input: [unsigned int which is a string | * C string ] * Returns: Arg. value in 32 bit integer. * On error returns VERILOG_C_ERROR * Action: Gets the parameter, calls 'mc_scan_plusargs' * to get the arg. value. * */ int np; char *cp; np = tf_nump(); if ( np != 1 ) { if (DEBUG_PLUS_ARGS) { io_printf("get_plus_args_num(): Error: Number of args != 1.\n"); } tf_putp(0, VERILOG_ERROR); return(VERILOG_ERROR); } cp = mc_scan_plusargs(tf_getcstringp(1)); if (cp == NULL ) { if (DEBUG_PLUS_ARGS) { io_printf("get_plus_args_num(): Matching number is not found: %d\n", tf_getcstringp(1)); } tf_putp(0, VERILOG_ERROR); return(VERILOG_ERROR); } if (DEBUG_PLUS_ARGS) io_printf("get_plus_args_num(): Got integer value: %d\n", atoi(cp)); tf_putp(0, atoi(cp) ); return(VERILOG_OK); }
int parse_ch_dispmon(void) { if (tf_nump() != 1) { printf("ERROR(parse_ch_dispmon): Usage: " "$parse_ch_dispmon(\"<unit>=<level>=<0/1>(,<unit>=<level>=<0/1>)*\"\n"); } else { char *l_string=tf_getcstringp(1); scan_n_chdispmon(l_string); } return 0; }
void error_call(int data, int reason) { char *ptr_mipname; char *ptr; int i; 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("$error requires at least two arguments, error-disable-tag, and format-string"); tf_dofinish(); return; } /* First argument to $error() must be a string */ if (tf_typep(ARG1) != tf_string) { tf_error("First argument to $error must be a value"); tf_dofinish(); } /* Second argument to $error() must be a string */ if (tf_typep(ARG2) != tf_string) { tf_error("Second argument to $error must be a formating string"); tf_dofinish(); } for (i = 0; i < diserr_num; i++) { ptr = strchr(diserr_arr[i], '.'); if (ptr == NULL) { if (strcmp (tf_getcstringp(ARG1), diserr_arr[i]) == 0) { io_printf ("%05d.%03d.%03d.%03d: ERROR: %s:%s\n", ms,us,ns,ps, ptr_mipname, format(ptr_mipname)); return; } } else { sprintf (format_buffer, "%s.%s\0", tf_getcstringp(ARG1), ptr_mipname); if (strcmp (format_buffer, diserr_arr[i]) == 0) { io_printf ("%05d.%03d.%03d.%03d: ERROR: %s:%s\n", ms,us,ns,ps, ptr_mipname, format(ptr_mipname)); return; } } } io_printf ("%05d.%03d.%03d.%03d: ERROR: %s:%s\n", ms,us,ns,ps, ptr_mipname, format(ptr_mipname)); if (!error_disable) tf_dofinish(); return; }
/*---------------------------------------------------------------------------- * 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; }
/*---------------------------------------------------------------------------- * 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; }
int fseq_checktf() { int err = 0; if (tf_nump() != 1) { tf_error("$fibonacci requires exactly 1 argument.\n"); err = 1; } if (tf_typep(1) == tf_nullparam) { tf_error("$fibonacci cannot have a NULL argument.\n"); err = 1; } if (tf_sizep(1) > 8) { tf_error("$fibonacci input no larger than 8-bits.\n"); err = 1; } if (err) { tf_message(ERR_ERROR, "", "", ""); } return(0); }
void warn_call(int data, int reason) { char *ptr_mipname; int i; 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("$warn requires at least two arguments, warn-disable-tag, and format-string"); tf_dofinish(); return; } /* First argument to $warn() must be a string */ if (tf_typep(ARG1) != tf_string) { tf_error("First argument to $warn must be a value"); tf_dofinish(); } /* Second argument to $warn() must be a string */ if (tf_typep(ARG2) != tf_string) { tf_error("Second argument to $warn must be a formating string"); tf_dofinish(); } for (i = 0; i < diswarn_num; i++) { if (strcmp (tf_getcstringp(ARG1), diswarn_arr[i]) == 0) return; } io_printf ("%05d.%03d.%03d.%03d: WARN: %s:%s\n", ms,us,ns,ps, ptr_mipname, format(ptr_mipname)); return; }
int util_get_plus_args_str() { /* Example use: invocation script (bosox is passed in as first argument) ----------------- set basename = $1 verilog mymodule.v +tst_file_name${basename}.tst +log_file_name${basename}.log +err_file_name${basename}.err +result_file_name${basename}.result mymodule.v ---------- reg [32*8:1] tst_file_name; // plus argument string value reg [32*8:1] err_file_name; // plus argument string value reg [32*8:1] log_file_name; // plus argument string value reg [32*8:1] result_file_name; // plus argument string value integer plus_arg_ok; // 0 if ok, 1 if no plus argument value initial begin // get strings from plus argument values plus_arg_ok = $util_get_plus_args_str("tst_file_name", tst_file_name); plus_arg_ok = $util_get_plus_args_str("err_file_name", err_file_name); plus_arg_ok = $util_get_plus_args_str("log_file_name", log_file_name); plus_arg_ok = $util_get_plus_args_str("result_file_name",result_file_name); $display("tst_file_name is %s", tst_file_name); $display("err_file_name is %s", err_file_name); $display("log_file_name is %s", log_file_name); $display("result_file_name is %s", result_file_name); end */ /* Input is string Returning value is string. */ handle wrk_out; char *strArgIn; int sizeOut,sizeS_in; int numArgs; int cnt,size; char *buffer, *bufferout; s_setval_value value_out; s_setval_delay delay_out; delay_out.model = accNoDelay; delay_out.time.type = accRealTime; delay_out.time.real = 0.0; value_out.format = accHexStrVal; acc_initialize(); numArgs = tf_nump(); if(numArgs !=2) { tf_error("$get_plus_arg_string must have two arguments"); tf_putp(0,VERILOG_ERROR); return(VERILOG_ERROR); } /* Fetch the input register and size */ wrk_out = acc_handle_tfarg(2); sizeOut = (acc_fetch_size(wrk_out)/8); /* Get the string value */ strArgIn = mc_scan_plusargs(tf_getcstringp(1)); if (strArgIn == NULL) { if (DEBUG_PLUS_ARGS) io_printf("get_plus_args_str(): Matching string is not found: %s.\n", tf_getcstringp(1)); tf_putp(0,VERILOG_ERROR); return(VERILOG_ERROR); } if (strArgIn) { if (DEBUG_PLUS_ARGS) io_printf("get_plus_args_str(): Got string value: %s\n",strArgIn); } else { io_printf("get_plus_args_str(): Bad input string value.\n"); tf_putp(0,VERILOG_ERROR); return(VERILOG_ERROR); } /* Build new string */ sizeS_in = strlen(strArgIn); bufferout = (char *) malloc(sizeS_in + 1); sprintf(bufferout, "%s",strArgIn); if (sizeOut < sizeS_in) { tf_error("get_plus_args_str(): Register %s is not large enough.\n", acc_fetch_fullname(wrk_out)); tf_putp(0,VERILOG_ERROR); return(VERILOG_ERROR); } size = sizeS_in*2; buffer = (char *) malloc(size + 1); for (cnt =0; cnt < size; cnt +=2){ if (cnt < size){ /* Convert string into HEX code */ sprintf(&buffer[cnt],"%x",bufferout[cnt/2]); } } /* Null out the rest of the register else { buffer[cnt] = '\0'; buffer[cnt +1] = '\0'; } */ /* assign buffer to the verilog register */ value_out.value.str = buffer; acc_set_value(wrk_out, &value_out, &delay_out); tf_putp(0,VERILOG_OK); acc_close(); free(buffer); free(bufferout); return(VERILOG_OK); }
/************************************************* lxt2_recordvars - add objects to be recorded ************************************************/ int lxt2_recordvars( int data, int reason ) { int update = 0; int objects = 0; int i; acc_initialize(); switch( reason ) { case reason_calltf: break; case reason_checktf: goto DONE; case reason_finish: if( lxt.inited ) { lxt2_close(); } goto DONE; case reason_rosynch: update = (lxt.updateList != NULL); while( lxt.updateList ) { info_p info; info = lxt.updateList; lxt2_dump( info, 0 ); lxt.updateList = info->updateNext; info->updateNext = 0; } if( update ) { lxt2_timemarkerp1(); } while( lxt.eventList ) { info_p info; info = lxt.eventList; lxt2_dump( info, 1 ); lxt.eventList = info->updateNext; info->updateNext = 0; } lxt2_nexttimemarker(); goto DONE; default: goto DONE; } ginstance = tf_getinstance(); /* * parse options first */ for( i = 1; i <= tf_nump(); ++i ) { handle object; if( tf_typep(i) == tf_nullparam ) { continue; } if( tf_typep(i) == tf_string ) { char* str = acc_fetch_tfarg_str(i); lxt2_option( str ); continue; } } /* * on first call, initialize structure */ if( !lxt.inited ) { lxt2_init(); } for( i = 1; i <= tf_nump(); ++i ) { handle object; if( tf_typep(i) == tf_nullparam ) { continue; } if( tf_typep(i) == tf_string ) { continue; } object = acc_handle_tfarg(i); if( !object ) { tf_error( "cannot find object" ); tf_dofinish(); goto DONE; } lxt2_add( object, lxt.depth ); objects++; } if( objects == 0 ) { #if DEBUG io_printf( "lxt2_recordvars: defaultpath=%s\n", acc_fetch_fullname(acc_handle_parent(acc_handle_tfinst())), lxt.depth ); #endif lxt2_add( acc_handle_parent(acc_handle_tfinst()), lxt.depth ); } lxt2_dump( lxt.objectList, 1 ); DONE: acc_close(); return 0; }
/* * format function */ char *format(char *mipname) { int num_args, cur_arg, len, i, j; char *fmt_str, *ptr, c; num_args = tf_nump(); cur_arg = 3; len = sprintf (format_buffer, " "); fmt_str = tf_getcstringp(ARG2); ptr = format_buffer + len; while (1) { c = *fmt_str++; if (c == 0) break; if (c == '%') { c = *fmt_str++; switch (c) { case 'b': len = sprintf (ptr, "%s", tf_strgetp(cur_arg, 'b')); ptr = ptr + len; cur_arg++; break; case 'o': len = sprintf (ptr, "%s", tf_strgetp(cur_arg, 'o')); ptr = ptr + len; cur_arg++; break; case 'd': len = sprintf (ptr, "%s", tf_strgetp(cur_arg, 'd')); ptr = ptr + len; cur_arg++; break; case 'h': len = sprintf (ptr, "%s", tf_strgetp(cur_arg, 'h')); ptr = ptr + len; cur_arg++; break; case 'e': len = sprintf (ptr, "%e", tf_getrealp(cur_arg)); ptr = ptr + len; cur_arg++; break; case 'f': len = sprintf (ptr, "%e", tf_getrealp(cur_arg)); ptr = ptr + len; cur_arg++; break; case 't': len = sprintf (ptr, "%d", tf_gettime()); ptr = ptr + len; break; case 's': len = sprintf (ptr, "%s", tf_strgetp(cur_arg, 'e')); ptr = ptr + len; cur_arg++; break; case 'm': len = sprintf (ptr, "%s", mipname); ptr = ptr + len; break; case '%': *ptr++ = '%'; break; } } else { *ptr++ = c; } } *ptr++ = '\0'; return format_buffer; }