/* * Implement $fclose system function */ static PLI_INT32 sys_fclose_calltf(PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle fd = vpi_scan(argv); s_vpi_value val; PLI_UINT32 fd_mcd; errno = 0; vpi_free_object(argv); /* Get the file/MC descriptor and verify that it is valid. */ val.format = vpiIntVal; vpi_get_value(fd, &val); fd_mcd = val.value.integer; if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) || ( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, "%s", "") == EOF) || (! fd_mcd)) { vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("invalid file descriptor/MCD (0x%x) given to %s.\n", (unsigned int)fd_mcd, name); errno = EBADF; return 0; } /* We need to cancel any active $fstrobe()'s for this FD/MCD. * For now we check in the strobe callback and skip the output * generation when needed. */ vpi_mcd_close(fd_mcd); return 0; }
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 == 2) { vpi_mcd_printf(1, "VCD Error:" " $dumpvars ignored," " previously called at simtime %" PLI_UINT64_FMT "\n", dumpvars_time); return 1; } time.type = vpiSimTime; cb.time = &time; cb.reason = cbReadOnlySynch; cb.cb_rtn = dumpvars_cb; cb.user_data = 0x0; cb.obj = 0x0; vpi_register_cb(&cb); dumpvars_status = 1; return 0; }
int _mon_check_mcd() { PLI_INT32 status; PLI_UINT32 mcd; PLI_BYTE8* filename = (PLI_BYTE8*)"obj_dir/t_vpi_var/mcd_open.tmp"; mcd = vpi_mcd_open(filename); CHECK_RESULT_NZ(mcd); { // Check it got written FILE* fp = fopen(filename,"r"); CHECK_RESULT_NZ(fp); fclose(fp); } status = vpi_mcd_printf(mcd, (PLI_BYTE8*)"hello %s", "vpi_mcd_printf"); CHECK_RESULT(status, strlen("hello vpi_mcd_printf")); status = vpi_mcd_flush(mcd); CHECK_RESULT(status, 0); status = vpi_mcd_close(mcd); CHECK_RESULT(status, 0); status = vpi_flush(); CHECK_RESULT(status, 0); return 0; }
static void open_dumpfile(void) { 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", dump_path); return; } else { int prec = vpi_get(vpiTimePrecision, 0); unsigned scale = 1; unsigned udx = 0; time_t walltime; vpi_mcd_printf(1, "VCD info: dumpfile %s opened for output.\n", dump_path); time(&walltime); assert(prec >= -15); while (prec < 0) { udx += 1; prec += 3; } while (prec > 0) { scale *= 10; prec -= 1; } fprintf(dump_file, "$date\n"); fprintf(dump_file, "\t%s",asctime(localtime(&walltime))); fprintf(dump_file, "$end\n"); fprintf(dump_file, "$version\n"); fprintf(dump_file, "\tIcarus Verilog\n"); fprintf(dump_file, "$end\n"); fprintf(dump_file, "$timescale\n"); fprintf(dump_file, "\t%u%s\n", scale, units_names[udx]); fprintf(dump_file, "$end\n"); } }
static int sys_dumpfile_compiletf(char*name) { vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); vpiHandle item; 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"); } if (dump_path) { vpi_mcd_printf(1, "VCD Warning:" " Overriding dumpfile path %s with %s\n", dump_path, path); free(dump_path); } dump_path = path; 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"); } }
/* * Implement $fflush system function */ static PLI_INT32 sys_fflush_calltf(PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle arg; s_vpi_value val; PLI_UINT32 fd_mcd; FILE *fp; errno = 0; /* If we have no argument then flush all the streams. */ if (argv == 0) { fflush(NULL); return 0; } /* Get the file/MC descriptor and verify that it is valid. */ arg = vpi_scan(argv); vpi_free_object(argv); val.format = vpiIntVal; vpi_get_value(arg, &val); fd_mcd = val.value.integer; /* If the MCD is zero we have nothing to do so just return. */ if (fd_mcd == 0) return 0; if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) || ( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, "%s", "") == EOF) || (! fd_mcd)) { vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("invalid file descriptor/MCD (0x%x) given to %s.\n", (unsigned int)fd_mcd, name); errno = EBADF; return 0; } if (IS_MCD(fd_mcd)) { vpi_mcd_flush(fd_mcd); } else { /* If we have a valid file descriptor flush the file. */ fp = vpi_get_file(fd_mcd); if (fp) fflush(fp); } return 0; }
static int sys_dumpfile_calltf(char*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 void scan_item(unsigned depth, vpiHandle item, int skip) { struct t_cb_data cb; struct vcd_info* info; const char* type; const char* name; const char* ident; int nexus_id; /* list of types to iterate upon */ int i; static int types[] = { /* Value */ vpiNet, vpiReg, vpiVariables, /* Scope */ vpiFunction, vpiModule, vpiNamedBegin, vpiNamedFork, vpiTask, -1 }; switch (vpi_get(vpiType, item)) { case vpiMemory: /* don't know how to watch memories. */ break; case vpiNamedEvent: /* There is nothing in named events to dump. */ break; case vpiNet: type = "wire"; if(0){ case vpiIntegerVar: case vpiTimeVar: case vpiReg: type = "reg"; } if (skip) break; name = vpi_get_str(vpiName, item); nexus_id = vpi_get(_vpiNexusId, item); if (nexus_id) { ident = find_nexus_ident(nexus_id); } else { ident = 0; } if (!ident) { ident = strdup(vcdid); gen_new_vcd_id(); if (nexus_id) set_nexus_ident(nexus_id, ident); info = malloc(sizeof(*info)); info->time.type = vpiSimTime; info->item = item; info->ident = ident; info->scheduled = 0; cb.time = &info->time; cb.user_data = (char*)info; cb.value = NULL; cb.obj = item; cb.reason = cbValueChange; cb.cb_rtn = variable_cb_1; info->next = vcd_list; info->dmp_next = 0; vcd_list = info; info->cb = vpi_register_cb(&cb); } fprintf(dump_file, "$var %s %u %s %s", type, vpi_get(vpiSize, item), ident, name); /* FIXME if (vpi_get(vpiVector, item) */ if (vpi_get(vpiSize, item) > 1 || vpi_get(vpiLeftRange, item) != 0) { fprintf(dump_file, "[%i:%i]", vpi_get(vpiLeftRange, item), vpi_get(vpiRightRange, item)); } fprintf(dump_file, " $end\n"); break; case vpiRealVar: if (skip) break; /* Declare the variable in the VCD file. */ name = vpi_get_str(vpiName, item); ident = strdup(vcdid); gen_new_vcd_id(); fprintf(dump_file, "$var real 1 %s %s $end\n", ident, name); /* Add a callback for the variable. */ info = malloc(sizeof(*info)); info->time.type = vpiSimTime; info->item = item; info->ident = ident; info->scheduled = 0; cb.time = &info->time; cb.user_data = (char*)info; cb.value = NULL; cb.obj = item; cb.reason = cbValueChange; cb.cb_rtn = variable_cb_1; info->next = vcd_list; info->dmp_next = 0; vcd_list = info; info->cb = vpi_register_cb(&cb); break; case vpiModule: type = "module"; if(0){ case vpiNamedBegin: type = "begin"; }if(0){ case vpiTask: type = "task"; }if(0){ case vpiFunction: type = "function"; }if(0){ case vpiNamedFork: type = "fork"; } if (depth > 0) { int nskip; vpiHandle argv; const char* fullname = vpi_get_str(vpiFullName, item); #if 0 vpi_mcd_printf(1, "VCD info:" " scanning scope %s, %u levels\n", fullname, depth); #endif nskip = 0 != vcd_names_search(&vcd_tab, fullname); if (!nskip) vcd_names_add(&vcd_tab, fullname); else vpi_mcd_printf(1, "VCD warning:" " ignoring signals" " in previously scanned scope %s\n", fullname); name = vpi_get_str(vpiName, item); fprintf(dump_file, "$scope %s %s $end\n", type, name); for (i=0; types[i]>0; i++) { vpiHandle hand; argv = vpi_iterate(types[i], item); while (argv && (hand = vpi_scan(argv))) { scan_item(depth-1, hand, nskip); } } fprintf(dump_file, "$upscope $end\n"); } break; default: vpi_mcd_printf(1, "VCD Error: $dumpvars: Unsupported parameter " "type (%d)\n", vpi_get(vpiType, item)); } }
static void sys_lxt_or_vcd_register() { int idx; struct t_vpi_vlog_info vlog_info; const char*dumper; /* Get the dumper of choice from the IVERILOG_DUMPER environment variable. */ dumper = getenv("IVERILOG_DUMPER"); if (dumper) { char*cp = strchr(dumper,'='); if (cp != 0) dumper = cp + 1; } else { dumper = "vcd"; } /* Scan the extended arguments, looking for flags that select major features. This can override the environment variable settings. */ vpi_get_vlog_info(&vlog_info); for (idx = 0 ; idx < vlog_info.argc ; idx += 1) { if (strcmp(vlog_info.argv[idx],"-fst") == 0) { dumper = "fst"; } else if (strcmp(vlog_info.argv[idx],"-fst-space") == 0) { dumper = "fst"; } else if (strcmp(vlog_info.argv[idx],"-fst-speed") == 0) { dumper = "fst"; } else if (strcmp(vlog_info.argv[idx],"-fst-space-speed") == 0) { dumper = "fst"; } else if (strcmp(vlog_info.argv[idx],"-fst-speed-space") == 0) { dumper = "fst"; } else if (strcmp(vlog_info.argv[idx],"-fst-none") == 0) { dumper = "none"; } else if (strcmp(vlog_info.argv[idx],"-lxt") == 0) { dumper = "lxt"; } else if (strcmp(vlog_info.argv[idx],"-lxt-space") == 0) { dumper = "lxt"; } else if (strcmp(vlog_info.argv[idx],"-lxt-speed") == 0) { dumper = "lxt"; } else if (strcmp(vlog_info.argv[idx],"-lxt-none") == 0) { dumper = "none"; } else if (strcmp(vlog_info.argv[idx],"-lxt2") == 0) { dumper = "lxt2"; } else if (strcmp(vlog_info.argv[idx],"-lxt2-space") == 0) { dumper = "lxt2"; } else if (strcmp(vlog_info.argv[idx],"-lxt2-speed") == 0) { dumper = "lxt2"; } else if (strcmp(vlog_info.argv[idx],"-lxt2-none") == 0) { dumper = "none"; } else if (strcmp(vlog_info.argv[idx],"-lx2") == 0) { dumper = "lxt2"; } else if (strcmp(vlog_info.argv[idx],"-lx2-space") == 0) { dumper = "lxt2"; } else if (strcmp(vlog_info.argv[idx],"-lx2-speed") == 0) { dumper = "lxt2"; } else if (strcmp(vlog_info.argv[idx],"-lx2-none") == 0) { dumper = "none"; } else if (strcmp(vlog_info.argv[idx],"-vcd") == 0) { dumper = "vcd"; } else if (strcmp(vlog_info.argv[idx],"-vcd-off") == 0) { dumper = "none"; } else if (strcmp(vlog_info.argv[idx],"-vcd-none") == 0) { dumper = "none"; } else if (strcmp(vlog_info.argv[idx],"-none") == 0) { dumper = "none"; } } if (strcmp(dumper, "vcd") == 0) sys_vcd_register(); else if (strcmp(dumper, "VCD") == 0) sys_vcd_register(); else if (strcmp(dumper, "fst") == 0) sys_fst_register(); else if (strcmp(dumper, "FST") == 0) sys_fst_register(); else if (strcmp(dumper, "lxt") == 0) sys_lxt_register(); else if (strcmp(dumper, "LXT") == 0) sys_lxt_register(); else if (strcmp(dumper, "lxt2") == 0) sys_lxt2_register(); else if (strcmp(dumper, "LXT2") == 0) sys_lxt2_register(); else if (strcmp(dumper, "lx2") == 0) sys_lxt2_register(); else if (strcmp(dumper, "LX2") == 0) sys_lxt2_register(); else if (strcmp(dumper, "none") == 0) sys_vcdoff_register(); else if (strcmp(dumper, "NONE") == 0) sys_vcdoff_register(); else { vpi_mcd_printf(1, "system.vpi: Unknown dumper format: %s," " using VCD instead.\n", dumper); sys_vcd_register(); } }