Re: DirectC C layer - open arrays and portability


Subject: Re: DirectC C layer - open arrays and portability
From: Andrzej Litwiniuk (Andrzej.Litwiniuk@synopsys.com)
Date: Tue Jan 14 2003 - 18:39:56 PST


Kevin's comments followed by my answers or comments.

Andrzej

> > Example 4 - open array
> > ======================
> >
> > SV:
> > typedef struct { ... } MyType;
> >
> > extern void foo(input MyType i [], output MyType o []);
> >
> > MyType source [11:20];
> > MyType target [11:20];
> >
> > foo(source, target);
> >
> > C:
> > #include "svc_bin.h"
> >
> > typedef struct ... } MyType;
> >
> > void foo(svHandle hin, svHandle hout)
> > {
> > int count = svUnpackedLength(hin, 1);
> > MyType *s = (MyType *)svGetArrayPtr(hin);
> > MyType *d = (MyType *)svGetArrayPtr(hout);
> >
> > if (s && d) { /* both arrays have C layout */
> >
> > /* an efficient solution using poiter arithmetics */
> > while (count--)
> > *d++ = *s++;
> >
> > /* even more efficient:
> > memcpy(d, s, svSizeOfArray(hin));
> > */
> >
> KEVIN:
> That's OK except you probably need a additional call to indicate data
> has changed, but..

Nope. SV side must assume for each output or inout argument, that the value
may change and is responsible for detecting such a change.

> > } else { /* less efficient yet implementation independent */
> >
> > int i = svUnpackedLow(hin, 1);
> > int j = svUnpackedLow(hout, 1);
> > while (i <= svUnpackedHigh(hin, 1)) {
> > *(MyType *)svGetArrElemPtr1(hout, j++) =
> > *(MyType *)svGetArrElemPtr1(hin, i++);
>
> KEVIN:
> You can't do that without knowing the size/layout of MyType,

You are absolutely right. That's why C code in this example contains
the definition of the structure MyType.

> it is therefore
> not vendor independent. You cannot dereference a vendor specific type in
> the user code and have it be portable.

Right. So in the worst case scenario the above code will be only source-level
compatible, cf. example 2.
Note however, that this may happen only when SV specific types are mixed with
C compatible types, e.g. when packed arrays are embedded in structures.
When types are not mixed yet vendor specific types are used (packed arrays),
portability (i.e. binary level compatibility) may be achieved by using
the canonical representation.
See the following example (derived from example 4):

SV:
        extern void foo(input bit [63:0] i [], output bit [63:0] o []);

        bit [63:0] source [11:20];
        bit [63:0] target [11:20];

        foo(source, target);

C:
        #include "svc_bin.h"

        void foo(const svHandle hin, svHandle hout)
        {
          svBitVec32 arr[VEC32_NEEDED(64)]; /* canonical repr. */

          int i = svLow(hin, 1);
          int j = svLow(hout, 1);

          while (i <= svHigh(hin, 1)) {
             svGetBitArrElem1Vec32(arr, hin, i++);
             svPutBitArrElem1Vec32(hout, arr, j++);
          }
        }

> KEVIN:
> You need to return a void pointer/handle
> and pass it back for the assignment e.g.:
>
> void *ptr = svGetArrElemPtr1(hout, j++);
> svPutArrElemPtr1(ptr,hin, i++);

Instead of that, I may go thru canonical representation, as in the example
above.

> KEVIN:
> If you want to keep copies of data in user space you need to know the size of
> the item and/or use malloc/free e.g.:

 - unless the size is statically known.

> KEVIN:
>
> char buff[svSizeOfArrElem1(hout)]; // GNU C
> bcopy(svGetArrElemPtr1(hout, j++),buff,sizeof(buff));
> svPutArrElemPtr1(ptr,hin, i++);
> or:
> void *ptr = svGetCopyArrElemPtr1(hout, j++);
> svPutArrElemPtr1(ptr,hin, i++);
> svFree(ptr);
>
>
> NB: One simulator may have multiple ways of storing the same data.
>
> Kev.



This archive was generated by hypermail 2b28 : Tue Jan 14 2003 - 18:40:34 PST