Re: [sv-cc] RE: Feedback on Read API (VPI enhancement)


Subject: Re: [sv-cc] RE: Feedback on Read API (VPI enhancement)
From: Francoise Martinolle (fm@cadence.com)
Date: Wed Dec 17 2003 - 07:00:59 PST


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
>To: Joao.Geada@synopsys.COM
>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 - 07:01:50 PST