diff --git a/vpi/sys_lxt.c b/vpi/sys_lxt.c index 91fe77d92..2ceaa383e 100644 --- a/vpi/sys_lxt.c +++ b/vpi/sys_lxt.c @@ -144,6 +144,7 @@ static char *create_full_name(const char *name) } +static char *dump_path = 0; static struct lt_trace *dump_file = 0; struct vcd_info { @@ -323,10 +324,8 @@ inline static int install_dumpvars_callback(void) return 0; if (dumpvars_status == 2) { - vpi_mcd_printf(1, "LXT warning:" - " $dumpvars ignored," - " previously called at simtime %lu\n", - dumpvars_time); + vpi_mcd_printf(1, "LXT warning:" " $dumpvars ignored, previously" + " called at simtime %lu\n", dumpvars_time); return 1; } @@ -353,24 +352,21 @@ static PLI_INT32 sys_dumpoff_calltf(PLI_BYTE8*name) s_vpi_time now; PLI_UINT64 now64; - if (dump_is_off) - return 0; + if (dump_is_off) return 0; dump_is_off = 1; - if (dump_file == 0) - return 0; - - if (dump_header_pending()) - return 0; + if (dump_file == 0) return 0; + if (dump_header_pending()) return 0; now.type = vpiSimTime; vpi_get_time(0, &now); now64 = timerec_to_time64(&now); - if (now64 > vcd_cur_time) + if (now64 > vcd_cur_time) { lt_set_time64(dump_file, now64); - vcd_cur_time = now64; + vcd_cur_time = now64; + } lt_set_dumpoff(dump_file); vcd_checkpoint_x(); @@ -383,24 +379,21 @@ static PLI_INT32 sys_dumpon_calltf(PLI_BYTE8*name) s_vpi_time now; PLI_UINT64 now64; - if (!dump_is_off) - return 0; + if (!dump_is_off) return 0; dump_is_off = 0; - if (dump_file == 0) - return 0; - - if (dump_header_pending()) - return 0; + if (dump_file == 0) return 0; + if (dump_header_pending()) return 0; now.type = vpiSimTime; vpi_get_time(0, &now); now64 = timerec_to_time64(&now); - if (now64 > vcd_cur_time) + if (now64 > vcd_cur_time) { lt_set_time64(dump_file, now64); - vcd_cur_time = now64; + vcd_cur_time = now64; + } lt_set_dumpon(dump_file); vcd_checkpoint(); @@ -413,19 +406,18 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name) s_vpi_time now; PLI_UINT64 now64; - if (dump_file == 0) - return 0; - - if (dump_header_pending()) - return 0; + if (dump_is_off) return 0; + if (dump_file == 0) return 0; + if (dump_header_pending()) return 0; now.type = vpiSimTime; vpi_get_time(0, &now); now64 = timerec_to_time64(&now); - if (now64> vcd_cur_time) + if (now64> vcd_cur_time) { lt_set_time64(dump_file, now64); - vcd_cur_time = now64; + vcd_cur_time = now64; + } vcd_checkpoint(); @@ -434,25 +426,26 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name) static void *close_dumpfile(void) { -lt_close(dump_file); -return(dump_file = NULL); + lt_close(dump_file); + return (dump_file = NULL); } -static void open_dumpfile(const char*path) +static void open_dumpfile(void) { - dump_file = lt_init(path); + if (dump_path == 0) dump_path = strdup("dump.lxt"); + + dump_file = lt_init(dump_path); if (dump_file == 0) { - vpi_mcd_printf(1, - "LXT Error: Unable to open %s for output.\n", - path); + vpi_mcd_printf(1, "LXT Error: Unable to open %s for output.\n", + dump_path); + vpi_control(vpiFinish, 1); return; } else { int prec = vpi_get(vpiTimePrecision, 0); - vpi_mcd_printf(1, - "LXT info: dumpfile %s opened for output.\n", - path); + vpi_mcd_printf(1, "LXT info: dumpfile %s opened for output.\n", + dump_path); assert(prec >= -15); lt_set_timescale(dump_file, prec); @@ -466,42 +459,33 @@ static void open_dumpfile(const char*path) static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name) { + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + s_vpi_value value; + char*path; - vpiHandle sys = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv = vpi_iterate(vpiArgument, sys); - vpiHandle item; - - if (argv && (item = vpi_scan(argv))) { - s_vpi_value value; - - if (vpi_get(vpiType, item) != vpiConstant - || vpi_get(vpiConstType, item) != vpiStringConst) { - vpi_mcd_printf(1, - "LXT Error:" - " %s parameter must be a string constant\n", - name); - return 0; - } - - value.format = vpiStringVal; - vpi_get_value(item, &value); - path = strdup(value.value.str); - - vpi_free_object(argv); - - } else { - path = strdup("dump.lxt"); + /* $dumpfile must be called before $dumpvars starts! */ + if (dumpvars_status != 0) { + vpi_mcd_printf(1, "LXT warning: %s called after $dumpvars started" + ",\n using existing file (%s).\n", + name, dump_path); + return 0; } - if (dump_file) - close_dumpfile(); + assert(argv); + value.format = vpiStringVal; + vpi_get_value(vpi_scan(argv), &value); + path = strdup(value.value.str); - assert(dump_file == 0); - open_dumpfile(path); - - free(path); + if (dump_path) { + vpi_mcd_printf(1, "LXT warning: Overriding dump file %s with" + " %s\n", dump_path, path); + free(dump_path); + } + dump_path = path; + vpi_free_object(argv); return 0; } @@ -513,40 +497,6 @@ static PLI_INT32 sys_dumpflush_calltf(PLI_BYTE8*name) return 0; } -static PLI_INT32 sys_dumplimit_compiletf(PLI_BYTE8 *name) -{ - vpiHandle callh = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv = vpi_iterate(vpiArgument, callh); - vpiHandle limit; - - /* Check that there is a argument and get it. */ - if (argv == 0) { - vpi_printf("ERROR: %s requires an argument.\n", name); - vpi_control(vpiFinish, 1); - return 0; - } - limit = vpi_scan(argv); - - /* Check that we are not given a string. */ - switch (vpi_get(vpiType, limit)) { - case vpiConstant: - case vpiParameter: - if (vpi_get(vpiConstType, limit) == vpiStringConst) { - vpi_printf("ERROR: %s's argument must be a number.\n", name); - } - } - - /* Check that there is only a single argument. */ - limit = vpi_scan(argv); - if (limit != 0) { - vpi_printf("ERROR: %s takes a single argument.\n", name); - vpi_control(vpiFinish, 1); - return 0; - } - - return 0; -} - static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); @@ -604,8 +554,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) case vpiTimeVar: case vpiReg: type = "reg"; } - if (skip) - break; + if (skip) break; name = vpi_get_str(vpiName, item); nexus_id = vpi_get(_vpiNexusId, item); @@ -620,8 +569,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) ident = strdup_sh(&name_heap, tmp); free(tmp); - if (nexus_id) - set_nexus_ident(nexus_id, ident); + if (nexus_id) set_nexus_ident(nexus_id, ident); info = malloc(sizeof(*info)); @@ -653,8 +601,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) case vpiRealVar: - if (skip) - break; + if (skip) break; name = vpi_get_str(vpiName, item); { char*tmp = create_full_name(name); @@ -706,11 +653,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) if (!nskip) vcd_names_add(&lxt_tab, fullname); else - vpi_mcd_printf(1, - "LXT warning:" - " ignoring signals" - " in previously scanned scope %s\n", - fullname); + vpi_mcd_printf(1, "LXT warning: ignoring signals in" + " previously scanned scope %s\n", fullname); name = vpi_get_str(vpiName, item); @@ -729,9 +673,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) break; default: - vpi_mcd_printf(1, - "LXT Error: $lxtdumpvars: Unsupported parameter " - "type (%d)\n", vpi_get(vpiType, item)); + vpi_mcd_printf(1, "LXT warning: $dumpvars: Unsupported parameter" + " type (%d)\n", vpi_get(vpiType, item)); } } @@ -757,80 +700,54 @@ static int draw_scope(vpiHandle item) default: type = "module"; break; } - push_scope(name); /* keep in type info determination for possible future usage */ + /* keep in type info determination for possible future usage */ + push_scope(name); return depth; } static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) { - unsigned depth; + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle item; s_vpi_value value; - vpiHandle item = 0; - vpiHandle sys = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv; + unsigned depth = 0; if (dump_file == 0) { - open_dumpfile("dump.lxt"); - if (dump_file == 0) - return 0; + open_dumpfile(); + if (dump_file == 0) return 0; } - if (install_dumpvars_callback()) { - return 0; + if (install_dumpvars_callback()) return 0; + + /* Get the depth if it exists. */ + if (argv) { + value.format = vpiIntVal; + vpi_get_value(vpi_scan(argv), &value); + depth = value.value.integer; + } + if (!depth) depth = 10000; + + /* This dumps all the modules in the design if none are given. */ + if (!argv || !(item = vpi_scan(argv))) { + argv = vpi_iterate(vpiModule, 0x0); + assert(argv); // There must be at least one top level module. + item = vpi_scan(argv); } - argv = vpi_iterate(vpiArgument, sys); - - depth = 0; - if (argv && (item = vpi_scan(argv))) - switch (vpi_get(vpiType, item)) { - case vpiConstant: - case vpiNet: - case vpiIntegerVar: - case vpiReg: - case vpiMemoryWord: - value.format = vpiIntVal; - vpi_get_value(item, &value); - depth = value.value.integer; - break; - } - - if (!depth) - depth = 10000; - - if (!argv) { - // $dumpvars; - // search for the toplevel module - vpiHandle parent = vpi_handle(vpiScope, sys); - while (parent) { - item = parent; - parent = vpi_handle(vpiScope, item); - } - - } else if (!item || !(item = vpi_scan(argv))) { - // $dumpvars(level); - // $dumpvars(); - // dump the current scope - item = vpi_handle(vpiScope, sys); - argv = 0x0; - } - - for ( ; item; item = argv ? vpi_scan(argv) : 0x0) { + for ( ; item; item = vpi_scan(argv)) { int dep = draw_scope(item); vcd_names_sort(&lxt_tab); scan_item(depth, item, 0); - while (dep--) { - pop_scope(); - } + while (dep--) pop_scope(); } /* Most effective compression. */ - if (lxm_optimum_mode == LXM_SPACE) - lt_set_no_interlace(dump_file); + if (lxm_optimum_mode == LXM_SPACE) lt_set_no_interlace(dump_file); return 0; } @@ -856,34 +773,20 @@ void sys_lxt_register() } } + /* All the compiletf routines are located in vcd_priv.c. */ + tf_data.type = vpiSysTask; tf_data.tfname = "$dumpall"; tf_data.calltf = sys_dumpall_calltf; - tf_data.compiletf = 0; + tf_data.compiletf = sys_dumpall_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpall"; vpi_register_systf(&tf_data); - tf_data.type = vpiSysTask; - tf_data.tfname = "$dumpoff"; - tf_data.calltf = sys_dumpoff_calltf; - tf_data.compiletf = 0; - tf_data.sizetf = 0; - tf_data.user_data = "$dumpoff"; - vpi_register_systf(&tf_data); - - tf_data.type = vpiSysTask; - tf_data.tfname = "$dumpon"; - tf_data.calltf = sys_dumpon_calltf; - tf_data.compiletf = 0; - tf_data.sizetf = 0; - tf_data.user_data = "$dumpon"; - vpi_register_systf(&tf_data); - tf_data.type = vpiSysTask; tf_data.tfname = "$dumpfile"; tf_data.calltf = sys_dumpfile_calltf; - tf_data.compiletf = 0; + tf_data.compiletf = sys_dumpfile_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpfile"; vpi_register_systf(&tf_data); @@ -891,7 +794,7 @@ void sys_lxt_register() tf_data.type = vpiSysTask; tf_data.tfname = "$dumpflush"; tf_data.calltf = sys_dumpflush_calltf; - tf_data.compiletf = 0; + tf_data.compiletf = sys_dumpflush_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpflush"; vpi_register_systf(&tf_data); @@ -904,10 +807,26 @@ void sys_lxt_register() tf_data.user_data = "$dumplimit"; vpi_register_systf(&tf_data); + tf_data.type = vpiSysTask; + tf_data.tfname = "$dumpoff"; + tf_data.calltf = sys_dumpoff_calltf; + tf_data.compiletf = sys_dumpoff_compiletf; + tf_data.sizetf = 0; + tf_data.user_data = "$dumpoff"; + vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.tfname = "$dumpon"; + tf_data.calltf = sys_dumpon_calltf; + tf_data.compiletf = sys_dumpon_compiletf; + tf_data.sizetf = 0; + tf_data.user_data = "$dumpon"; + vpi_register_systf(&tf_data); + tf_data.type = vpiSysTask; tf_data.tfname = "$dumpvars"; tf_data.calltf = sys_dumpvars_calltf; - tf_data.compiletf = sys_vcd_dumpvars_compiletf; + tf_data.compiletf = sys_dumpvars_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpvars"; vpi_register_systf(&tf_data); diff --git a/vpi/sys_lxt2.c b/vpi/sys_lxt2.c index 75e08a2e8..bdaebc885 100644 --- a/vpi/sys_lxt2.c +++ b/vpi/sys_lxt2.c @@ -145,6 +145,7 @@ static char *create_full_name(const char *name) } +static char *dump_path; static struct lxt2_wr_trace *dump_file = 0; struct vcd_info { @@ -256,10 +257,10 @@ static PLI_INT32 variable_cb_1(p_cb_data cause) struct t_cb_data cb; struct vcd_info*info = (struct vcd_info*)cause->user_data; - if (dump_is_full) return 0; - if (dump_is_off) return 0; + if (dump_is_full) return 0; + if (dump_is_off) return 0; if (dump_header_pending()) return 0; - if (info->scheduled) return 0; + if (info->scheduled) return 0; if ((dump_limit > 0) && (ftell(dump_file->handle) > dump_limit)) { dump_is_full = 1; @@ -284,8 +285,7 @@ static PLI_INT32 variable_cb_1(p_cb_data cause) static PLI_INT32 dumpvars_cb(p_cb_data cause) { - if (dumpvars_status != 1) - return 0; + if (dumpvars_status != 1) return 0; dumpvars_status = 2; @@ -302,8 +302,7 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause) static PLI_INT32 finish_cb(p_cb_data cause) { - if (finish_status != 0) - return 0; + if (finish_status != 0) return 0; finish_status = 1; @@ -320,14 +319,11 @@ inline static int install_dumpvars_callback(void) struct t_cb_data cb; static struct t_vpi_time time; - if (dumpvars_status == 1) - return 0; + if (dumpvars_status == 1) return 0; if (dumpvars_status == 2) { - vpi_mcd_printf(1, "LXT2 warning:" - " $dumpvars ignored," - " previously called at simtime %lu\n", - dumpvars_time); + vpi_mcd_printf(1, "LXT2 warning: $dumpvars ignored, previously" + " called at simtime %lu\n", dumpvars_time); return 1; } @@ -354,23 +350,21 @@ static PLI_INT32 sys_dumpoff_calltf(PLI_BYTE8*name) s_vpi_time now; PLI_UINT64 now64; - if (dump_is_off) - return 0; + if (dump_is_off) return 0; dump_is_off = 1; - if (dump_file == 0) - return 0; - - if (dump_header_pending()) - return 0; + if (dump_file == 0) return 0; + if (dump_header_pending()) return 0; now.type = vpiSimTime; vpi_get_time(0, &now); now64 = timerec_to_time64(&now); - if (now64 > vcd_cur_time) + + if (now64 > vcd_cur_time) { lxt2_wr_set_time(dump_file, now64); - vcd_cur_time = now.low; + vcd_cur_time = now.low; + } lxt2_wr_set_dumpoff(dump_file); vcd_checkpoint_x(); @@ -383,24 +377,21 @@ static PLI_INT32 sys_dumpon_calltf(PLI_BYTE8*name) s_vpi_time now; PLI_UINT64 now64; - if (!dump_is_off) - return 0; + if (!dump_is_off) return 0; dump_is_off = 0; - if (dump_file == 0) - return 0; - - if (dump_header_pending()) - return 0; + if (dump_file == 0) return 0; + if (dump_header_pending()) return 0; now.type = vpiSimTime; vpi_get_time(0, &now); now64 = timerec_to_time64(&now); - if (now64 > vcd_cur_time) + if (now64 > vcd_cur_time) { lxt2_wr_set_time64(dump_file, now64); - vcd_cur_time = now64; + vcd_cur_time = now64; + } lxt2_wr_set_dumpon(dump_file); vcd_checkpoint(); @@ -413,15 +404,12 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name) s_vpi_time now; PLI_UINT64 now64; - if (dump_file == 0) - return 0; - - if (dump_header_pending()) - return 0; + if (dump_is_off) return 0; + if (dump_file == 0) return 0; + if (dump_header_pending()) return 0; now.type = vpiSimTime; vpi_get_time(0, &now); - now64 = timerec_to_time64(&now); if (now64 > vcd_cur_time) @@ -440,21 +428,22 @@ static void *close_dumpfile(void) return 0; } -static void open_dumpfile(const char*path) +static void open_dumpfile(void) { - dump_file = lxt2_wr_init(path); + if (dump_path == 0) dump_path = strdup("dump.lx2"); + + dump_file = lxt2_wr_init(dump_path); if (dump_file == 0) { - vpi_mcd_printf(1, - "LXT2 Error: Unable to open %s for output.\n", - path); + vpi_mcd_printf(1, "LXT2 Error: Unable to open %s for output.\n", + dump_path); + vpi_control(vpiFinish, 1); return; } else { int prec = vpi_get(vpiTimePrecision, 0); - vpi_mcd_printf(1, - "LXT2 info: dumpfile %s opened for output.\n", - path); + vpi_mcd_printf(1, "LXT2 info: dumpfile %s opened for output.\n", + dump_path); assert(prec >= -15); lxt2_wr_set_timescale(dump_file, prec); @@ -470,42 +459,33 @@ static void open_dumpfile(const char*path) static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name) { - char*path; - vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); - vpiHandle item; + s_vpi_value value; - if (argv && (item = vpi_scan(argv))) { - s_vpi_value value; + char*path; - if (vpi_get(vpiType, item) != vpiConstant - || vpi_get(vpiConstType, item) != vpiStringConst) { - vpi_mcd_printf(1, - "LXT2 Error:" - " %s parameter must be a string constant\n", - name); - return 0; - } - - value.format = vpiStringVal; - vpi_get_value(item, &value); - path = strdup(value.value.str); - - vpi_free_object(argv); - - } else { - path = strdup("dump.lx2"); + /* $dumpfile must be called before $dumpvars starts! */ + if (dumpvars_status != 0) { + vpi_mcd_printf(1, "LXT2 warning: %s called after $dumpvars started" + ",\n using existing file (%s).\n", + name, dump_path); + return 0; } - if (dump_file) - close_dumpfile(); + assert(argv); + value.format = vpiStringVal; + vpi_get_value(vpi_scan(argv), &value); + path = strdup(value.value.str); - assert(dump_file == 0); - open_dumpfile(path); - - free(path); + if (dump_path) { + vpi_mcd_printf(1, "LXT2 warning: Overriding dump file %s with" + " %s.\n", dump_path, path); + free(dump_path); + } + dump_path = path; + vpi_free_object(argv); return 0; } @@ -519,39 +499,6 @@ static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name) static PLI_INT32 sys_dumpflush_calltf(PLI_BYTE8*name) { if (dump_file) lxt2_wr_flush(dump_file); - return 0; -} - -static PLI_INT32 sys_dumplimit_compiletf(PLI_BYTE8 *name) -{ - vpiHandle callh = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv = vpi_iterate(vpiArgument, callh); - vpiHandle limit; - - /* Check that there is a argument and get it. */ - if (argv == 0) { - vpi_printf("ERROR: %s requires an argument.\n", name); - vpi_control(vpiFinish, 1); - return 0; - } - limit = vpi_scan(argv); - - /* Check that we are not given a string. */ - switch (vpi_get(vpiType, limit)) { - case vpiConstant: - case vpiParameter: - if (vpi_get(vpiConstType, limit) == vpiStringConst) { - vpi_printf("ERROR: %s's argument must be a number.\n", name); - } - } - - /* Check that there is only a single argument. */ - limit = vpi_scan(argv); - if (limit != 0) { - vpi_printf("ERROR: %s takes a single argument.\n", name); - vpi_control(vpiFinish, 1); - return 0; - } return 0; } @@ -560,12 +507,12 @@ static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); - vpiHandle limit = vpi_scan(argv); s_vpi_value val; /* Get the value and set the dump limit. */ + assert(argv); val.format = vpiIntVal; - vpi_get_value(limit, &val); + vpi_get_value(vpi_scan(argv), &val); dump_limit = val.value.integer; vpi_free_object(argv); @@ -613,8 +560,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) case vpiTimeVar: case vpiReg: type = "reg"; } - if (skip) - break; + if (skip) break; name = vpi_get_str(vpiName, item); nexus_id = vpi_get(_vpiNexusId, item); @@ -629,8 +575,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) ident = strdup_sh(&name_heap, tmp); free(tmp); - if (nexus_id) - set_nexus_ident(nexus_id, ident); + if (nexus_id) set_nexus_ident(nexus_id, ident); info = malloc(sizeof(*info)); @@ -666,8 +611,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) case vpiRealVar: - if (skip) - break; + if (skip) break; name = vpi_get_str(vpiName, item); { char*tmp = create_full_name(name); @@ -722,11 +666,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) if (!nskip) vcd_names_add(&lxt_tab, fullname); else - vpi_mcd_printf(1, - "LXT2 warning:" - " ignoring signals" - " in previously scanned scope %s\n", - fullname); + vpi_mcd_printf(1, "LXT2 warning: ignoring signals in" + " previously scanned scope %s\n", fullname); name = vpi_get_str(vpiName, item); @@ -745,9 +686,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) break; default: - vpi_mcd_printf(1, - "LXT2 Error: $lxtdumpvars: Unsupported parameter " - "type (%d)\n", vpi_get(vpiType, item)); + vpi_mcd_printf(1, "LXT2 warning: $dumpvars: Unsupported parameter" + " type (%d)\n", vpi_get(vpiType, item)); } } @@ -759,8 +699,7 @@ static int draw_scope(vpiHandle item) char *type; vpiHandle scope = vpi_handle(vpiScope, item); - if (!scope) - return 0; + if (!scope) return 0; depth = 1 + draw_scope(scope); name = vpi_get_str(vpiName, scope); @@ -773,75 +712,50 @@ static int draw_scope(vpiHandle item) default: type = "module"; break; } - push_scope(name); /* keep in type info determination for possible future usage */ + /* keep in type info determination for possible future usage */ + push_scope(name); return depth; } static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) { - unsigned depth; + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle item; s_vpi_value value; - vpiHandle item = 0; - vpiHandle sys = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv; + unsigned depth = 0; if (dump_file == 0) { - open_dumpfile("dump.lx2"); - if (dump_file == 0) - return 0; + open_dumpfile(); + if (dump_file == 0) return 0; } - if (install_dumpvars_callback()) { - return 0; + if (install_dumpvars_callback()) return 0; + + /* Get the depth if it exists. */ + if (argv) { + value.format = vpiIntVal; + vpi_get_value(vpi_scan(argv), &value); + depth = value.value.integer; + } + if (!depth) depth = 10000; + + /* This dumps all the modules in the design if none are given. */ + if (!argv || !(item = vpi_scan(argv))) { + argv = vpi_iterate(vpiModule, 0x0); + assert(argv); // There must be at least one top level module. + item = vpi_scan(argv); } - argv = vpi_iterate(vpiArgument, sys); - - depth = 0; - if (argv && (item = vpi_scan(argv))) - switch (vpi_get(vpiType, item)) { - case vpiConstant: - case vpiNet: - case vpiIntegerVar: - case vpiReg: - case vpiMemoryWord: - value.format = vpiIntVal; - vpi_get_value(item, &value); - depth = value.value.integer; - break; - } - - if (!depth) - depth = 10000; - - if (!argv) { - // $dumpvars; - // search for the toplevel module - vpiHandle parent = vpi_handle(vpiScope, sys); - while (parent) { - item = parent; - parent = vpi_handle(vpiScope, item); - } - - } else if (!item || !(item = vpi_scan(argv))) { - // $dumpvars(level); - // $dumpvars(); - // dump the current scope - item = vpi_handle(vpiScope, sys); - argv = 0x0; - } - - for ( ; item; item = argv ? vpi_scan(argv) : 0x0) { + for ( ; item; item = vpi_scan(argv)) { int dep = draw_scope(item); vcd_names_sort(&lxt_tab); scan_item(depth, item, 0); - while (dep--) { - pop_scope(); - } + while (dep--) pop_scope(); } /* Most effective compression. */ @@ -874,34 +788,20 @@ void sys_lxt2_register() } } + /* All the compiletf routines are located in vcd_priv.c. */ + tf_data.type = vpiSysTask; tf_data.tfname = "$dumpall"; tf_data.calltf = sys_dumpall_calltf; - tf_data.compiletf = 0; + tf_data.compiletf = sys_dumpall_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpall"; vpi_register_systf(&tf_data); - tf_data.type = vpiSysTask; - tf_data.tfname = "$dumpoff"; - tf_data.calltf = sys_dumpoff_calltf; - tf_data.compiletf = 0; - tf_data.sizetf = 0; - tf_data.user_data = "$dumpoff"; - vpi_register_systf(&tf_data); - - tf_data.type = vpiSysTask; - tf_data.tfname = "$dumpon"; - tf_data.calltf = sys_dumpon_calltf; - tf_data.compiletf = 0; - tf_data.sizetf = 0; - tf_data.user_data = "$dumpon"; - vpi_register_systf(&tf_data); - tf_data.type = vpiSysTask; tf_data.tfname = "$dumpfile"; tf_data.calltf = sys_dumpfile_calltf; - tf_data.compiletf = 0; + tf_data.compiletf = sys_dumpfile_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpfile"; vpi_register_systf(&tf_data); @@ -909,7 +809,7 @@ void sys_lxt2_register() tf_data.type = vpiSysTask; tf_data.tfname = "$dumpflush"; tf_data.calltf = sys_dumpflush_calltf; - tf_data.compiletf = 0; + tf_data.compiletf = sys_dumpflush_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpflush"; vpi_register_systf(&tf_data); @@ -922,10 +822,26 @@ void sys_lxt2_register() tf_data.user_data = "$dumplimit"; vpi_register_systf(&tf_data); + tf_data.type = vpiSysTask; + tf_data.tfname = "$dumpoff"; + tf_data.calltf = sys_dumpoff_calltf; + tf_data.compiletf = sys_dumpoff_compiletf; + tf_data.sizetf = 0; + tf_data.user_data = "$dumpoff"; + vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.tfname = "$dumpon"; + tf_data.calltf = sys_dumpon_calltf; + tf_data.compiletf = sys_dumpon_compiletf; + tf_data.sizetf = 0; + tf_data.user_data = "$dumpon"; + vpi_register_systf(&tf_data); + tf_data.type = vpiSysTask; tf_data.tfname = "$dumpvars"; tf_data.calltf = sys_dumpvars_calltf; - tf_data.compiletf = sys_vcd_dumpvars_compiletf; + tf_data.compiletf = sys_dumpvars_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpvars"; vpi_register_systf(&tf_data); diff --git a/vpi/sys_priv.h b/vpi/sys_priv.h index 9dba6454d..41d3bde52 100644 --- a/vpi/sys_priv.h +++ b/vpi/sys_priv.h @@ -25,12 +25,6 @@ # include "vpi_config.h" # include "vpi_user.h" -/* - * This function is used by sys_vcd and sys_lxt as the dumpvars - * compiletf function. - */ -extern PLI_INT32 sys_vcd_dumpvars_compiletf(PLI_BYTE8*name); - /* * Context structure for PRNG in mt19937int.c */ @@ -56,32 +50,4 @@ struct timeformat_info_s { extern struct timeformat_info_s timeformat_info; - -/* - * $Log: sys_priv.h,v $ - * Revision 1.8 2007/03/14 04:05:51 steve - * VPI tasks take PLI_BYTE* by the standard. - * - * Revision 1.7 2006/10/30 22:45:37 steve - * Updates for Cygwin portability (pr1585922) - * - * Revision 1.6 2006/08/12 03:38:12 steve - * scanf support for real values. - * - * Revision 1.5 2004/01/21 01:22:53 steve - * Give the vip directory its own configure and vpi_config.h - * - * Revision 1.4 2003/10/30 03:43:20 steve - * Rearrange fileio functions, and add ungetc. - * - * Revision 1.3 2003/09/30 01:33:39 steve - * dumpers must be aware of 64bit time. - * - * Revision 1.2 2003/05/14 04:18:16 steve - * Use seed to store random number context. - * - * Revision 1.1 2002/08/15 02:12:20 steve - * add dumpvars_compiletf to check first argument. - * - */ #endif diff --git a/vpi/sys_table.c b/vpi/sys_table.c index be260e8bc..d9edbe213 100644 --- a/vpi/sys_table.c +++ b/vpi/sys_table.c @@ -124,6 +124,9 @@ static void sys_lxt_or_vcd_register() } else if (strcmp(vlog_info.argv[idx],"-vcd-none") == 0) { dumper = "none"; + } else if (strcmp(vlog_info.argv[idx],"-none") == 0) { + dumper = "none"; + } } @@ -158,8 +161,8 @@ static void sys_lxt_or_vcd_register() sys_vcdoff_register(); else { - fprintf(stderr, "system.vpi: Unknown dumper format: %s\n", - dumper); + vpi_mcd_printf(1, "system.vpi: Unknown dumper format: %s," + " using VCD instead.\n", dumper); sys_vcd_register(); } } diff --git a/vpi/sys_vcd.c b/vpi/sys_vcd.c index edde342eb..a4f4d1e5d 100644 --- a/vpi/sys_vcd.c +++ b/vpi/sys_vcd.c @@ -92,18 +92,13 @@ static char *truncate_bitvec(char *s) char l, r; r=*s; - if(r=='1') - return s; - else - s += 1; + if(r=='1') return s; + else s += 1; for(;;s++) { l=r; r=*s; if(!r) return (s-1); - - if(l!=r) - return(((l=='0')&&(r=='1'))?s:s-1); - + if(l!=r) return(((l=='0')&&(r=='1'))?s:s-1); } } @@ -123,8 +118,7 @@ static void show_this_item(struct vcd_info*info) } else { value.format = vpiBinStrVal; vpi_get_value(info->item, &value); - fprintf(dump_file, "b%s %s\n", - truncate_bitvec(value.value.str), + fprintf(dump_file, "b%s %s\n", truncate_bitvec(value.value.str), info->ident); } } @@ -203,10 +197,10 @@ static PLI_INT32 variable_cb_1(p_cb_data cause) struct t_cb_data cb; struct vcd_info*info = (struct vcd_info*)cause->user_data; - if (dump_is_full) return 0; - if (dump_is_off) return 0; + if (dump_is_full) return 0; + if (dump_is_off) return 0; if (dump_header_pending()) return 0; - if (info->scheduled) return 0; + if (info->scheduled) return 0; if ((dump_limit > 0) && (ftell(dump_file) > dump_limit)) { dump_is_full = 1; @@ -233,8 +227,7 @@ static PLI_INT32 variable_cb_1(p_cb_data cause) static PLI_INT32 dumpvars_cb(p_cb_data cause) { - if (dumpvars_status != 1) - return 0; + if (dumpvars_status != 1) return 0; dumpvars_status = 2; @@ -255,8 +248,7 @@ static PLI_INT32 dumpvars_cb(p_cb_data cause) static PLI_INT32 finish_cb(p_cb_data cause) { - if (finish_status != 0) - return 0; + if (finish_status != 0) return 0; finish_status = 1; @@ -274,13 +266,11 @@ inline static int install_dumpvars_callback(void) struct t_cb_data cb; static struct t_vpi_time time; - if (dumpvars_status == 1) - return 0; + if (dumpvars_status == 1) return 0; if (dumpvars_status == 2) { - vpi_mcd_printf(1, "VCD warning:" - " $dumpvars ignored," - " previously called at simtime %" PLI_UINT64_FMT "\n", + vpi_mcd_printf(1, "VCD warning: $dumpvars ignored, previously" + " called at simtime %" PLI_UINT64_FMT "\n", dumpvars_time); return 1; } @@ -308,24 +298,21 @@ static PLI_INT32 sys_dumpoff_calltf(PLI_BYTE8*name) s_vpi_time now; PLI_UINT64 now64; - if (dump_is_off) - return 0; + if (dump_is_off) return 0; dump_is_off = 1; - if (dump_file == 0) - return 0; - - if (dump_header_pending()) - return 0; + if (dump_file == 0) return 0; + if (dump_header_pending()) return 0; now.type = vpiSimTime; vpi_get_time(0, &now); now64 = timerec_to_time64(&now); - if (now64 > vcd_cur_time) + if (now64 > vcd_cur_time) { fprintf(dump_file, "#%" PLI_UINT64_FMT "\n", now64); - vcd_cur_time = now64; + vcd_cur_time = now64; + } fprintf(dump_file, "$dumpoff\n"); vcd_checkpoint_x(); @@ -339,24 +326,21 @@ static PLI_INT32 sys_dumpon_calltf(PLI_BYTE8*name) s_vpi_time now; PLI_UINT64 now64; - if (!dump_is_off) - return 0; + if (!dump_is_off) return 0; dump_is_off = 0; - if (dump_file == 0) - return 0; - - if (dump_header_pending()) - return 0; + if (dump_file == 0) return 0; + if (dump_header_pending()) return 0; now.type = vpiSimTime; vpi_get_time(0, &now); now64 = timerec_to_time64(&now); - if (now64 > vcd_cur_time) + if (now64 > vcd_cur_time) { fprintf(dump_file, "#%" PLI_UINT64_FMT "\n", now64); - vcd_cur_time = now64; + vcd_cur_time = now64; + } fprintf(dump_file, "$dumpon\n"); vcd_checkpoint(); @@ -370,19 +354,18 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name) s_vpi_time now; PLI_UINT64 now64; - if (dump_file == 0) - return 0; - - if (dump_header_pending()) - return 0; + if (dump_is_off) return 0; + if (dump_file == 0) return 0; + if (dump_header_pending()) return 0; now.type = vpiSimTime; vpi_get_time(0, &now); now64 = timerec_to_time64(&now); - if (now64 > vcd_cur_time) + if (now64 > vcd_cur_time) { fprintf(dump_file, "#%" PLI_UINT64_FMT "\n", now64); - vcd_cur_time = now.low; + vcd_cur_time = now64; + } fprintf(dump_file, "$dumpall\n"); vcd_checkpoint(); @@ -393,16 +376,14 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name) static void open_dumpfile(void) { - if (dump_path == 0) { - dump_path = strdup("dump.vcd"); - } + if (dump_path == 0) dump_path = strdup("dump.vcd"); dump_file = fopen(dump_path, "w"); if (dump_file == 0) { - vpi_mcd_printf(1, - "VCD Error: Unable to open %s for output.\n", + vpi_mcd_printf(1, "VCD Error: Unable to open %s for output.\n", dump_path); + vpi_control(vpiFinish, 1); return; } else { int prec = vpi_get(vpiTimePrecision, 0); @@ -410,8 +391,7 @@ static void open_dumpfile(void) unsigned udx = 0; time_t walltime; - vpi_mcd_printf(1, - "VCD info: dumpfile %s opened for output.\n", + vpi_mcd_printf(1, "VCD info: dumpfile %s opened for output.\n", dump_path); time(&walltime); @@ -438,91 +418,41 @@ static void open_dumpfile(void) } } -static PLI_INT32 sys_dumpfile_compiletf(PLI_BYTE8*name) +static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name) { - vpiHandle sys = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv = vpi_iterate(vpiArgument, sys); - vpiHandle item; + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + s_vpi_value value; char*path; - if (argv && (item = vpi_scan(argv))) { - s_vpi_value value; - - if (vpi_get(vpiType, item) != vpiConstant - || vpi_get(vpiConstType, item) != vpiStringConst) { - vpi_mcd_printf(1, - "VCD Error:" - " %s parameter must be a string constant\n", - name); - return 0; - } - - value.format = vpiStringVal; - vpi_get_value(item, &value); - path = strdup(value.value.str); - - vpi_free_object(argv); - - } else { - path = strdup("dump.vcd"); + /* $dumpfile must be called before $dumpvars starts! */ + if (dumpvars_status != 0) { + vpi_mcd_printf(1, "VCD warning: %s called after $dumpvars started" + ",\n using existing file (%s).\n", + name, dump_path); + return 0; } + assert(argv); + value.format = vpiStringVal; + vpi_get_value(vpi_scan(argv), &value); + path = strdup(value.value.str); + if (dump_path) { - vpi_mcd_printf(1, "VCD Warning:" - " Overriding dumpfile path %s with %s\n", - dump_path, path); + vpi_mcd_printf(1, "VCD warning: Overriding dump file %s with" + " %s\n", dump_path, path); free(dump_path); } - dump_path = path; - return 0; -} - -static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name) -{ + vpi_free_object(argv); return 0; } static PLI_INT32 sys_dumpflush_calltf(PLI_BYTE8*name) { - if (dump_file) - fflush(dump_file); - - return 0; -} - -static PLI_INT32 sys_dumplimit_compiletf(PLI_BYTE8 *name) -{ - vpiHandle callh = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv = vpi_iterate(vpiArgument, callh); - vpiHandle limit; - - /* Check that there is a argument and get it. */ - if (argv == 0) { - vpi_printf("ERROR: %s requires an argument.\n", name); - vpi_control(vpiFinish, 1); - return 0; - } - limit = vpi_scan(argv); - - /* Check that we are not given a string. */ - switch (vpi_get(vpiType, limit)) { - case vpiConstant: - case vpiParameter: - if (vpi_get(vpiConstType, limit) == vpiStringConst) { - vpi_printf("ERROR: %s's argument must be a number.\n", name); - } - } - - /* Check that there is only a single argument. */ - limit = vpi_scan(argv); - if (limit != 0) { - vpi_printf("ERROR: %s takes a single argument.\n", name); - vpi_control(vpiFinish, 1); - return 0; - } + if (dump_file) fflush(dump_file); return 0; } @@ -531,12 +461,12 @@ static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); - vpiHandle limit = vpi_scan(argv); s_vpi_value val; /* Get the value and set the dump limit. */ + assert(argv); val.format = vpiIntVal; - vpi_get_value(limit, &val); + vpi_get_value(vpi_scan(argv), &val); dump_limit = val.value.integer; vpi_free_object(argv); @@ -593,8 +523,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) break; } - if (skip) - break; + if (skip) break; name = vpi_get_str(vpiName, item); prefix = is_escaped_id(name) ? "\\" : ""; @@ -611,8 +540,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) ident = strdup(vcdid); gen_new_vcd_id(); - if (nexus_id) - set_nexus_ident(nexus_id, ident); + if (nexus_id) set_nexus_ident(nexus_id, ident); info = malloc(sizeof(*info)); @@ -660,8 +588,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) break; } - if (skip) - break; + if (skip) break; /* Declare the variable in the VCD file. */ name = vpi_get_str(vpiName, item); @@ -718,11 +645,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) if (!nskip) vcd_names_add(&vcd_tab, fullname); else - vpi_mcd_printf(1, - "VCD warning:" - " ignoring signals" - " in previously scanned scope %s\n", - fullname); + vpi_mcd_printf(1, "VCD warning: ignoring signals in" + " previously scanned scope %s\n", fullname); name = vpi_get_str(vpiName, item); @@ -741,8 +665,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) break; default: - vpi_mcd_printf(1, - "VCD Error: $dumpvars: Unsupported parameter " + vpi_mcd_printf(1, "VCD warning: $dumpvars: Unsupported parameter " "type (%d)\n", vpi_get(vpiType, item)); } } @@ -754,8 +677,7 @@ static int draw_scope(vpiHandle item) char *type; vpiHandle scope = vpi_handle(vpiScope, item); - if (!scope) - return 0; + if (!scope) return 0; depth = 1 + draw_scope(scope); name = vpi_get_str(vpiName, scope); @@ -773,103 +695,37 @@ static int draw_scope(vpiHandle item) return depth; } -/* - * This function is also used in sys_lxt to check the arguments of the - * lxt variant of $dumpvars. - */ -PLI_INT32 sys_vcd_dumpvars_compiletf(PLI_BYTE8*name) -{ - vpiHandle sys = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv = vpi_iterate(vpiArgument, sys); - vpiHandle tmp; - - if (argv == 0) - return 0; - - tmp = vpi_scan(argv); - assert(tmp); - - switch (vpi_get(vpiType, tmp)) { - case vpiConstant: - if (vpi_get(vpiConstType, tmp) == vpiStringConst) { - vpi_printf("ERROR: %s argument must be " - "a number constant.\n", name); - vpi_control(vpiFinish, 1); - } - break; - - case vpiNet: - case vpiReg: - case vpiIntegerVar: - case vpiMemoryWord: - break; - - default: - vpi_printf("ERROR: %s argument must be " - "a number constant.\n", name); - vpi_control(vpiFinish, 1); - break; - } - - vpi_free_object(argv); - return 0; -} - static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) { - unsigned depth; + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle item; s_vpi_value value; - vpiHandle item = 0; - vpiHandle sys = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv; + unsigned depth = 0; if (dump_file == 0) { open_dumpfile(); - if (dump_file == 0) - return 0; + if (dump_file == 0) return 0; } - if (install_dumpvars_callback()) { - return 0; + if (install_dumpvars_callback()) return 0; + + /* Get the depth if it exists. */ + if (argv) { + value.format = vpiIntVal; + vpi_get_value(vpi_scan(argv), &value); + depth = value.value.integer; + } + if (!depth) depth = 10000; + + /* This dumps all the modules in the design if none are given. */ + if (!argv || !(item = vpi_scan(argv))) { + argv = vpi_iterate(vpiModule, 0x0); + assert(argv); // There must be at least one top level module. + item = vpi_scan(argv); } - argv = vpi_iterate(vpiArgument, sys); - - depth = 0; - if (argv && (item = vpi_scan(argv))) - switch (vpi_get(vpiType, item)) { - case vpiConstant: - case vpiNet: - case vpiReg: - case vpiIntegerVar: - case vpiMemoryWord: - value.format = vpiIntVal; - vpi_get_value(item, &value); - depth = value.value.integer; - break; - } - - if (!depth) - depth = 10000; - - if (!argv) { - // $dumpvars; - // search for the toplevel module - vpiHandle parent = vpi_handle(vpiScope, sys); - while (parent) { - item = parent; - parent = vpi_handle(vpiScope, item); - } - - } else if (!item || !(item = vpi_scan(argv))) { - // $dumpvars(level); - // $dumpvars(); - // dump the current scope - item = vpi_handle(vpiScope, sys); - argv = 0x0; - } - - for ( ; item; item = argv ? vpi_scan(argv) : 0x0) { + for ( ; item; item = vpi_scan(argv)) { const char *scname; int add_var = 0; @@ -879,6 +735,7 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) * been included. */ switch (vpi_get(vpiType, item)) { case vpiIntegerVar: + /* What about MemoryWord? */ case vpiNet: case vpiRealVar: case vpiReg: @@ -898,9 +755,7 @@ static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) scan_item(depth, item, 0); - while (dep--) { - fprintf(dump_file, "$upscope $end\n"); - } + while (dep--) fprintf(dump_file, "$upscope $end\n"); /* Add this signal to the variable list so we can verify it * is not included twice. This must be done after it has @@ -918,30 +773,16 @@ void sys_vcd_register() { s_vpi_systf_data tf_data; + /* All the compiletf routines are located in vcd_priv.c. */ + tf_data.type = vpiSysTask; tf_data.tfname = "$dumpall"; tf_data.calltf = sys_dumpall_calltf; - tf_data.compiletf = 0; + tf_data.compiletf = sys_dumpall_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpall"; vpi_register_systf(&tf_data); - tf_data.type = vpiSysTask; - tf_data.tfname = "$dumpoff"; - tf_data.calltf = sys_dumpoff_calltf; - tf_data.compiletf = 0; - tf_data.sizetf = 0; - tf_data.user_data = "$dumpoff"; - vpi_register_systf(&tf_data); - - tf_data.type = vpiSysTask; - tf_data.tfname = "$dumpon"; - tf_data.calltf = sys_dumpon_calltf; - tf_data.compiletf = 0; - tf_data.sizetf = 0; - tf_data.user_data = "$dumpon"; - vpi_register_systf(&tf_data); - tf_data.type = vpiSysTask; tf_data.tfname = "$dumpfile"; tf_data.calltf = sys_dumpfile_calltf; @@ -953,7 +794,7 @@ void sys_vcd_register() tf_data.type = vpiSysTask; tf_data.tfname = "$dumpflush"; tf_data.calltf = sys_dumpflush_calltf; - tf_data.compiletf = 0; + tf_data.compiletf = sys_dumpflush_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpflush"; vpi_register_systf(&tf_data); @@ -966,10 +807,26 @@ void sys_vcd_register() tf_data.user_data = "$dumplimit"; vpi_register_systf(&tf_data); + tf_data.type = vpiSysTask; + tf_data.tfname = "$dumpoff"; + tf_data.calltf = sys_dumpoff_calltf; + tf_data.compiletf = sys_dumpoff_compiletf; + tf_data.sizetf = 0; + tf_data.user_data = "$dumpoff"; + vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.tfname = "$dumpon"; + tf_data.calltf = sys_dumpon_calltf; + tf_data.compiletf = sys_dumpon_compiletf; + tf_data.sizetf = 0; + tf_data.user_data = "$dumpon"; + vpi_register_systf(&tf_data); + tf_data.type = vpiSysTask; tf_data.tfname = "$dumpvars"; tf_data.calltf = sys_dumpvars_calltf; - tf_data.compiletf = sys_vcd_dumpvars_compiletf; + tf_data.compiletf = sys_dumpvars_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpvars"; vpi_register_systf(&tf_data); diff --git a/vpi/sys_vcdoff.c b/vpi/sys_vcdoff.c index d9600b0c9..181adb51b 100644 --- a/vpi/sys_vcdoff.c +++ b/vpi/sys_vcdoff.c @@ -23,8 +23,7 @@ # include "sys_priv.h" /* - * This file contains the implementations of the VCD related - * functions. These are stub versions + * This file contains do nothing stubs of all the VCD routines. */ # include "vpi_user.h" @@ -39,86 +38,18 @@ # include "vcd_priv.h" -static FILE*dump_file = 0; +static int dump_flag = 0; -static PLI_INT32 sys_dumpoff_calltf(PLI_BYTE8*name) +static PLI_INT32 sys_dump_calltf(PLI_BYTE8*name) { return 0; } -static PLI_INT32 sys_dumpon_calltf(PLI_BYTE8*name) -{ - return 0; -} - -static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name) -{ - return 0; -} - -static void open_dumpfile(const char*path) -{ - dump_file = fopen(path, "w"); - - if (dump_file == 0) { - vpi_mcd_printf(6, - "VCD Error: Unable to open %s for output.\n", - path); - return; - } else { - fprintf(dump_file, "VCD Dump suppressed.\n"); - } -} - -static PLI_INT32 sys_dumpfile_calltf(PLI_BYTE8*name) -{ - char*path; - - vpiHandle sys = vpi_handle(vpiSysTfCall, 0); - vpiHandle argv = vpi_iterate(vpiArgument, sys); - vpiHandle item; - - if (argv && (item = vpi_scan(argv))) { - s_vpi_value value; - - if (vpi_get(vpiType, item) != vpiConstant - || vpi_get(vpiConstType, item) != vpiStringConst) { - vpi_mcd_printf(6, - "VCD Error:" - " %s parameter must be a string constant\n", - name); - return 0; - } - - value.format = vpiStringVal; - vpi_get_value(item, &value); - path = strdup(value.value.str); - - vpi_free_object(argv); - - } else { - path = strdup("dumpfile.vcd"); - } - - if (dump_file) { - fclose(dump_file); - dump_file = 0; - } - - assert(dump_file == 0); - open_dumpfile(path); - - free(path); - - return 0; -} - static PLI_INT32 sys_dumpvars_calltf(PLI_BYTE8*name) { - if (dump_file == 0) { - open_dumpfile("dumpfile.vcd"); - if (dump_file == 0) - return 0; + if (dump_flag == 0) { + vpi_mcd_printf(1, "VCD info: dumping is suppressed.\n"); + dump_flag = 1; } return 0; @@ -128,63 +59,62 @@ void sys_vcdoff_register() { s_vpi_systf_data tf_data; + /* All the compiletf routines are located in vcd_priv.c. */ + tf_data.type = vpiSysTask; tf_data.tfname = "$dumpall"; - tf_data.calltf = sys_dumpall_calltf; - tf_data.compiletf = 0; + tf_data.calltf = sys_dump_calltf; + tf_data.compiletf = sys_dumpall_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpall"; vpi_register_systf(&tf_data); + tf_data.type = vpiSysTask; + tf_data.tfname = "$dumpfile"; + tf_data.calltf = sys_dump_calltf; + tf_data.compiletf = sys_dumpfile_compiletf; + tf_data.sizetf = 0; + tf_data.user_data = "$dumpfile"; + vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.tfname = "$dumpflush"; + tf_data.calltf = sys_dump_calltf; + tf_data.compiletf = sys_dumpflush_compiletf; + tf_data.sizetf = 0; + tf_data.user_data = "$dumpflush"; + vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.tfname = "$dumplimit"; + tf_data.calltf = sys_dump_calltf; + tf_data.compiletf = sys_dumplimit_compiletf; + tf_data.sizetf = 0; + tf_data.user_data = "$dumplimit"; + vpi_register_systf(&tf_data); + tf_data.type = vpiSysTask; tf_data.tfname = "$dumpoff"; - tf_data.calltf = sys_dumpoff_calltf; - tf_data.compiletf = 0; + tf_data.calltf = sys_dump_calltf; + tf_data.compiletf = sys_dumpoff_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpoff"; vpi_register_systf(&tf_data); tf_data.type = vpiSysTask; tf_data.tfname = "$dumpon"; - tf_data.calltf = sys_dumpon_calltf; - tf_data.compiletf = 0; + tf_data.calltf = sys_dump_calltf; + tf_data.compiletf = sys_dumpon_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpon"; vpi_register_systf(&tf_data); - tf_data.type = vpiSysTask; - tf_data.tfname = "$dumpfile"; - tf_data.calltf = sys_dumpfile_calltf; - tf_data.compiletf = 0; - tf_data.sizetf = 0; - tf_data.user_data = "$dumpfile"; - vpi_register_systf(&tf_data); - tf_data.type = vpiSysTask; tf_data.tfname = "$dumpvars"; tf_data.calltf = sys_dumpvars_calltf; - tf_data.compiletf = sys_vcd_dumpvars_compiletf; + tf_data.compiletf = sys_dumpvars_compiletf; tf_data.sizetf = 0; tf_data.user_data = "$dumpvars"; vpi_register_systf(&tf_data); } -/* - * $Log: sys_vcdoff.c,v $ - * Revision 1.5 2007/03/14 04:05:52 steve - * VPI tasks take PLI_BYTE* by the standard. - * - * Revision 1.4 2006/10/30 22:45:38 steve - * Updates for Cygwin portability (pr1585922) - * - * Revision 1.3 2004/10/04 01:10:58 steve - * Clean up spurious trailing white space. - * - * Revision 1.2 2004/01/21 01:22:53 steve - * Give the vip directory its own configure and vpi_config.h - * - * Revision 1.1 2003/03/06 20:04:42 steve - * Add means to suppress wveform output - * - */ - diff --git a/vpi/vcd_priv.c b/vpi/vcd_priv.c index 1f9f23112..c93a9a575 100644 --- a/vpi/vcd_priv.c +++ b/vpi/vcd_priv.c @@ -188,3 +188,205 @@ void set_nexus_ident(int nex, const char *id) vcd_ids[ihash(nex)] = bucket; } +/* This is used by the compiletf routines to check if an argument + * is numeric. */ +static void check_numeric_arg(vpiHandle arg, char *msg, PLI_BYTE8 *name) +{ + assert(arg); + + switch (vpi_get(vpiType, arg)) { + case vpiConstant: + case vpiParameter: + /* String constants are invalid numeric values. */ + if (vpi_get(vpiConstType, arg) == vpiStringConst) { + vpi_mcd_printf(1, msg, name); + vpi_control(vpiFinish, 1); + } + break; + + /* These have valid numeric values. */ + case vpiIntegerVar: + case vpiMemoryWord: + case vpiNet: + case vpiRealVar: + case vpiReg: + case vpiTimeVar: + break; + + default: + /* Anything else is not a numeric value. */ + vpi_mcd_printf(1, msg, name); + vpi_control(vpiFinish, 1); + break; + } +} + +/* This is used by the compiletf routines to check if an argument + * is a string value. */ +static void check_string_arg(vpiHandle arg, char *msg, PLI_BYTE8 *name) +{ + assert(arg); + PLI_INT32 ctype = 0; + + switch (vpi_get(vpiType, arg)) { + case vpiConstant: + case vpiParameter: + /* These must be a string or binary constant. */ + ctype = vpi_get(vpiConstType, arg); + if (ctype != vpiStringConst && ctype != vpiBinaryConst) { + vpi_mcd_printf(1, msg, name); + vpi_control(vpiFinish, 1); + } + break; + + /* These have valid string values. */ + case vpiIntegerVar: + case vpiMemoryWord: + case vpiNet: + case vpiReg: + case vpiTimeVar: + break; + + default: + /* Anything else is not a string. */ + vpi_mcd_printf(1, msg, name); + vpi_control(vpiFinish, 1); + break; + } +} + +/* + * Since the compiletf routines are all the same they are located here, + * so we only need a single copy. + */ + +/* $dumpall does not take an argument. */ +PLI_INT32 sys_dumpall_compiletf(PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + + if (argv != 0) { + vpi_mcd_printf(1, "ERROR: %s does not take an argument.\n", name); + vpi_control(vpiFinish, 1); + } + + return 0; +} + +/* $dumpfile takes a single string argument. */ +PLI_INT32 sys_dumpfile_compiletf(PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle file; + + /* Check that there is an argument and that it is a string. */ + if (argv == 0) { + vpi_mcd_printf(1, "ERROR: %s requires an argument.\n", name); + vpi_control(vpiFinish, 1); + return 0; + } + check_string_arg(vpi_scan(argv), "ERROR: %s's argument must be a" + " string.\n", name); + + /* Check that there is only a single argument. */ + if (vpi_scan(argv) != 0) { + vpi_mcd_printf(1, "ERROR: %s takes a single argument.\n", name); + vpi_control(vpiFinish, 1); + return 0; + } + + return 0; +} + +/* $dumpflush does not take an argument. */ +PLI_INT32 sys_dumpflush_compiletf(PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + + if (argv != 0) { + vpi_mcd_printf(1, "ERROR: %s does not take an argument.\n", name); + vpi_control(vpiFinish, 1); + } + + return 0; +} + +/* $dumplimit takes a single numeric argument. */ +PLI_INT32 sys_dumplimit_compiletf(PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + + /* Check that there is an argument and that it is numeric. */ + if (argv == 0) { + vpi_mcd_printf(1, "ERROR: %s requires an argument.\n", name); + vpi_control(vpiFinish, 1); + return 0; + } + check_numeric_arg(vpi_scan(argv), "ERROR: %s's argument must be" + " numeric.\n", name); + + /* Check that there is only a single argument. */ + if (vpi_scan(argv) != 0) { + vpi_mcd_printf(1, "ERROR: %s takes a single argument.\n", name); + vpi_control(vpiFinish, 1); + return 0; + } + + return 0; +} + +/* $dumpoff does not take an argument. */ +PLI_INT32 sys_dumpoff_compiletf(PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + + if (argv != 0) { + vpi_mcd_printf(1, "ERROR: %s does not take an argument.\n", name); + vpi_control(vpiFinish, 1); + } + + return 0; +} + +/* $dumpon does not take an argument. */ +PLI_INT32 sys_dumpon_compiletf(PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + + if (argv != 0) { + vpi_mcd_printf(1, "ERROR: %s does not take an argument.\n", name); + vpi_control(vpiFinish, 1); + } + + return 0; +} + +/* $dumpvars takes a variety of arguments. */ +PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle arg; + + /* No arguments is OK, dump everything. */ + if (argv == 0) + return 0; + + /* The first argument is the numeric level. */ + check_numeric_arg(vpi_scan(argv), "ERROR: %s's first argument must be" + " numeric.\n", name); + + /* The rest of the arguments are either a module or a variable. */ + while (arg = vpi_scan(argv)) { +/* Need variable checks here. */ + } + + return 0; +} + diff --git a/vpi/vcd_priv.h b/vpi/vcd_priv.h index 14a201cf8..be39c4e88 100644 --- a/vpi/vcd_priv.h +++ b/vpi/vcd_priv.h @@ -22,6 +22,8 @@ #ident "$Id: vcd_priv.h,v 1.2 2003/02/13 18:13:28 steve Exp $" #endif +#include "vpi_user.h" + extern int is_escaped_id(const char *name); struct vcd_names_s; @@ -44,4 +46,13 @@ extern void vcd_names_sort(struct vcd_names_list_s*tab); extern const char*find_nexus_ident(int nex); extern void set_nexus_ident(int nex, const char *id); +/* The compiletf routines are common for the VCD, LXT and LXT2 dumpers. */ +extern PLI_INT32 sys_dumpall_compiletf(PLI_BYTE8 *name); +extern PLI_INT32 sys_dumpfile_compiletf(PLI_BYTE8 *name); +extern PLI_INT32 sys_dumpflush_compiletf(PLI_BYTE8 *name); +extern PLI_INT32 sys_dumplimit_compiletf(PLI_BYTE8 *name); +extern PLI_INT32 sys_dumpoff_compiletf(PLI_BYTE8 *name); +extern PLI_INT32 sys_dumpon_compiletf(PLI_BYTE8 *name); +extern PLI_INT32 sys_dumpvars_compiletf(PLI_BYTE8 *name); + #endif diff --git a/vvp/vvp.man b/vvp/vvp.man index a3afa4e5b..86f3d12bd 100644 --- a/vvp/vvp.man +++ b/vvp/vvp.man @@ -68,26 +68,20 @@ There are a few extended arguments that are interpreted by the standard system.vpi module, which implements the standard system tasks and so is always included. These arguments are described here. .TP 8 -.B -vcd\fR|\fP-vcd-none +.B -vcd This extended argument sets the wave dump format to VCD. This is the default in the absence of any \fBIVERILOG_DUMPER\fP environment variable. The VCD dump files are large and ponderous, but are also maximally compatible with third party tools that read waveform dumps. -.PP -The \fB-vcd-none\fP variant actually suppresses all waveform -output. This can make long simulations run faster. .TP 8 -.B -lxt\fR|\fP-lxt-speed\fR|\fP-lxt-space\fR|\fP-lxt-none +.B -lxt\fR|\fP-lxt-speed\fR|\fP-lxt-space These extended arguments set the wave dump format to lxt, possibly with format optimizations. The \fB-lxt-space\fP flag sets the output format to lxt with full compression enabled. The resulting files are quite small. The \fB-lxt-speed\fP chooses the lxt compression mode that leads to the best execution time and the fastest read time, at the expense of some file size. -.PP -The \fB-lxt-none\fP variant actually suppresses all waveform -output. This can make long simulations run faster. .TP 8 .B -lxt2\fR|\fP-lx2 @@ -96,14 +90,20 @@ space, and is written out incrementally. Thus, you can view lxt2 files while a simulation is still running (or paused) or if your simulation crashes or is killed, you still have a useful dump. +.TP 8 +.B -none +This flag can be used by itself or appended to the end of the above +dumpers (vcd/lxt/lxt2/lx2) to suppress all waveform output. This can +make long simulations run faster. + .TP 8 .B -sdf-warn -When loading an SDF annnotation file, this option causes the annotator +When loading an SDF annotation file, this option causes the annotator to print warnings for questionable but non-fatal issues. .TP 8 .B -sdf-info -When loading an SDF annnotation file, this option causes the annotator +When loading an SDF annotation file, this option causes the annotator to print information about the annotation. .TP 8