DirectC C-Layer: open arrays and abstract access - revised


Subject: DirectC C-Layer: open arrays and abstract access - revised
From: Andrzej Litwiniuk (Andrzej.Litwiniuk@synopsys.com)
Date: Wed Jan 08 2003 - 08:48:07 PST


Team,

Here is the revised/corrected version of the abstract access to open vectors.

Modifications:
 - fixed typos ("U" replaced with "int" in function headers)
 - prefix "svc"
 - redundant functions eliminated (variants of "get pointer")
 - new function "int svcSizeOfArray(svcHandle);"
 - corrected declaration "void foo(input MyType i [][])" in Example 3.

Regards,
Andrzej I. Litwiniuk

        ============================================================
        DirectC C layer - open (unsized) arrays and abstract access
        ============================================================

Overview
========

All open arrays, packed (i.e. vectors) and unpacked (i.e. arrays per se)
will be passed by handle and accessed mainly via accessory functions (abstract
access).

Abstract access for open arrays will allow inquires about the dimensions
and the original boundaries of SV actual argument and will allow to access
the elements of an open array using the same range of indices as in SV.

The programmer will always have a choice, whether to specify a formal
argument as a sized array or as an open (unsized) array.

In the former case all indices will be normalized on the C side (i.e. 0 and up)
and the programmer is assumed to know the size of an array.
Programmer is also assumed to be capable of figuring out how the ranges of
the actual argument will map onto C-style ranges.
Hint: programmers may decide to stick to [n:0]name[0:k] style ranges in SV.

In the later case, i.e. open array, the abstract access mode will be used,
what would facilitate SV-style of indexing with the original boundaries of
the actual argument, all this for the price of some overhead.

Note that this provides some degree of flexibility and allows programmer
to control the trade-off of performance vs. convenience.
If a formal argument is specified as a sized array, then it will be passed by reference, with no overhead, and will be directly accessible as a normalized
array.
If a formal argument is specified as a open (unsized) array, then it will be
passed by handle, with some overhead, and will be accessible mostly indirectly,
again with some overhead, although with the original boundaries.

Unsized formal arguments
========================

For input, output and inout arguments that are declared as open array,
the corresponding formal argument in C will be of type svcHandle.

Type svcHandle denotes an opaque pointer to a descriptor generated by SV
compiler for an actual argument. Descriptor will provide comprehensive
information about an actual argument. The internal structure of a descriptor
is implementation dependent and fully irrelevant to the user.

Limitations
===========

The unpacked part of an open array may be multidimensional.
The packed part, however, is restricted to a single dimension.

Note that any packed data type in SV is eventually equivalent to
a one-dimensional packed array. Hence the above limitation is practically
not restrictive.

Open array querying functions
=============================

These functions are modelled upon SV array querying functions, with
the same semantics:

/* h= handle to open array, d=dimension */

/* For unpacked part */
int svcUnpackedLeft(svcHandle h, int d);
int svcUnpackedRight(svcHandle h, int d);
int svcUnpackedLow(svcHandle h, int d);
int svcUnpackedHigh(svcHandle h, int d);
int svcUnpackedIncrement(svcHandle h, int d);
int svcUnpackedLength(svcHandle h, int d);
int svcUnpackedDimensions(svcHandle h);

/* For 1-dimensional packed part */
int svcPackedLeft(svcHandle h);
int svcPackedRight(svcHandle h);
int svcPackedLow(svcHandle h);
int svcPackedHigh(svcHandle h);
int svcPackedIncrement(svcHandle h);
int svcPackedLength(svcHandle h);

(Would you prefer more intuitive names for 'Unpacked', say, "svcArr*"?)

Open array access functions
=============================

Similarly to sized arrays, there are functions for copying data between
the simulator representation and the canonical representation.

It will be also possible to get the actual address of SV data object
or of an individual element of an unpacked array.
This may be useful for the simulator-specific tuning of the application.

Depending on the type of an element of an unpacked array, different access
methods are used:
- packed arrays ('bit' or 'logic') are accessed via copying to or from
  the canonical representation
- scalars (1-bit value of type 'bit' or 'logic') are accessed directly
- other types of values (e.g. structures) are accessed via generic pointers;
  a library function calculates an address and the user should provide
  the appropriate casting
- all types but scalars may be accessed via pointers, as described above

SV allows arbitrary dimensions and hence an arbitrary number of indices.
To facilitate this, a variable argument list functions will be used.
For the sake of performance the specialized versions of all indexing functions
are provided for 1, 2 and 3 indices.

Access via canonical representation
-----------------------------------

This group of functions is meant for accessing elements which are packed
arrays ('bit' or 'logic').

The following functions will copy a single vector from a canonical
representation to an element of an open array or other way round.

Element of an array is identified by indices bound by the ranges of the
actual argument. In other words, original SV values are used for indexing.

/* functions for translation between simulator's and canonical
   representations */

/* s=source, d=destination */

/* actual <-- canonical */
void svcPutBitArrElemVec32 (svcHandle d, svcBitVec32* s, int indx1, ...);
void svcPutBitArrElem1Vec32(svcHandle d, svcBitVec32* s, int indx1);
void svcPutBitArrElem2Vec32(svcHandle d, svcBitVec32* s, int indx1, int indx2);
void svcPutBitArrElem3Vec32(svcHandle d, svcBitVec32* s,
                                             U indx1, int indx2, int indx3);

void svcPutLogicArrElemVec32 (svcHandle d, svcLogicVec32* s, int indx1, ...);
void svcPutLogicArrElem1Vec32(svcHandle d, svcLogicVec32* s, int indx1);
void svcPutLogicArrElem2Vec32(svcHandle d, svcLogicVec32* s, int indx1, int indx2);
void svcPutLogicArrElem3Vec32(svcHandle d, svcLogicVec32* s,
                                                 U indx1, int indx2, int indx3);

/* canonical <-- actual */
void svcGetBitArrElemVec32 (svcBitVec32* d, svcHandle s, int indx1, ...);
void svcGetBitArrElem1Vec32(svcBitVec32* d, svcHandle s, int indx1);
void svcGetBitArrElem2Vec32(svcBitVec32* d, svcHandle s, int indx1, int indx2);
void svcGetBitArrElem3Vec32(svcBitVec32* d, svcHandle s,
                                             U indx1, int indx2, int indx3);

void svcGetLogicArrElemVec32 (svcLogicVec32* d, svcHandle s, int indx1, ...);
void svcGetLogicArrElem1Vec32(svcLogicVec32* d, svcHandle s, int indx1);
void svcGetLogicArrElem2Vec32(svcLogicVec32* d, svcHandle s, int indx1, int indx2);
void svcGetLogicArrElem3Vec32(svcLogicVec32* d, svcHandle s,
                                                  U indx1,U indx2, int indx3);

The above functions copy the whole array in either direction. User is responsible for providing the correct width and for allocating an array in the canonical
representation.

Access to scalars ('bit' and 'logic')
-------------------------------------

Another group of functions is needed for scalars (i.e. when an element
of an array is a simple scalar, 'bit' or 'logic':

svcBit svcGetBitArrElem (svcHandle s, int indx1, ...);
svcBit svcGetBitArrElem (svcHandle s, int indx1);
svcBit svcGetBitArrElem (svcHandle s, int indx1, int indx2);
svcBit svcGetBitArrElem (svcHandle s, int indx1,U indx2, int indx3);

svcLogic svcGetLogicArrElem(svcHandle s, int indx1, ...);
svcLogic svcGetLogicArrElem(svcHandle s, int indx1);
svcLogic svcGetLogicArrElem(svcHandle s, int indx1, int indx2);
svcLogic svcGetLogicArrElem(svcHandle s, int indx1,U indx2, int indx3);

void svcPutLogicArrElem(svcHandle d, svcBit value, int indx1, ...);
void svcPutLogicArrElem(svcHandle d, svcBit value, int indx1);
void svcPutLogicArrElem(svcHandle d, svcBit value, int indx1, int indx2);
void svcPutLogicArrElem(svcHandle d, svcBit value, int indx1,U indx2, int indx3);

void svcPutBitArrElem (svcHandle d, svcLogic value, int indx1, ...);
void svcPutBitArrElem (svcHandle d, svcLogic value, int indx1);
void svcPutBitArrElem (svcHandle d, svcLogic value, int indx1, int indx2);
void svcPutBitArrElem (svcHandle d, svcLogic value, int indx1,U indx2, int indx3);

Access to the actual representation
-----------------------------------

The following functions provide an actual address of the whole array or
of its individual element. These functions will be used for accessing
elements of the arrays of types compatible with C.

These functions will be also usefull for the vendors, because
they provide access to the actual representation for all types of arrays.

/* a pointer to the actual representation of the whole array of any type */
void *svcGetArrayPtr(svcHandle);

Note that no specific representation of an array is assumed here, hence
a generic pointer void *.

int svcSizeOfArray(svcHandle); /* total size in bytes */

/* Return a pointer to an element of the array
   or NULL if index outside the range or null pointer */

void *svcGetArrElemPtr(svcHandle, int indx1, ...);

      /* specialized versions for 1-, 2- and 3-dimensional arrays: */
void *svcGetArrElemPtr1(svcHandle, int indx1);
void *svcGetArrElemPtr2(svcHandle, int indx1, int indx2);
void *svcGetArrElemPtr3(svcHandle, int indx1, int indx2, int indx3);

Access to array elements of other types
---------------------------------------

If array's elements are of a type compatible with C, then there is no need
to use the canonical representation. In such situations the elements will
be accessed via pointers, i.e. the actual address of an element will be
computed first and then used to access the desired element.

Example 3 - open array,
======================

SV:
        typedef struct {int i; ... } MyType;

        extern void foo(input MyType i [][]);
                        // 2-dimensional unsized unpacked array of MyType

        MyType a_10x5 [11:20][6:2];
        MyType a_64x8 [64:1][-1:-8];

        foo(a_10x5);
        foo(a_64x8);

C:
        #include "svcerilog.h"

        typedef struct {int i; ... } MyType;

        void foo(svcHandle h)
        {
          MyType my_value;
          int i, j;
          int lo1 = svcUnpackedLow(h, 1);
          int hi1 = svcUnpackedHigh(h, 1);
          int lo2 = svcUnpackedLow(h, 2);
          int hi2 = svcUnpackedHigh(h, 2);

          for (i = lo1; i <= hi1; i++) {
              for (j = lo2; j <= hi2; j++) {

                my_value = *(MyType *)svcGetArrElemPtr2(h, i, j);
                ...
                *(MyType *)svcGetArrElemPtr2(h, i, j) = my_value;
                ...
              }
                ...
          }
        }

==============================================================================
Andrzej I. Litwiniuk, PhD Principal Engineer VCS R&D
Synopsys, Inc TEL: (508) 263-8056
154 Crane Meadow Road, Suite 300, FAX: (508) 263-8069
Marlboro, MA 01752, USA
==============================================================================



This archive was generated by hypermail 2b28 : Wed Jan 08 2003 - 08:49:19 PST