From a916f8e34e551d56eba954a39752c64e97a1000c Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 7 Jun 2010 19:16:09 -0700 Subject: [PATCH] V0.9: Cache vpi_call error messages so we can include file and line info. This patch caches the vpi_call error messages (task/function does not exist, task being called as a function and function being called as a task). This allows us to display the file name and line number information for the invalid usage. --- vvp/compile.h | 3 +- vvp/main.cc | 5 ++-- vvp/vpi_tasks.cc | 77 +++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/vvp/compile.h b/vvp/compile.h index b134d7ee8..7b44405c4 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -1,7 +1,7 @@ #ifndef __compile_H #define __compile_H /* - * Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -403,6 +403,7 @@ extern void compile_vpi_func_call(char*label, char*name, unsigned vbit, int vwid, long file_idx, long lineno, unsigned argc, vpiHandle*argv); +extern void print_vpi_call_errors(); extern void compile_fork(char*label, struct symb_s targ_s, struct symb_s scope_s); diff --git a/vvp/main.cc b/vvp/main.cc index 8ae5210f7..fdc6165ba 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -276,7 +276,7 @@ int main(int argc, char*argv[]) if (version_flag) { fprintf(stderr, "Icarus Verilog runtime version " VERSION " (" VERSION_TAG ")\n\n"); - fprintf(stderr, "Copyright 1998-2009 Stephen Williams\n\n"); + fprintf(stderr, "Copyright 1998-2010 Stephen Williams\n\n"); fprintf(stderr, " This program is free software; you can redistribute it and/or modify\n" " it under the terms of the GNU General Public License as published by\n" @@ -345,6 +345,7 @@ int main(int argc, char*argv[]) int ret_cd = compile_design(design_path); destroy_lexor(); + print_vpi_call_errors(); if (ret_cd) return ret_cd; if (!have_ivl_version) { diff --git a/vvp/vpi_tasks.cc b/vvp/vpi_tasks.cc index 6c48dd6b3..359b5c24b 100644 --- a/vvp/vpi_tasks.cc +++ b/vvp/vpi_tasks.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -547,6 +547,67 @@ struct __vpiUserSystf* vpip_find_systf(const char*name) return 0; } +/* + * To get better error message we need to cache the vpi_call fail + * information so that we can print the file name. + */ +enum vpi_call_error_type {VPI_CALL_NO_DEF, VPI_CALL_TASK_AS_FUNC, + VPI_CALL_FUNC_AS_TASK}; +typedef struct vpi_call_error { + vpi_call_error_type type; + char *name; + long file_idx; + long lineno; +} vpi_call_error_s, *vpi_call_error_p; + +static vpi_call_error_p vpi_call_error_lst = NULL; +static unsigned vpi_call_error_num = 0; + +static void add_vpi_call_error(vpi_call_error_type type, const char *name, + long file_idx, long lineno) +{ + vpi_call_error_lst = (vpi_call_error_p) + realloc((void *)vpi_call_error_lst, + (vpi_call_error_num + 1) * + sizeof(vpi_call_error_s)); + vpi_call_error_lst[vpi_call_error_num].type = type; + vpi_call_error_lst[vpi_call_error_num].name = strdup(name); + vpi_call_error_lst[vpi_call_error_num].file_idx = file_idx; + vpi_call_error_lst[vpi_call_error_num].lineno = lineno; + vpi_call_error_num += 1; +} + +void print_vpi_call_errors() +{ + for (unsigned idx = 0; idx < vpi_call_error_num; idx += 1) { + switch (vpi_call_error_lst[idx].type) { + case VPI_CALL_NO_DEF: + fprintf(stderr, "%s:%d: Error: System task/function %s() is " + "not defined by any module.\n", + file_names[vpi_call_error_lst[idx].file_idx], + vpi_call_error_lst[idx].lineno, + vpi_call_error_lst[idx].name); + break; + case VPI_CALL_TASK_AS_FUNC: + fprintf(stderr, "%s:%d: Error: %s() is a system task, it " + "cannot be called as a function.\n", + file_names[vpi_call_error_lst[idx].file_idx], + vpi_call_error_lst[idx].lineno, + vpi_call_error_lst[idx].name); + break; + case VPI_CALL_FUNC_AS_TASK: + fprintf(stderr, "%s:%d: Error: %s() is a system function, it " + "cannot be called as a task.\n", + file_names[vpi_call_error_lst[idx].file_idx], + vpi_call_error_lst[idx].lineno, + vpi_call_error_lst[idx].name); + break; + } + free(vpi_call_error_lst[idx].name); + } + free(vpi_call_error_lst); +} + /* * A vpi_call is actually built up into a vpiSysTaskCall VPI object * that refers back to the vpiUserSystf VPI object that is the @@ -566,16 +627,15 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid, { struct __vpiUserSystf*defn = vpip_find_systf(name); if (defn == 0) { - fprintf(stderr, "%s: This task not defined " - "by any modules. I cannot compile it.\n", name); + add_vpi_call_error(VPI_CALL_NO_DEF, name, file_idx, lineno); return 0; } switch (defn->info.type) { case vpiSysTask: if (vwid != 0 || fnet != 0) { - fprintf(stderr, "%s: This is a system Task, " - "you cannot call it as a Function\n", name); + add_vpi_call_error(VPI_CALL_TASK_AS_FUNC, name, file_idx, + lineno); return 0; } assert(vbit == 0); @@ -583,14 +643,15 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid, case vpiSysFunc: if (vwid == 0 && fnet == 0) { - fprintf(stderr, "%s: This is a system Function, " - "you cannot call it as a Task\n", name); + add_vpi_call_error(VPI_CALL_FUNC_AS_TASK, name, file_idx, + lineno); return 0; } break; default: - fprintf(stderr, "Unsupported type %d.\n", (int)defn->info.type); + fprintf(stderr, "Unsupported call type %d.\n", + (int)defn->info.type); assert(0); }