Re: DirectC: C layer


Subject: Re: DirectC: C layer
From: Michael Rohleder (michael.rohleder@motorola.com)
Date: Tue Dec 10 2002 - 10:30:59 PST


Some very initial comments, more details will follow when I have really understood it:

a) Thanks for this work, I like the overall thinking and would like to thank you for doing this effort
b) I like the split into binary and source compatibility for the include files, but I don't like the include file names.
   Instead I would suggest "svc_binlevel.h" and svc_srclevel.h". But this is of course just a minor problem.
c) We need to say something about memory handling; at least for strings. Who is owning the memory for a
   string parameter and how this has to be modified in case of modifications.
   [Assume you have an inout string, initialized by SV to "Andrzej", and I want to overwrite it with "Swapnajit",
     how do I handle the additional two characters needed for the newer string ??? Or in case I have an output string,
     who is responsible for allocating the memory ??? Or in case of an input parameter what is the lifetime of the
     corresponding data ???]
d) I would like to see the const being part of the mapping described for input parameters ... And, again, is is part of
   the linking, at least for some compilers ...
e) Since arrays are always starting at 0, it might be possible to map a function with a parameter logic [15:8] and a
   second function with a parameter logic [7:0] to a single C function (althought the extern definitions on the SV side
   are _intentionally_ different here). Do we want to have this, is this O.K., and what would be the implications ?
   At least one is that there is a need to have a function to retrieve the _actual_ range of an array ...
f) You need to define whether an array starts at the msb or at bit 0, if you are settling upon the syntax in your proposal
   (so what is the mapping between the first element on the SV side and the element 0 on the C side. Think about
    cases like logic [7:0] and logic [0:7])
g) I would like to have a function that is able to _directly_ manipulate a single bit of a Vector (having size > 32 bit).
   When I just want to modify a single or a few bits, I don't want to fiddle around with all this stuff.

That's all for now, there will be surely more.

Regards,
-Michael

Andrzej Litwiniuk wrote:

> Team,
>
> As promised, I'm sending the proposal for the C layer of the interface.
>
> The proposal is unfinished. This is the best I managed to do before
> the deadline Friday midnight PST (technically speaking, I still have
> 15 minutes :-)
>
> I hope this could be a base for a complete solution.
>
> Regards,
> Andrzej
>
> ----------------------------------------------------------------------------
>
> C layer of SV DirectC Interface
> -------------------------------
>
> Preface.
> ========
>
> The enclosed proposal addresses only restricted a subset of SV types.
> I failed to find/invent a solution that would be efficient and general at
> the same time.
>
> The proposed solution offers very efficient access, with no or very little
> overhead, although only for restricted a subset of types.
>
> I believe that such approach seems to be justified by the requirements
> for DirectC interface. Should a general solution be used, VPI or PLI
> may serve as the last resort.
>
> Let me start with presenting the reasoning that has led to the proposed
> solution.
>
> It's obvious that for each SV data type passed from SV to C, the matching
> C type has to be used in C code, if that data is to be directly accessed
> in C. An abstract access would also require a similar mapping, though perhaps
> a simpler one.
>
> The DirectC interface or an implementation, or both, must define the mapping
> from SV datypes onto C types. (The reverse mapping is by and large easier,
> assuming the existance of generic pointers.)
>
> Consider the following structure:
>
> struct {
> int a;
> T b; /* T is a data type */
> int C;
> }
>
> A compiler cannot process such a type and determine the relative offset of 'b'
> without knowing at least the size of 'T'.
>
> So, if the above structure is defined in SV, what should be the corresponding
> data type to be used in C?
>
> The answer is simple and obvious if the type 'T' has a natural mapping onto
> some C type, like the basic types 'int', 'byte' or 'real'.
>
> But what is the "natural mapping" for, say, 'logic [2:3][1:3][2:0] b [1:10]',
> i.e. an unpacked 10-element array of packed array 2 by 3 by 3 bits, 4-state
> each?
> A single element of unpacked array is 18 bits; how many bytes or words
> will it take to represent it? Verilog simulator very likely will use 2*3 bytes
> per each 18-bit element of an array; C implementation would rather use 2 words
> per element.
>
> So the key question is what to do with SV specific data types?
>
> A few solutions have been proposed, but none of them seems satisfactory
> and working.
>
> For example, SV compiler might generate C types for SV types (similarly
> to VCS generating headers for the external functions).
> This would solve the problem of writing a matching declaration in C; such
> declaration would be automatically generated.
> (Note the use model: user will have to start with a SV definition and then
> use a SV compiler in order to get the corresponding C definition.)
> This would not help, however, with accessing a packed part of an element
> in C code. (C does not support multi-indexing on bits level.)
>
> Another discussed solution is to standarize the representation.
>
> Any standarization of the internal data representation used by a simulator
> will sacrify the performance.
> May I here recall that we accepted 13c from "17 items"?
> [ 13c: "The layout of 2- or 4-state vectors (i.e. packed structs and arrays)
> is implementation- and platform- dependent. ]
>
> So instead we might standarize the representation visible to the C user,
> by introducing something like avalue/bvalue known from PLI.
> Actually, this idea is partly employed in my proposal.
>
> But again, what would be the "standard" representation for the example of array
> considered above?
>
> Yet another approach is to replace troublesome SV-specific data types
> with a handle and use the abstract access mode to access such troublesome data
> solely thru a handle.
>
> With that approach the structure
>
> 'struct { int a; T b; int c; }', where T is a troublesome data type
>
> would be seen in C as
>
> 'struct { int a; sv_handle b; int c; }'
>
> where sv_handle is a pointer to some descriptor of the value of type T.
> A descriptor could be standarized or left to vendors.
>
> Unfortunately, this will not work for calling SV functions from C.
> The actual arguments exist on the caller's side and it's the caller
> who creates them. How would the caller in C code create a handle for SV data
> object and how such object would be created in C?
>
> Sure, there may be some conceivable solutions. For example, if SV code exports
> a function, then SV compiler might also provide constructor functions, to be
> called from C, for creating handles for those involved types of arguments that
> require a handle.
> But such solution's going to be pretty complicated and the use model may got
> confusing.
>
> Either approach, i.e. a standarized API representation or a handle, will
> require the translation between the two representations: the one used by
> a simulator and the other one visible to C.
> Such translation may be quite expensive, if an array of structures is passed.
>
> Let me summarize the downsides of the above solutions:
>
> - both approaches will impose an overhead
> - standarized API representation will not help with complex SV types
> - handle will not work for calling SV functions from C
>
> Having said that, I propose a modest yet pragmatic solution.
> (It's pragmatic because it's doable :-)
>
> Overview of C layer
> ===================
>
> Only restricted and 'normalized' SV specific types will be supported.
>
> For example, if 'logic [2:3][1:3][2:0] b [1:10]' is used in SV type,
> it will have to be defined in C as if it were declared in SV in the following
> normalized form: 'logic [17:0] b [0:9]'.
> That practically means that the packed part must be linearized and the ranges
> must be normalized.
> (Well, perhaps the range normalization requirement could be relaxed.)
>
> By and large the actual arguments will be passed by reference, with a few
> exceptions (e.g. small input arguments).
>
> There will be no copying of arguments (other than resulting from coercing)
> Please recall item 10 from "17 items"!
> [10a: "xf must not modify the values of its input args'
> 10b: "The initial values of formal output args are unspecified and may be
> implementation dependent."]
>
> The actual arguments passed by reference by and large will be passed as they are, without changing their representation from the one used by a simulator.
> (Again, there are some exceptions, mainly for the 'open' alias 'unsized' arrays.)
>
> Therefore there will be no overhead on argument passing because no copying or
> translation between different representations will be required.
>
> C data types will be directly accessible.
>
> SV specific types will be accessible both via the interface library functions,
> what grants the compatibility, and directly thru pointers, what allows for
> the simulator-specific tuning of the application.
>
> DirectC interface defines the canonical API representation of packed 2-state
> and 4-state arrays. (Actually based on PLI's avalue/bvalue for 4-state.)
>
> Library functions will provide the translation between the representation
> used in a simulator and the canonical API representation.
>
> 'Open' alias 'unsized' arrays will be accessible through the abstract access
> mode, i.e. via the interface library functions.
>
> Depending on the data types used for the external (or exported) functions,
> either binary level or C source level compatibility is granted.
>
> The binary level compatibility is granted for all data types that do not mix
> C types with SV specific types, though either category separately is fine.
> For example, if a formal argument type is a C structure or a packed array
> of bit or logic, then binary level compatibility is granted.
> On the other hand, if a packed structure is embedded in an unpacked data
> type, then only a source level compatibility is granted.
> (Binary level compatibility means that an application compiled for a given
> platform shall work with every SV simulator on that platform.
> Source level compatibility means that an application will have to be re-compiled
> for each SV simulator and that the implementation specific definitions
> will be required for the compilation.)
>
> Data type mapping
> =================
>
> The basic SV data types will be represented as follows:
>
> int -> int
> real -> double
> shortreal -> float
>
> etc. (Actually, LRM shall provide a complete list.)
>
> SV specific data types like packed bit and logic vectors, will be discussed
> separately.
>
> Argument passing
> =================
>
> Actual arguments generally are passed by reference or by value and will
> be directly accessible in C code.
>
> In some cases, defined separately, an argument will be passed by handle and will
> be accessible via library functions (abstract acess mode).
>
> For the arguments passed by reference, their original simulator-specific
> representation will be used and a reference to the original data object
> will be passed.
>
> If an argument of type 'T' is passed by reference, than the formal argument
> shall be of the type 'T *'.
>
> Output and inout arguments are passed by reference.
>
> Input arguments are passed by value or by reference, depending on the size.
> 'Small' values of formal input arguments are passed by value.
> The following data types are considered 'small':
>
> - char, byte, int, real, shortreal (have I omitted something?)
> - pointer, string
> - bit (i.e. 2-state) vectors up to 32-bit; canonical representation will
> be used, similarly for function result
>
> Input arguments of other types are passed by reference.
>
> Include files
> =================
>
> (All names are provisional and subject to discussion and improvment.)
>
> The C layer of SV DirectC interface defines two include files corresponding to
> the two levels of compatibility (binary level and source code level):
> - sverilog.h
> - directc.h
>
> "sverilog.h" is fully defined by the interface and is implementation independent.
> It defines the canonical API representation of 2-state (bit) and 4-state (logic)
> values, defines the types used for passing references to SV data objects,
> provides function headers and defines a number of helper macros and constants.
>
> "directc.h" provides implementation dependent definitions.
> The contens of this file, i.e. what symbols are defined (constants, macros,
> typedefs), is defined by the interface.
> The actual definitions of the symbols, however, are implementation specific and
> will be provided by the vendors.
> "directc.h" defines data structures for implementation specific representation of
> 2-state and 4-state vectors, as well as a number of helper macros and constants.
>
> User's applications that require "directc.h" file will be only source-level
> compatible, i.e. they will have to be compiled with the version of "directc.h"
> provided for a particular implementation of SV.
>
> The applications that use only "sverilog.h" will be binary compatible with
> all SV simulators.
>
> The values of C-like types may be directly accessed via the corresponding
> C type definitions.
>
> The values of SV specific types, like packed arrays of bit or logic, may
> be accessed via interface functions using the canonical representation of
> 2-state and 4-state vectors.
> They also may be directly accessed using the implementation representation.
> The former mode will assure binary level compatibility, the later one
> will allow for tool-specific performance oriented tuning of an application.
>
> There will be no confusion whether passing a particular data type
> is binary compatible or only source level compatible.
> The rule is straightforward: if a correcponding type definition can be
> written in C without the need to include "directc.h" file, then the binary
> compatibility is granted. Everything that requires "directc.h" is not binary
> compatible and needs recompilation for each simulator of choice.
>
> Applications that pass solely C compatible data types or standalone packed arrays
> (both 2-st and 4-st) will require only "sverilog.h" and therefore will be binary
> compatible will all simulators.
>
> Applications that pass complex data types that contain at the same time
> packed arrays and C-compatible types, will require also "directc.h" file and
> therefore will not be binary compatible will all simulators. The source level
> compatibility is, however, granted.
>
> "sverilog.h"
> =================
>
> This file contains the following definitions:
>
> /* canonical API representation */
>
> #define sv_0 0
> #define sv_1 1
> #define sv_z 2 /* representation of 4-st scalar z */
> #define sv_x 3 /* representation of 4-st scalar x */
>
> typedef unsigned char svBit; /* scalar */
> typedef unsigned char svLogic; /* scalar */
>
> /* 2-state and 4-state vectors, modelled upon PLI's avalue/bvalue */
> #define VEC32_NEEDED(WIDTH) (((WIDTH)+31)>>5)
>
> typedef unsigned int
> svBitVec32; /* (a chunk of) packed bit array */
>
> typedef struct { unsigned int c; unsigned int d;}
> svLogicVec32; /* (a chunk of) packed logic array */
>
> /* reference to a standalone packed array */
> typedef void* svBitPackedArr;
> typedef void* svLogicPackedArr;
>
> /* a handle to a generic object (actually, unsized array) */
> typedef void* svHandle;
>
> /* functions for translation between simulator's and canonical representations */
>
> /* s=source, d=destination, w=width */
>
> /* actual <-- canonical */
> void vcPutBitVec32 (svBitPackedArr d, svBitVec32* s, int w);
> void vcPutLogicVec32 (svLogicPackedArr d, svLogicVec32* s, int w);
>
> /* canonical <-- actual */
> void vcGetBitVec32 (svBitVec32* d, svBitPackedArr s, int w);
> void vcGetLogicVec32 (svLogicVec32* d, svLogicPackedArr s, int w);
>
> 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.
>
> More functions may be added, for accesing individual bits or small (<=32)
> part-selects.
>
> Similarly, functions for converting packed arrays into char* strings (for
> printing) or other way round (for reading) may be provided, like in VCS
> (cf. VCS DirectC.h).
>
> "directc.h"
> ===========
>
> This file provides implementation specific definitions.
> In particular, it defines the macros for specifying variables representing
> SV packed arrays:
>
> #define BIT_PACKED_ARRAY(WIDTH,NAME) ...
> #define LOGIC_PACKED_ARRAY(WIDTH,NAME) ...
>
> (For example, VCS might defined the later macro as follows:
> #define LOGIC_PACKED_ARRAY(WIDTH,NAME) vec32 NAME [ VEC32_NEEDED(WIDTH) ]
> )
>
> Example 1 - binary compatible application
> =========================================
>
> SV:
> typedef struct {int a; int b;} pair;
> extern void foo(input int i1, pair i2, output logic [63:0] o3);
>
> C:
> #include "sverilog.h"
>
> typedef struct {int a; int b;} pair;
> void foo(int i1, pair *i2, svLogicPackedArr o3)
> {
> svLogicVec32 arr[VEC32_NEEDED(64)]; /* 2 chunks needed */
>
> printf("%d\n", i1);
> arr[1].c = i2->a;
> arr[1].d = 0;
> arr[2].c = i2->b;
> arr[2].d = 0;
> vcPutLogicVec32 (o3, arr, 64);
> }
>
> Example 2 - source level compatible application
> =========================================
>
> SV:
> typedef struct {int a; bit [6:1][1:8] b [65:2]; int c;} triple;
> // troublesome mix od C types and packed arrays
> extern void foo(input triple i);
>
> C:
> #include "sverilog.h"
> #include "directc.h"
>
> typedef struct {
> int a;
> BIT_PACKED_ARRAY(6*8, b) [64];
> int c;
> } triple;
>
> /* Note that 'b' is defined as for 'bit [6*8-1:0] b [63:0]' */
>
> void foo(triple *i)
> {
> int j;
> svBitVec32 arr[VEC32_NEEDED(6*8)]; /* 6*8 packed bits */
>
> printf("%d %d\n", i->a, i->c);
> for (j=0; j<64; j++) {
> vcGetBitVec32(arr, (svBitPackedArr)&(i->b[j]), 6*8);
> ...
> }
> }
>
> Note that 'a', 'b', 'c' are directly accessed as fields in a structure.
> In the case of 'b', which represents unpacked array of packed arrays,
> individual element is accessed via library function vcGetBitVec32(),
> by passing its address to the function.
>
> ---------------------------------------------------------------------------
>
> This is all that I managed to describe before midnight PST, Friday.
>
> The representation of open/unsized arrays and access to them (via handle,
> abstract access mode) is still missing.
>
> I suppose that the functions for accessing arrays may be modelled upon SV array
> querying functions: $left, $right, $dimension, etc.

--

NOTE: The content of this message may contain personal views which are not neccessarily the views of Motorola, unless specifically stated.

___________________________________________________ | | _ | Michael Rohleder Tel: +49-89-92103-259 | _ / )| Software Technologist Fax: +49-89-92103-680 |( \ / / | Motorola, Semiconductor Products, System Design | \ \ _( (_ | _ Schatzbogen 7, D-81829 Munich, Germany _ | _) )_ (((\ \>|_/ > < \_|</ /))) (\\\\ \_/ / mailto:Michael.Rohleder@motorola.com \ \_/ ////) \ /_______________________________________________\ / \ _/ \_ / / / \ \

The information contained in this email has been classified as: Motorola General Business Information (x) Motorola Internal Use Only ( ) Motorola Confidential Proprietary ( )

*** This note may contain Motorola Confidential Proprietary or Motorola Internal Use Only Information and is intended to be reviewed by only the individual or organization named above. If you are not the intended recipient or an authorized representative of the intended recipient, you are hereby notified that any review, dissemination or copying of this email and its attachments, if any, or the information contained herein is prohibited. If you have received this email in error, please immediately notify the sender by return email and delete this email from your system. Thank you! ***




This archive was generated by hypermail 2b28 : Tue Dec 10 2002 - 10:44:21 PST