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


Subject: RE: [sv-cc] RE: Feedback on Read API (VPI enhancement)
From: Joao Geada (Joao.Geada@synopsys.com)
Date: Wed Dec 17 2003 - 08:23:30 PST


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
      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
      (408) 467-7893



This archive was generated by hypermail 2b28 : Wed Dec 17 2003 - 08:24:36 PST