Subject: RE: [sv-cc] RE: Feedback on Read API (VPI enhancement)
From: Bassam Tabbara (bassam@novas.com)
Date: Wed Dec 17 2003 - 08:50:24 PST
Hi All,
Thanks Joao and Francoise. There is, I believe, a subtle distinction
between the 2 clarifications you suggest.
I think *for purposes of this chapter*, a simple enhancement to
vpi_read_init to clear up the confusion (basically in the current scheme
of the proposal, the "dlopen" part is ignored, and the "db pointer" is
not explicity returned, these can combine to make things not very clear,
despite the explanation, a pointer can be better than a 100 words :-)!
so to make that clear I'm thinking a simple reworking (NULL mostly for
the lib argument, and some explanation in the "multiple database"
section a la Joao's suggestion.) I had wanted to stay away from doing
something like pointer-> but I think that can be controlled in one
section and would not be a major distraction/digression from the VPI
part.
If we were to think of the *whole VPI* and the set of interfaces added
to SV (coverage/assertion/....) the approach Francoise details is more
appropriate, and it is reasonable to add a separate chapter/annex to
explain static/dynamic linking and so on ... This is outside the scope
of *this* chapter, and more appropriately separated out. As a committee
we can decide to take this on, and decide the when/where.
Thx.
-Bassam.
-- Dr. Bassam Tabbara Technical Manager, R&D Novas Software, Inc.http://www.novas.com <http://www.novas.com/> (408) 467-7893
-----Original Message----- From: Joao Geada [mailto:Joao.Geada@synopsys.com] Sent: Wednesday, December 17, 2003 8:24 AM To: Francoise Martinolle; Joao.Geada@synopsys.COM; bassam@novas.com; Sv-Cc Cc: Ghassan Khoory Subject: RE: [sv-cc] RE: Feedback on Read API (VPI enhancement)
Francoise, I think you're making it unnecessarily complex: vpi_read_init could itself be the bootstrapper routine and belong to the "simulator" system. Note that as I said/implied in my comments, the intent for vpi_read_init is to: 1- load the appropriate reader library (dlopen) 2- use a well defined entry point in the newly loaded library (eg library name itself as a function, so the "vpd" reader library would define "vpd()" as it's entry point) to create the function vector 3- indirectiving via the just created function vector, invoke the routine to load the requested waveform 4- if all the above was successful, return the function vector. For standalone applications the above "vpi_read_init" functionality would need to be provided in a standalone library, so that the simulator was not required to be linked into the standalone executable. I believe in keeping things as simple as possible (but no simpler ;-) Joao
======================================================================== ====== Joao Geada, PhD Principal Engineer Verif Tech Group Synopsys, Inc TEL: (508) 263-8083 377 Simarano Drive, Suite 300, FAX: (508) 263-8069 Marlboro, MA 01752, USA ======================================================================== ======
-----Original Message----- From: owner-sv-cc@eda.org [mailto:owner-sv-cc@eda.org]On Behalf Of Francoise Martinolle Sent: Wednesday, December 17, 2003 10:01 AM To: Joao.Geada@synopsys.COM; bassam@novas.com; Sv-Cc Cc: Ghassan Khoory Subject: Re: [sv-cc] RE: Feedback on Read API (VPI enhancement)
Joao,
the problem which still remains is which vpi_read_init do you call if there are multiple ones present.
If you have multiple tools providing the READ API, the only way I think to solve this problem is to have each tool provide a bootstrap function of their READ api. Essentially there would be a vpi_read_init for ncverilog, a vpi_read_init for debussy, a vpi_read_init for vcs.
An application would then need to call these bootstrap functions before starting any processing. myapp -vpiload debussy/libreadapi.so:vpi_read_init -vpiload ncv/libs/libreadapi.so:vpi_read_init - vpiload vcs/libreadapi.so:vpi_read_init
The first thing that myapp will do is to dlopen debussy/libreadapi.so and invoke vpi_read_init, then dlopen ncv/libs/libreadapi.so and call vpi_read_init and so on.
This does not work for static linking. where only one symbol vpi_read_init can exits. For static linking, each tool would need to provide a bootstrap function which name is different.
Bassam and I worked out something similar which will work in dynamic or static linking. A tool specific routine is provided which serves as a bootstrap function. This can be use in the general case where 2 VPI libraries are present because of 2 simulators. It can be extended to support the new VPI routines added with the vpi read API.
We propose to add the following routine: p_vpi_routine_array *vpi_get_routines_* ()
where the routine name would be tool specific after vpi_get_routines_. For example, NC-Verilog might create a routine vpi_get_routines_ncv(), and VCS could create a routine vpi_get_routines_vcs(). These routines would return an array of vpi_routine_array_p structs: typedef struct vpi_routine_array *p_vpi_routine_array; typedef struct vpi_routine_array { char *name; union { PLI_INT32 int_routine(); PLI_BYTE8 str_routine(); vpiHandle handle_routine(); void void_routine(); VPI_UINT32 uint_routine(); PLI_LNG64 long_routine(); ...etc } routine; } s_vpi_routine_array; The array of structures returned by vpi_get_routines_*() would return a NULL terminated array of routines. The application would then resolve each reference itself, for example: list = vpi_get_routines_ncv(); assert(list); cur = *list; while (cur && (!strcmp(cur->name,vpi_get)) cur++; assert(cur); ncv_vpi_get = cur->routine->int_routine; Similarly a waveform database tool would provide such a routine: vpi_get_routines_debussy(), or vpi_get_routines_sst2. The user application which desires to read that database produced by the waveform tool would call this routine and then resolve each VPI function reference and then be able to use the VPI read API implementation of that database. Note that this indirection is only required if a user application is used in the context of multiple tools, each tool having its own VPI implementation. Example As an example, and proof of concept, consider the following code: example.h file: #define NULL 0L
typedef struct vpi_routine_array *p_vpi_routine_array; typedef struct vpi_routine_array { char *name; union { int (*int_routine)(); char *(*str_routine)(); } routine; } s_vpi_routine_array;
#define vpiName 1 ncv.c file: #include <stdarg.h> #include <ctype.h> #include example.h
static char *vpi_get_str(int type, int RH) { return(Called NCV vpi_get_str()\n); }
static int vpi_handle(int type, int RH) { return(NULL); }
p_vpi_routine_array *vpi_get_routine_ncv() { static p_vpi_routine_array retVal[3];
retVal[0] = (p_vpi_routine_array)malloc(sizeof(s_vpi_routine_array)); (retVal[0])->name = (char *)malloc((strlen(vpi_get_str) + 1) * sizeof(char)); strcpy((retVal[0])->name,vpi_get_str); (retVal[0])->routine.str_routine = vpi_get_str;
retVal[1] = (p_vpi_routine_array)malloc(sizeof(s_vpi_routine_array)); (retVal[1])->name = (char *)malloc((strlen(vpi_handle) + 1) * sizeof(char)); strcpy((retVal[1])->name,vpi_handle); (retVal[1])->routine.int_routine = vpi_handle;
retVal[2] = NULL;
return(retVal); } vcs.c file: #include <stdarg.h> #include <ctype.h> #include example.h
static char *vpi_get_str(int type, int RH) { return(Called VCS vpi_get_str()\n); }
static int vpi_handle(int type, int RH) { return(NULL); }
p_vpi_routine_array *vpi_get_routine_vcs() { static p_vpi_routine_array retVal[3];
retVal[0] = (p_vpi_routine_array)malloc(sizeof(s_vpi_routine_array)); (retVal[0])->name = (char *)malloc((strlen(vpi_get_str) + 1) * sizeof(char)); strcpy((retVal[0])->name,vpi_get_str); (retVal[0])->routine.str_routine = vpi_get_str;
retVal[1] = (p_vpi_routine_array)malloc(sizeof(s_vpi_routine_array)); (retVal[1])->name = (char *)malloc((strlen(vpi_handle) + 1) * sizeof(char)); strcpy((retVal[1])->name,vpi_handle); (retVal[1])->routine.int_routine = vpi_handle;
retVal[2] = NULL;
return(retVal); } main.c file: #include <stdarg.h> #include <ctype.h> #include example.h
extern p_vpi_routine_array *vpi_get_routine_ncv(); extern p_vpi_routine_array *vpi_get_routine_vcs();
int main(int argc,char *argv[]) { p_vpi_routine_array *ncv = vpi_get_routine_ncv(); p_vpi_routine_array *vcs = vpi_get_routine_vcs(); p_vpi_routine_array ptr;
char *(*strFunc)();
ptr = *ncv; while (strcmp(ptr->name,vpi_get_str)) ptr++; strFunc = ptr->routine.str_routine;
printf((*strFunc)(vpiName,NULL));
ptr = *vcs; while (strcmp(ptr->name,vpi_get_str)) ptr++; strFunc = ptr->routine.str_routine;
printf((*strFunc)(vpiName,NULL)); } This code compiles and when run produces the following output: Called NCV vpi_get_str() Called VCS vpi_get_str() Of course, vpi_get_str() and vpi_handle() are not currently static routines in NC-Verilog or VCS. This issue will need to be resolved by the various tools.
At 07:19 PM 12/16/2003 -0500, Joao Geada wrote:
Bassam, I still have the same problem as before with the new revision. Basically the issue is that, without explicit indirection, all the VPI routines you use (vpi_handle et all) belong to the simulator and will always reflect the model present in the simulator, rather than any information loaded from the waveform file. I realize that this latest revision has made some effort towards this, but without completely insulating the read vpi from the simulator vpi I do not feel that the effort is sufficient. Personally I would much prefer something with the following form: reader_handle = vpi_read_init(access_mode, "read library to be used", "file to be opened") where: access mode: is the open mode as per your vpi_read_init spec "read library" (string) specifies the reader to be used (eg vcd, vpd, fsdb, dai, etc). If NULL uses vendor's default form. Basically indicates the name of a shared library to be loaded that provides the waveform reading services "file" (string) the name of the waveform file to be opened. Can be NULL if using interactive access If reader_handle is non-NULL then the read initialization was successful. From that point on, all read calls are made following the pattern: reader_handle->vpi_xxxx(args) This approach allows: 1) reader API to be kept separate from vendor's tool API 2) multiple separate readers to be present simultaneously 3) multiple databases (using same or different readers) to be opened simultaneously 4) does not (in my opinion) make the interface any harder to use or require any other changes to the existing proposal. I firmly believe that such an approach is essential for the reader API to become viable. Joao
======================================================================== ====== Joao Geada, PhD Principal Engineer Verif Tech Group Synopsys, Inc TEL: (508) 263-8083 377 Simarano Drive, Suite 300, FAX: (508) 263-8069 Marlboro, MA 01752, USA ======================================================================== ======
-----Original Message-----
From: Bassam Tabbara [mailto:bassam@novas.com]
Sent: Tuesday, December 16, 2003 6:44 PM
Subject: Feedback on Read API (VPI enhancement)
Hi Joao,
Swapnajit said you may have some feedback on the Read API ? Can you please send my way, if so ?
Thx.
-Bassam.
--
Dr. Bassam Tabbara
Technical Manager, R&D
Novas Software, Inc.
http://www.novas.com <http://www.novas.com/>
(408) 467-7893
This archive was generated by hypermail 2b28 : Wed Dec 17 2003 - 08:51:43 PST