DirectC C-Layer: open arrays and abstract access


Subject: DirectC C-Layer: open arrays and abstract access
From: Andrzej Litwiniuk (Andrzej.Litwiniuk@synopsys.com)
Date: Fri Dec 13 2002 - 17:25:02 PST


Team,

Here is the last (?) missing piece of the C Layer of DirectC:
abstract access to open vectors.

Regards,
Andrzej I. Litwiniuk

PS. Because I will not be able to attend the remaining meetings this year,
    I'd like to use this last opportunity to wish all of you
    Merry Christmas and Happy New Year!

    See you next year!
    Andrzej

==============================================================================
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
==============================================================================

        ============================================================
        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 svHandle.

Type svHandle 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 svUnpackedLeft(svHandle h, int d);
int svUnpackedRight(svHandle h, int d);
int svUnpackedLow(svHandle h, int d);
int svUnpackedHigh(svHandle h, int d);
int svUnpackedIncrement(svHandle h, int d);
int svUnpackedLength(svHandle h, int d);
int svUnpackedDimensions(svHandle h);

/* For 1-dimensional packed part */
int svPackedLeft(svHandle h);
int svPackedRight(svHandle h);
int svPackedLow(svHandle h);
int svPackedHigh(svHandle h);
int svPackedIncrement(svHandle h);
int svPackedLength(svHandle h);

(Would you prefer shorter names, say, "svUnpkd*" instead of "svUnpacked*" ,
and similarly, "svPkd*" instead of "svPacked*"?
Or perhaps "svVec*" for packed and "svArr*" for unpacked?)

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.

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
-----------------------------------

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 vcPutBitArrElemVec32 (svHandle d, svBitVec32* s, U indx1, ...);
void vcPutBitArrElem1Vec32(svHandle d, svBitVec32* s, U indx1);
void vcPutBitArrElem2Vec32(svHandle d, svBitVec32* s, U indx1, U indx2);
void vcPutBitArrElem3Vec32(svHandle d, svBitVec32* s,
                                             U indx1, U indx2, U indx3);

void vcPutLogicArrElemVec32 (svHandle d, svLogicVec32* s, U indx1, ...);
void vcPutLogicArrElem1Vec32(svHandle d, svLogicVec32* s, U indx1);
void vcPutLogicArrElem2Vec32(svHandle d, svLogicVec32* s, U indx1, U indx2);
void vcPutLogicArrElem3Vec32(svHandle d, svLogicVec32* s,
                                                 U indx1, U indx2, U indx3);

/* canonical <-- actual */
void vcGetBitArrElemVec32 (svBitVec32* d, svHandle s, U indx1, ...);
void vcGetBitArrElem1Vec32(svBitVec32* d, svHandle s, U indx1);
void vcGetBitArrElem2Vec32(svBitVec32* d, svHandle s, U indx1, U indx2);
void vcGetBitArrElem3Vec32(svBitVec32* d, svHandle s,
                                             U indx1, U indx2, U indx3);

void vcGetLogicArrElemVec32 (svLogicVec32* d, svHandle s, U indx1, ...);
void vcGetLogicArrElem1Vec32(svLogicVec32* d, svHandle s, U indx1);
void vcGetLogicArrElem2Vec32(svLogicVec32* d, svHandle s, U indx1, U indx2);
void vcGetLogicArrElem3Vec32(svLogicVec32* d, svHandle s,
                                                  U indx1,U indx2, U 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.

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

svBit vcGetBitArrElem (svHandle s, U indx1, ...);
svBit vcGetBitArrElem (svHandle s, U indx1);
svBit vcGetBitArrElem (svHandle s, U indx1, U indx2);
svBit vcGetBitArrElem (svHandle s, U indx1,U indx2, U indx3);

svLogic vcGetLogicArrElem(svHandle s, U indx1, ...);
svLogic vcGetLogicArrElem(svHandle s, U indx1);
svLogic vcGetLogicArrElem(svHandle s, U indx1, U indx2);
svLogic vcGetLogicArrElem(svHandle s, U indx1,U indx2, U indx3);

void vcPutLogicArrElem(svHandle d, svBit value, U indx1, ...);
void vcPutLogicArrElem(svHandle d, svBit value, U indx1);
void vcPutLogicArrElem(svHandle d, svBit value, U indx1, U indx2);
void vcPutLogicArrElem(svHandle d, svBit value, U indx1,U indx2, U indx3);

void vcPutBitArrElem (svHandle d, svLogic value, U indx1, ...);
void vcPutBitArrElem (svHandle d, svLogic value, U indx1);
void vcPutBitArrElem (svHandle d, svLogic value, U indx1, U indx2);
void vcPutBitArrElem (svHandle d, svLogic value, U indx1,U indx2, U 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 */
void *svGetBitArrayPtr(svHandle); /* element is packed bit */
void *svGetLogicArrayPtr(svHandle); /* element is packed logic */
void *svGetArrayPtr(svHandle); /* element is of other type */

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

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

void *svGetBitArrElemPtr(svHandle, U indx1, ...);

      /* specialized versions for 1-, 2- and 3-dimensional arrays: */
void *svGetBitArrElemPtr1(svHandle, U indx1);
void *svGetBitArrElemPtr2(svHandle, U indx1, U indx2);
void *svGetBitArrElemPtr3(svHandle, U indx1, U indx2, U indx3);

void *svGetLogicArrElemPtr(svHandle, U indx1, ...);

      /* specialized versions for 1-, 2- and 3-dimensional arrays: */
void *svGetLogicArrElemPtr1(svHandle, U indx1);
void *svGetLogicArrElemPtr2(svHandle, U indx1, U indx2);
void *svGetLogicArrElemPtr3(svHandle, U indx1, U indx2, U indx3);

void *svGetArrElemPtr(svHandle, U indx1, ...);

      /* specialized versions for 1-, 2- and 3-dimensional arrays: */
void *svGetArrElemPtr1(svHandle, U indx1);
void *svGetArrElemPtr2(svHandle, U indx1, U indx2);
void *svGetArrElemPtr3(svHandle, U indx1, U indx2, U 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 triple i);

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

        foo(a_10x5);
        foo(a_64x8);

C:
        #include "sverilog.h"

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

        void foo(svHandle h)
        {
          MyType my_value;
          int i, j;
          int lo1 = svUnpackedLow(h, 1);
          int hi1 = svUnpackedHigh(h, 1);
          int lo2 = svUnpackedLow(h, 2);
          int hi2 = svUnpackedHigh(h, 2);

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

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



This archive was generated by hypermail 2b28 : Fri Dec 13 2002 - 17:30:34 PST