[sv-cc] Calling SV from C


Subject: [sv-cc] Calling SV from C
From: Francoise Martinolle (fm@cadence.com)
Date: Wed Feb 05 2003 - 08:54:03 PST


Andrzej,

I don't understand section 5.2 calling SV functions from C:

"Note that the functions exported from SV may not have open arrays as
arguments.
Otherwise the same types of formal arguments may be declared in SV both for
the exported functions and for the external functions.
A function exported from SV will have the same function header as the external
function with the same function result type and same formal argument list."

My understanding was that there is an export declaration of the SV function
in the Verilog
code.
There must also be an extern function declaration in C indicating that this
function is extern to the C file.
The formal arguments types, modes and argument passing of the C function
extern declaration must comply with the rules which were defined for a SV
function calling a directC function.
Therefore the user declare this function and determine the matching types
to the Verilog function
data types.

Example:
typedef struct {int i; double r;} complex;
export logic [15:0] myfunc (input int address, output logic [31:0] r, input
T complex)

The extern function declaration which will be used would be:
extern SVlogicVec32 myfunc (int address, SVlogicVec32 *r, T *complex)
address is passed by value, r is passed by reference, complex is passed by
reference, the function
return is a 32 bit logic struct.

Correct?
If I am not understanding this correctly, please explain and or reword
section 5.2

Another question I have is what would be the C matching type of a output SV
function
argument which is output logic r[31:0]; (unpacked array of 32 elements, 1
bit wide).

Francoise
        '

At 11:28 AM 2/4/2003 -0500, Andrzej Litwiniuk wrote:
>Hi all,
>
>Enclosed is the revised and almost final revision of DirectC C Layer.
>I'll send a decently formatted .pdf file asap.
>
>This most recent version has been deeply re-structured. Here are the most
>important technical changes:
> - new chapter "Semantical Constraints"
> - renamed files "svc.h", "svc_src.h"
> - renamed types svBitPackedArrRef, svLogicPackedArrRef
> - new functions svSizeOfLogicPackedArr(), svSizeOfBitPackedArr()
> - corrected types in functions for bit select, part select
>
>What is still missing: comments on the (undetermined) contents of unused bits.
>
>
>Thanks,
>Andrzej
>
>
>------------------------ DirectC C Layer
>--------------------------------------
>
>--------------------------------------------------------------
>Table of Contents
>1. Overview
> 1.1 Naming convention
>2. Portability
> 2.1 Binary compatibility
> 2.2 Source level compatibility
> 2.3 Include files
> 2.4 "svc.h" include file
> 2.5 "svc_src.h" include file
>3. Semantical Constraints
> 3.1 Types of formal arguments
> 3.2 Input Arguments
> 3.3 Output Arguments
> 3.4 Value changes for output and inout arguments
> 3.5 'Context' and non-'context' functions
> 3.6 'Pure' functions
> 3.7 Memory management
>4. Data Types
> 4.1 Limitations
> 4.2 Duality of types: SV types vs. C types
> 4.3 Assumed Data Representation
> 4.4 Basic Types
> 4.5 Normalized Ranges
> 4.6 Mapping between SV ranges and normalized ranges
> 4.7 Canonical representation of packed arrays
>5. Argument passing modes
> 5.1 Overview
> 5.2 Calling SV functions from C
> 5.3 Argument passing by value
> 5.4 Argument passing by reference
> 5.4.1 Allocating actual arguments for SV specific types.
> 5.5 Argument passing by sv_handle - Open Arrays
> 5.6 Input arguments
> 5.7 Inout and output arguments
>6. Include files
> 6.1 Binary compatibility include file "svc.h"
> 6.1.1 scalars of type 'bit' and 'logic'
> 6.1.2 Canonical representation of packed arrays
> 6.1.3 Implementation dependent representation
> 6.1.4 Translation between actual representation and canonical
> representation
> 6.2 Source level compatibility include file "svc_src.h"
>7. Arrays
> 7.1 Multidimensional arrays
> 7.2 Direct access to unpacked arrays
> 7.3 Access to packed arrays via canonical representation
> 7.4 Bit selects
> 7.5 Part selects
>8. Open Arrays
> 8.1 Actual ranges
> 8.2 Array querying functions
> 8.3 Access functions
> 8.4 Access to the actual representation
> 8.5 Access via canonical representation
> 8.6 Access to scalars ('bit' and 'logic')
> 8.7 Access to array elements of other types
>--------------------------------------------------------------
>
>
>1. Overview
>
>This document describes the C layer of DirectC Interface and applies to calls
>from either direction, both for C functions called from System Verilog code
>and for exported System Verilog functions called from C code.
>
>System Verilog DirectC Interface supports only System Verilog data types
>and they are the sole data types that may cross the boundary between System
>Verilog and a foreign language in either direction (i.e. when a foreign
>function
>is called from SV code or when exported SV function is called from a foreign
>code).
>
>On the other hand, the data types used in C code must be C types.
>Hence the duality of types. A value that is passed through DirectC Interface
>is specified in SV code as a value of SV type, while the same value must be
>specified in C code as a value of C type.
>Therefore passing a value through DirectC Interface takes a pair of matching
>type definitions: SV definition and C definition.
>It is user's responsibility to provide such matching definitions.
>A tool (SV compiler) may facilitate this by generating C type definitions for
>SV definitions used in DirectC interface for external and exported functions.
>
>Some SV types are directly compatible with C types and defining a matching C
>type for them is pretty straightforward.
>There are, however, SV specific types, namely packed types (arrays,
>structures,
>unions), 2-state or 4-state, that have no natural correspondence in C.
>DirectC does not require any particular representation of such types
>and thus does not impose any restrictions on SV implementation. This allows
>implementors to chose the layout and representation of packed types that
>best suits the simulation performance.
>
>While not specifying the actual representation of packed types, the C
>layer of
>DirectC defines the canonical representation of packed 2-state and 4-state
>arrays. This canonical representation is actually based on Verilog legacy
>PLI's
>avalue/bvalue representation of 4-state vectors.
>Library functions provide the translation between the representation used in
>a simulator and the canonical representation of packed arrays.
>There are also functions for bit selects and limited part selects for packed
>arrays, that do not require the use of the canonical representation.
>
>Generally, normalized ranges are assumed for accessing SV arrays.
>Normalized ranges mean [n-1:0] indexing for the packed part (packed arrays
>are
>restricted to 1 dimension), and [0:n-1] indexing for a dimension in the
>unpacked
>part of an array.
>The open arrays, however, are accessed using the original ranges as
>defined for
>the actual arguments in SV and the same indexing as it would have been
>used in
>SV.
>
>Formal arguments in SV may be specified as open arrays solely in the external
>declarations; exported SV functions may not have formal arguments
>specified as
>open arrays. The term "open array" refers to the fact that a range of one or
>more dimensions of a formal argument is unspecified (what is denoted in SV by
>"[]").
>This is solely a relaxation of argument matching rules. An actual argument
>will
>match the formal one regardless of its range(s) for the corresponding
>dimension(s).
>This allows to write in C a more general code that may handle SV arrays of
>different sizes.
>
>The function arguments are generally passed by some form of a reference, with
>the exception of small values of SV input arguments, which are passed by
>value.
>
>All types of formal arguments but open arrays are passed either by direct
>reference or by value and therefore are directly accessible in C code.
>Passing such arguments incurs virtually no overhead.
>
>Formal arguments declared in SV as open arrays are passed by a handle, see the
>type 'svHandle', and are accessible via library functions. Array querying
>functions are provided for open arrays.
>
>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
>SV packed and unpacked types. Open arrays with both packed and unpacked part
>are, however, the allowed exception.
>
>If a data type that mixes SV packed and unpacked types is used, then C code
>must be re-compiled using the implementation dependent definitions provided by
>the vendor.
>
>The C layer of DirectC Interface provides two include files. The main include
>file "svc.h" is implementation independent and defines the canonical
>representation, all basic types and all interface functions.
>The second include file, svc_src.h" defines only the actual representation of
>packed arrays and hence its contents is implementation dependent.
>The applications that do not need include this file are binary level
>compatible.
>
>1.1 Naming convention
>
>All names defined in this interface are prefixed with "sv".
>
>Function and type names start with "sv" followed by Capitalized words with
>no separators, e.g. svBitPackedArrRef.
>
>Names of symbolic constants start with "sv_", e.q. sv_x.
>
>Names of macro definitions start with "sv_" followed by all capitalized
>words separated by "-", e.g. sv_CANONICAL_SIZE.
>
>
>2. Portability
>
>Depending on the data types used for the external (or exported) functions,
>C code may be either binary level or source level compatible.
>
>The applications that do not use SV packed types are always binary compatible.
>
>Applications that don't mix SV packed and unpacked types in the same data
>type
>may always be written in a way that will guarantee the binary compatibility.
>Open arrays with both packed and unpacked part don't breach the binary
>compatibility.
>
>The values of SV packed types may be accessed either solely via interface
>functions using the canonical representation of 2-state and 4-state packed
>arrays, or they also may be accessed directly thru pointers 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
>though it will require recompilation with the implementation dependent
>definitions provided by the vendor and shipped with the simulator.
>
>
>2.1 Binary compatibility
>
>Binary compatibility means that an application compiled for a given platform
>shall work with every SV simulator on that platform.
>
>
>2.2 Source level compatibility
>
>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.
>
>
>2.3 Include files
>
>The C layer of SV DirectC Interface defines two include files
>corresponding to
>the two levels of compatibility: "svc.h" and "svc_src.h".
>
>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 corresponding type definition can be
>written in C without the need to include "svc_src.h" file, then the binary
>compatibility is granted. Everything that requires "svc_src.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-state and 4-state) will require only "svc.h" and therefore
>will
>be binary compatible will all simulators.
>
>Applications that use complex data types that are constructed both of SV
>packed arrays and C-compatible types, will require also "svc_src.h" file and
>therefore will not be binary compatible will all simulators. The source level
>compatibility is, however, granted.
>
>2.4 "svc.h" include file
>
>This is the main include file needed by all applications that use DirectC
>interface with C code.
>"svc.h" is fully defined by the interface and is implementation independent.
>It defines the canonical 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.
>
>The applications that use only "svc.h" will be binary compatible with all SV
>simulators.
>
>
>2.5 "svc_src.h" include file
>
>This is the auxiliary include file.
>"svc_src.h" defines data structures for implementation specific
>representation
>of 2-state and 4-state SV packed arrays.
>The contens of this file, i.e. what symbols are defined is specified by the
>interface.
>The actual definitions of those symbols, however, are implementation specific
>and will be provided by the vendors.
>
>User's applications that require "svc_src.h" file will be only source-level
>compatible, i.e. they will have to be compiled with the version of "svc_src.h"
>provided for a particular implementation of SV.
>
>
>3. Semantical Constraints
>
>3.1 Types of formal arguments
>
>The principle "What You Specify Is What You Get" guarantees the types of
>formal
>arguments of external functions. For open arrays some ranges may remain
>unspecified.
>
>The formal arguments other than open arrays are fully defined by the
>external declaration and therefore they are assumed to have ranges of
>packed or unpacked
>arrays exactly as specified in the external declaration.
>Only the declaration site (SV) of the external function is relevant for such
>formal arguments.
>
>The formal arguments defined as open arrays have the size and ranges of the
>actual argument, i.e. have the ranges of packed or unpacked arrays exactly
>as of
>the actual argument. The actual ranges of an open array are determined per
>call,
>hence the call sites of the external function are relevant for the formal
>arguments specified as open arrays.
>
>To be exact, the unsized ranges of open arrays are determined at a call site,
>the rest of type information is specified at the external declaration.
>So, if a formal argument is declared as 'bit [15:8] b []', then it is the
>external declaration that specifies that formal argument is an unpacked
>array of packed bit array with bounds 15 to 8, while the actual argument
>used at a particular call site defines the bounds for the unpacked part
>for that particular call.
>
>
>3.2 Input Arguments
>
>The formal arguments specified in SV as 'input' must not be modified.
>
>
>3.3 Output Arguments
>
>The initial values of formal arguments specified in SV as 'output' are
>undetermined and may be implementation dependent.
>
>
>3.4 Value changes for output and inout arguments
>
>There is neither a need nor the means to notify the caller that a value of
>a formal argument specified in SV as 'output' or 'inout' has change.
>SV simulator is responsible for handling the value changes for output and
>inout
>arguments. Such changes will be detected and handled after the control returns
>from C code to SV code.
>
>
>3.5 'Context' and non-'context' functions
>
>Only functions specified as 'context' in their corresponding SV external
>declarations may safely call functions from other APIs, including PLI and VPI
>functions, or exported SV functions.
>
>For functions not specified as 'context' the effects of calling PLI or VPI
>functions or SV functions are unpredictable and such calls may crash.
>
>3.6 'Pure' functions
>
>The functions specified as 'pure' in their corresponding SV external
>declarations must have no side effects whatsoever directly or indirectly.
>Their result must depend solely on the values of their input arguments.
>Specifically, such functions should not perform any file operations,
>not read or write anything, not access any persistent data like global or
>static
>variables.
>
>The user should assume that any call of 'pure' function in SV code may be
>removed by SV compiler optimizations.
>
>3.7 Memory management
>
>The memory spaces owned and allocated by C code and SV code are disjoined.
>Each side is responsible for its own allocated memory. Specifically, C code
>shall not free the memory allocated by SV code (or the SV compiler) nor
>expect
>that SV code will free the memory allocated by C code (or the C compiler).
>The above does not exclude scenarios in which C code allocates a block of
>memory, then passes a handle (i.e. a pointer) to that block to SV code,
>which in
>turn calls C function which directly (if it is the standard function
>'free') or
>indirectly frees that block.
>Note that in the above scenario a block of memory is allocated and freed
>in C code, even when standard functions 'malloc' and 'free' are called
>directly
>from SV code.
>
>
>4. Data Types
>
>4.1 Limitations
>
>The packed arrays are assumed to be always 1-dimensional.
>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.
>If the packed part of an array in the type of a formal argument in SV
>is specified as multi-dimensional, then the SV compiler linearizes it.
>
>Although the original ranges are generally preserved for open arrays, if
>the actual argument has multidimensional packed part of the array, the
>equivalent 1-dimensional packed array will be normalized.
>
>4.2 Duality of types: SV types vs. C types
>
>A value that crosses the DirectC Interface is specified in SV code as
>a value of SV type, while the same value must be specified in C code as a
>value
>of C type.
>Therefore each data type that is passed through DirectC Interface requires
>two matching type definitions: SV definition and C definition.
>It is user's responsibility to provide such matching definitions.
>Specifically, for each SV type used in the external declarations or export
>declarations in SV code, the user must provide the equivalent type definition
>in C.
>To be exact, the actual C definition must reflect the argument passing mode
>for the particular type of SV value and the direction (input, output, inout)
>of the formal SV argument.
>Specifically, for values passed by reference a generic pointer "void *"
>may be used (typedefed conveniently) without the knowledge of the actual
>representation of the value.
>
>
>4.3 Assumed Data Representation
>
>DirectC does not impose any additional restrictions on the representation of
>SV data types.
>
>The following is assumed about the representation of SV data:
>
>a) representation of packed types is implementation dependent
>
>b) basic integer and real data types are represented as defined in SV LRM 3.3,
> 3.4.2, see also "4.4 Basic Types" below.
>
>c) layout of unpacked structures is same as used by C compiler (SV LRM 3.7)
>
>d) layout of unpacked arrays, with the exception of actual arguments passed
> for formal arguments specified as open arrays, is same as used by C
> compiler;
> this includes arrays embedded in structures and the standalone arrays
> (i.e. not embedded in any structure)
>
> Note that this is a restriction imposed on the SV side of the interface!
> Depending on the implementation, a particular array may or may be not
> accepted as an actual argument for the formal argument which is a sized
> array (it will be always accepted for open array).
>
> A natural order of elements is assumed for each dimension in the layout of
> an unpacked array, i.e. elements with lower indices go first.
> In other words, for SV range [L:R], the element with SV index min(L,R)
> will
> have C index 0, and the element with SV index max(L,R) will have C index
> abs(L-R).
>
>e) layout of the unsized (aka open) standalone unpacked arrays
> is implementation dependent with the following restriction:
> an element of an array must have the same representation as
> individual a value of the same type, with the exception of scalars
> (bit or logic) and packed arrays as a type of an element.
> Hence array's elements other than scalars or packed arrays can be
> accessed via pointers similarly to individual values.
>
>
>Note that d) actually does not impose any restrictions on how unpacked arrays
>are implemented; it says only that an array that does not satisfy d)
>may not be passed as an actual argument for the formal argument which is
>a sized array; it may be passed, however, for unsized (i.e. open) array.
>Therefore, the correctness of an actual argument may be implementation
>dependent. Nevertheless an open array provides implementation independent
>solution. This seems to be a reasonable trade-off.
>
>
>4.4 Basic Types
>
>The following table defines the mapping between the basic SV data types
>and the corresponding C types:
>
>SV type C type
>------- ------
>char <-> char
>shortint <-> shortint
>int <-> int
>longint <-> long long
>byte <-> char
>real <-> double
>shortreal <-> float
>handle <-> void*
>string <-> char*
>
>The representation of SV specific data types like packed 'bit' and 'logic'
>arrays is implementation dependent and generally transparent to the user.
>Nevertheless, for the sake of performance, applications may be tuned for a
>specific implementation and make use of the actual representation used by
>that
>implementation; such applications will not be binary compatible, however.
>
>
>4.5 Normalized Ranges
>
>The packed arrays are assumed to be always 1-dimensional, the unpacked part of
>an array may have arbitrary number of dimensions.
>
>Normalized ranges mean [n-1:0] indexing for the packed part, and [0:n-1]
>indexing for a dimension of the unpacked part of an array.
>
>Normalized ranges are used for accessing all arguments but the open arrays.
>The canonical representation of packed arrays also uses normalized ranges.
>
>
>4.6 Mapping between SV ranges and normalized ranges
>
>The SV ranges for a formal argument specified as an open array are those of
>the actual argument for a particular call. Open arrays are accessible,
>however,
>using their original ranges and the same indexing as in SV code.
>
>For all other types of arguments, i.e. all arguments but open arrays, the SV
>ranges are defined in the corresponding SV external or export declaration.
>Normalized ranges are assumed for accessing such arguments in C code.
>The mapping between SV ranges and normalized ranges is defined as follows.
>
>First, if a packed part of an array has more than 1 dimension, it is
>linearized as specified by the equivalence of packed types.
>
>Then a packed array of range [L:R] will be normalized as [abs(L-R):0];
>its most significant bit will have a normalized index abs(L-R), and its least
>significant bit will have a normalized index 0.
>
>A natural order of elements is assumed for each dimension in the layout of
>an unpacked array, i.e. elements with lower indices go first.
>In other words, for SV range [L:R], the element with SV index min(L,R) will
>have C index 0, and the element with SV index max(L,R) will have C index
>abs(L-R).
>
>Note that the above range mapping from SV to C applies to calls made in both
>directions, i.e. SV-calls-C and C-calls-SV.
>
>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]'.
>
>
>4.7 Canonical representation of packed arrays
>
>DirectC interface defines the canonical representation of packed 2-state
>and 4-state arrays.
>This canonical representation is actually based on Verilog legacy PLI's
>avalue/bvalue representation of 4-state vectors.
>Library functions provide the translation between the representation used in
>a simulator and the canonical representation of packed arrays.
>
>A packed array is represented as an array of one or more elements, each
>element
>representing a group of 32 bits. See the types 'svBitVec32', 'svLogicVec32'.
>
>
>5. Argument passing modes
>
>5.1 Overview
>
>The function arguments are generally passed by some form of a reference, with
>the exception of small values of SV input arguments, which are passed by
>value.
>
>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.
>There will be no inherent copying of arguments (other than resulting from
>coercing). Therefore there will be no inherent overhead on argument passing
>because generally no copying or translation between different representations
>will be required.
>
>The access to packed arrays via the canonical representation will involve,
>however, arguments copying and hence will incur some overhead.
>Alternatively, for the sake of performance the application may be tuned for
>a particular tool and may access the packed arrays directly thru pointers
>using
>the implementation representation, what would of course defy the binary
>compatibility.
>Note that this provides some degree of flexibility and allows the user
>to control the trade-off of performance vs. portability.
>
>All types of formal arguments but open arrays are passed either by direct
>reference or by value and therefore are directly accessible in C code.
>Passing such arguments incurs virtually no overhead.
>
>Formal arguments declared in SV as open arrays are passed by handle, see the
>type 'svHandle', and are accessible via library functions.
>
>
>5.2 Calling SV functions from C
>
>There is no difference in argument passing between calls from SV to C and
>calls from C to SV.
>Note that the functions exported from SV may not have open arrays as
>arguments.
>Otherwise the same types of formal arguments may be declared in SV both for
>the exported functions and for the external functions.
>A function exported from SV will have the same function header as the external
>function with the same function result type and same formal argument list.
>In the case of arguments passed by reference, an actual argument to SV
>function
>called from C must be allocated on C side using the same layout of data
>as SV would use for that type of argument.
>
>5.3 Argument passing by value
>
>Only 'small' values of formal input arguments are passed by value.
>Also function results are directly passed by value.
>User must provide the C type equivalent to SV type of a formal argument,
>if an argument is passed by value.
>
>5.4 Argument passing by reference
>
>For the arguments passed by reference, their original simulator-defined
>representation will be used and a reference (a pointer) to the actual data
>object will be passed.
>
>The actual argument is usually allocated by a caller. The caller may also
>pass over a reference to the object already allocated somewhere else,
>for example, its own formal argument passed by reference.
>
>If an argument of type 'T' is passed by reference, than the formal argument
>shall be of the type 'T *'.
>However, packed arrays may be also passed using generic pointers 'void *'
>typedefed accordingly to 'svBitPackedArrRef' or 'svLogicPackedArrRef'.
>
>
>5.4.1 Allocating actual arguments for SV specific types.
>
>This is relevant only for calling (exported) SV functions from C code.
>The caller is responsible for allocating the actual arguments that are
>passed by reference.
>
>Statical allocation requires the knowledge of the relevant data type.
>If such a type involves SV packed arrays, their actual representation must
>be known to C code and hence file "svc_src.h" must be included what would
>deem the C code implementation-dependent and thus not binary compatible.
>
>Sometimes the binary compatibility may be achieved by using dynamic
>allocation.
>Functions 'svSizeOfLogicPackedArr()' and 'svSizeOfBitPackedArr()' provide
>the size of the actual representation of a packed array. The needed size
>may be used for the dynamic allocation of an actual argument, without
>compromising the portability. Such a technique will not work if a packed
>array is a part of another type.
>
>
>5.5 Argument passing by sv_handle - Open Arrays
>
>Arguments specified as open (unsized) arrays are always passed by a handle,
>regardless of direction of SV formal argument, and will be accessible via
>library functions.
>The actual implementation of a handle is simulator-specific and transparent
>to the user. A handle is represented by generic pointer 'void *' typedefed
>to 'sv_handle'.
>Arguments passed by handle should always have 'const' qualifier, because
>the user shall not modify the contents of a handle.
>
>5.6 Input arguments
>
>Input arguments should always have 'const' qualifier.
>
>Input arguments, with the exception of open arrays, 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, shortint, int, longint, real, shortreal
> - handle, string
> - bit (i.e. 2-state) packed arrays up to 32-bit; canonical
> representation will
> be used, similarly for function result
>
>Input arguments of other types are passed by reference.
>
>
>5.7 Inout and output arguments
>
>Inout and output arguments, with the exception of open arrays, are always
>passed
>by reference.
>
>
>6. Include files
>
>The C layer of DirectC Interface defines two include files. The main include
>file "svc.h" is implementation independent and defines the canonical
>representation, all basic types and all interface functions.
>The second include file, "svc_src.h" defines only the actual
>representation of
>packed arrays and hence is implementation dependent.
>
>The applications that need not include "svc_src.h" are binary level
>compatible.
>
>
>6.1 Binary compatibility include file "svc.h"
>
>This is the main include file needed by most of applications that use DirectC
>interface with C code. "svc.h" is fully defined by the interface.
>
>It defines the canonical representation of 2-state ('bit') and 4-state
>('logic')
>values, defines all types used for passing references to SV data objects.
>
>All interface functions are declared in this file.
>
>6.1.1 scalars of type 'bit' and 'logic'
>
>This file contains the following definitions:
>
>/* canonical 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 */
>
>/* common type for 'bit' and 'logic' scalars. */
>typedef unsigned char svScalar;
>
>typedef svScalar svBit; /* scalar */
>typedef svScalar svLogic; /* scalar */
>
>
>6.1.2 Canonical representation of packed arrays
>
>/* 2-state and 4-state vectors, modelled upon PLI's avalue/bvalue */
>#define sv_CANONICAL_SIZE(WIDTH) (((WIDTH)+31)>>5)
>
>typedef unsigned int
> svBitVec32; /* (a chunk of) packed bit array */
>
>typedef struct { unsigned int c; unsigned int d;} /* as in VCS */
> svLogicVec32; /* (a chunk of) packed logic array */
>
>
>6.1.3 Implementation dependent representation
>
> /* a handle to a generic object (actually, unsized array) */
>typedef void* svHandle;
>
>/* reference to a standalone packed array */
>typedef void* svBitPackedArrRef;
>typedef void* svLogicPackedArrRef;
>
>/* total size in bytes of the simulator's representation of a packed array */
>/* width in bits */
>int svSizeOfLogicPackedArr(int width);
>int svSizeOfBitPackedArr(int width);
>
>
>6.1.4 Translation between actual representation and canonical representation
>
>/* functions for translation between the representation actually used by
>simulator
> and canonical representation */
>
>/* s=source, d=destination, w=width */
>
>/* actual <-- canonical */
>void svPutBitVec32 (svBitPackedArrRef d, const svBitVec32* s, int w);
>void svPutLogicVec32 (svLogicPackedArrRef d, const svLogicVec32* s, int w);
>
>/* canonical <-- actual */
>void svGetBitVec32 (svBitVec32* d, const svBitPackedArrRef s, int w);
>void svGetLogicVec32 (svLogicVec32* d, const svLogicPackedArrRef 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.
>
>Although the put/get functionality provided for 'bit' and 'logic'
>packed arrays is sufficient yet basic, it requires unnecessary copying of
>the whole packed array when perhaps only some bits are needed.
>
>For the sake of the convenience and improved performance, the bit selects and
>limited (up to 32 bits) part selects are also supported, see 7.4, 7.5.
>
>
>6.2 Source level compatibility include file "svc_src.h"
>
>Only two symbols are defined: the macros that allow to declare variables
>representing SV packed arrays of type 'bit' or 'logic'.
>
>#define sv_BIT_PACKED_ARRAY(WIDTH,NAME) ...
>#define sv_LOGIC_PACKED_ARRAY(WIDTH,NAME) ...
>
>The actual definitions are implementation specific.
>
>For example, VCS might define the later macro as follows:
> #define sv_LOGIC_PACKED_ARRAY(WIDTH,NAME) \
> svLogicVec32 NAME [ sv_CANONICAL_SIZE(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);
>
> export extern $root.exported_sv_func; // whatever is the syntax ...
>
> function void exported_sv_func(input int i, output int o [0:7]);
> begin ... end endfunction
>
>C:
> #include "svc.h"
>
> typedef struct {int a; int b;} pair;
>
> extern void exported_sv_func(int, int *); /* imported from SV */
>
> void foo(const int i1, const pair *i2, svLogicPackedArrRef o3)
> {
> svLogicVec32 arr[sv_CANONICAL_SIZE(64)]; /* 2 chunks needed */
> int tab[8];
>
> printf("%d\n", i1);
> arr[1].c = i2->a;
> arr[1].d = 0;
> arr[2].c = i2->b;
> arr[2].d = 0;
> svPutLogicVec32 (o3, arr, 64);
>
> /* call SV */
> exported_sv_func(i1, tab); /* tab passed by reference */
> ...
> }
>
>
>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);
>
> export extern $root.exported_sv_func; // whatever is the syntax ...
>
> function void exported_sv_func(input int i, output logic [63:0] o);
> begin ... end endfunction
>
>C:
> #include "svc.h"
> #include "svc_src.h"
>
> typedef struct {
> int a;
> sv_BIT_PACKED_ARRAY(6*8, b) [64]; /* implementation
> specific representation */
> int c;
> } triple;
>
> /* Note that 'b' is defined as for 'bit [6*8-1:0] b [63:0]' */
>
> extern void exported_sv_func(int, svLogicPackedArrRef); /*
> imported from SV */
>
> void foo(const triple *i)
> {
> int j;
>
> /* canonical representation */
> svBitVec32 arr[sv_CANONICAL_SIZE(6*8)]; /* 6*8 packed bits */
> svLogicVec32 aL[sv_CANONICAL_SIZE(64)];
>
> /* implementation specific representation */
> sv_LOGIC_PACKED_ARRAY(64, my_tab);
>
> printf("%d %d\n", i->a, i->c);
> for (j=0; j<64; j++) {
> svGetBitVec32(arr, (svBitPackedArrRef)&(i->b[j]), 6*8);
> ...
> }
> ...
> /* call SV */
> exported_sv_func(2, (svLogicPackedArrRef)&my_tab); /* by
> reference */
> svGetLogicVec32(aL, (svLogicPackedArrRef)&my_tab, 64);
> ...
> }
>
>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 svGetBitVec32(),
>by passing its address to the function.
>
>
>
>7. Arrays
>
>Generally, normalized ranges are assumed for accessing SV arrays, with the
>exception of formal arguments specified as open arrays.
>
>7.1 Multidimensional arrays
>
>The packed arrays are assumed to be always 1-dimensional.
>Upacked arrays may have arbitrary number of dimensions.
>
>7.2 Direct access to unpacked arrays
>
>Unpacked ararys, with the exception of formal arguments specified as open
>arrays, are assumed to have the same layout as used by C compiler,
>and they are accessed using C indexing; cf. 4.6.
>
>7.3 Access to packed arrays via canonical representation
>
>Packed arrays are accessible via canonical representation; interface provides
>functions for moving data between implementation representation and canonical
>representation, any necessary convertion is performed on the fly; cf. 6.1.3.
>
>There are also functions for bit selects and limited (up to 32 bits) part
>selects.
>
>
>7.4 Bit selects
>
>/* Packed arrays are assumed to be indexed n-1:0,
> where 0 is the index of least significant bit */
>
>/* functions for bit select */
>
>/* s=source, i=bit-index */
>svBit svGetSelectBit(const svBitPackedArrRef s, int i);
>svLogic svGetSelectLogic(const svLogicPackedArrRef s, int i);
>
>/* d=destination, i=bit-index, s=scalar */
>void svPutSelectBit(svBitPackedArrRef d, int i, svBit s);
>void svPutSelectLogic(svLogicPackedArrRef d, int i, svLogic s);
>
>
>
>7.5 Part selects
>
>Limited (up to 32 bits) part selects are supported.
>"Part select" denotes here a slice of packed array of types 'bit' or 'logic'.
>Array slices are not supported for unpacked arrays.
>
>Functions for part select allow to access (read/write) only a narrow subranges
>of up to 32 bits. A canonical representation will be used for such narrow
>vectors.
>
>
>/*
> * functions for part select
> *
> * a narrow (<=32 bits) part select is copied between
> * the implementation representation and a single chunk of
> * canonical representation
> * Normalized ranges and indexing [n-1:0] are used for both arrays:
> * the array in the implementation representation and the canonical array.
> *
> * s=source, d=destination, i=starting bit index, w=width
> * like for variable part selects; limitations: w <= 32
> */
>
>Please note that for the sake of symmetry a canonical representation
>(i.e. an array) is used both for 'bit' and 'logic', though a simpler
>int could be used for 'bit' part selects <= 32-bit.
>
>/* canonical <-- actual */
>void svGetPartSelectBit(svBitVec32* d, const svBitPackedArrRef s, int i,
>int w);
>void svGetPartSelectLogic(svLogicVec32* d, const svLogicPackedArrRef s,
>int i, int w);
>
>/* actual <-- canonical */
>void svPutPartSelectBit(svBitPackedArrRef d, const svBitVec32* s, int i,
>int w);
>void svPutPartSelectLogic(svLogicPackedArrRef d, const svLogicVec32* s,
>int i, int w);
>
>
>
>
>
>8. Open Arrays
>
>Formal arguments specified as open arrays allow to pass actual arguments
>of different sizes (different range and/or different number of elements).
>This facilitates writing in C a more general code that may handle SV
>arrays of
>different sizes.
>
>Better yet, the elements of an open array are accessed in C code using the
>same range of indices and the same indexing as in SV code.
>Additionally, inquires about the dimensions and the original boundaries of
>SV actual argument are supported for open arrays. This may make them more
>attractive for the users and less confusing than sized arrays, which always
>use normalized ranges and thus require the mapping between the original
>indices or ranges in SV and the normalized ranges and indices used in C.
>
>
>All formal arguments declared in SV as open arrays are passed by handle (type
>'svHandle') regardless of a direction of SV formal argument.
>Such arguments are accessible via interface functions.
>
>8.1 Actual ranges
>
>The formal arguments defined as open arrays have the size and ranges of the
>actual argument, determined on per call basis.
>
>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, cf. 4.6.
>Hint: programmers may decide to stick to [n:0]name[0:k] style ranges in SV.
>
>In the later case, i.e. open array, individual elements of a packed array
>will
>be accessible via interface functions, 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 an 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.
>
>The following example shows the use of sized vs. unsized ararys in SV code:
>
> // both unpacked arrays are 64 by 8 elements, packed 16-bit each
> logic [15: 0] a_64x8 [63:0][7:0];
> logic [31:16] b_64x8 [64:1][-1:-8];
>
> extern void foo(input logic [] i [][]);
> // 2-dimensional unsized unpacked array of unsized packed
> logic
>
> extern void boo(input logic [31:16] i [64:1][-1:-8]);
> // 2-dimensional sized unpacked array of sized packed logic
>
> foo(a_64x8);
> foo(b_64x8); // C code may use original ranges [31:16][64:1][-1:-8]
>
> boo(b_64x8); // C code must use normalized ranges [15:0][0:63][0:7]
>
>
>8.2 Array querying functions
>
>These functions are modelled upon SV array querying functions, with
>the same semantics (cf. SV 3.0 LRM 16.3).
>
>If the dimension is 0, then the query refers to the packed part (which is
>always
>assumed to be 1-dimensional) of an array, and dimensions > 0 refer to
>the unpacked part of an array.
>
>/* h= handle to open array, d=dimension */
>int svLeft(const svHandle h, int d);
>int svRight(const svHandle h, int d);
>int svLow(const svHandle h, int d);
>int svHigh(const svHandle h, int d);
>int svIncrement(const svHandle h, int d);
>int svLength(const svHandle h, int d);
>int svDimensions(const svHandle h);
>
>
>8.3 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 must be 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 (read or
>written) 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 and packed arrays may be accessed via pointers, as
>described
> above. Scalars and packed arrays may or may be not accessible via
> pointers depending
> on implementation.
>
>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.
>
>
>8.4 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.
>
>If the actual layout of the SV array passed as an argument for an open
>unpacked
>array is different than C layout, then it will not be posssible to access
>such
>array as a whole and therefore the address and size of such array will be
>undefined (zero, to be exact).
>Nonetheless the adresses of individual elements of an array will be always
>supported.
>
>Note that no specific representation of an array is assumed here, hence
>all functions use a generic pointer void *.
>
>
>/* a pointer to the actual representation of the whole array of any type */
>/* NULL if not in C layout */
>void *svGetArrayPtr(const svHandle);
>
>int svSizeOfArray(const svHandle); /* total size in bytes or 0 if not in C
>layout */
>
>/* Return a pointer to an element of the array
> or NULL if index outside the range or null pointer */
>
>void *svGetArrElemPtr(const svHandle, int indx1, ...);
>
> /* specialized versions for 1-, 2- and 3-dimensional arrays: */
>void *svGetArrElemPtr1(const svHandle, int indx1);
>void *svGetArrElemPtr2(const svHandle, int indx1, int indx2);
>void *svGetArrElemPtr3(const svHandle, int indx1, int indx2, int indx3);
>
>Access to an individual array's element via pointer makes sense only if the
>representation of such element is same as it would be for an individual
>value of the
>same type. Representation of array elements of type scalar or packed value is
>implementation dependent; if it differes from the representation of
>individual values of
>the same type, the above functions will return null.
>
>
>8.5 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 ranges are used for indexing.
>
>
>/* functions for translation between simulator's and canonical
> representations */
>
>/* s=source, d=destination */
>
>/* actual <-- canonical */
>void svPutBitArrElemVec32 (const svHandle d, const svBitVec32* s, int
>indx1, ...);
>void svPutBitArrElem1Vec32(const svHandle d, const svBitVec32* s, int indx1);
>void svPutBitArrElem2Vec32(const svHandle d, const svBitVec32* s, int
>indx1, int indx2);
>void svPutBitArrElem3Vec32(const svHandle d, const svBitVec32* s,
> int indx1, int indx2, int
> indx3);
>
>void svPutLogicArrElemVec32 (const svHandle d, const svLogicVec32* s, int
>indx1, ...);
>void svPutLogicArrElem1Vec32(const svHandle d, const svLogicVec32* s, int
>indx1);
>void svPutLogicArrElem2Vec32(const svHandle d, const svLogicVec32* s, int
>indx1, int indx2);
>void svPutLogicArrElem3Vec32(const svHandle d, const svLogicVec32* s,
> int indx1, int indx2,
> int indx3);
>
>/* canonical <-- actual */
>void svGetBitArrElemVec32 (svBitVec32* d, const svHandle s, int indx1, ...);
>void svGetBitArrElem1Vec32(svBitVec32* d, const svHandle s, int indx1);
>void svGetBitArrElem2Vec32(svBitVec32* d, const svHandle s, int indx1, int
>indx2);
>void svGetBitArrElem3Vec32(svBitVec32* d, const svHandle s,
> int indx1, int indx2, int
> indx3);
>
>void svGetLogicArrElemVec32 (svLogicVec32* d, const svHandle s, int indx1,
>...);
>void svGetLogicArrElem1Vec32(svLogicVec32* d, const svHandle s, int indx1);
>void svGetLogicArrElem2Vec32(svLogicVec32* d, const svHandle s, int indx1,
>int indx2);
>void svGetLogicArrElem3Vec32(svLogicVec32* d, const svHandle s,
> int indx1, int indx2,
> int indx3);
>
>The above functions copy the whole packed array in either direction.
>User is responsible for allocating an array in the canonical representation.
>
>
>8.6 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':
>
>svBit svGetBitArrElem (const svHandle s, int indx1, ...);
>svBit svGetBitArrElem1(const svHandle s, int indx1);
>svBit svGetBitArrElem2(const svHandle s, int indx1, int indx2);
>svBit svGetBitArrElem3(const svHandle s, int indx1, int indx2, int indx3);
>
>svLogic svGetLogicArrElem (const svHandle s, int indx1, ...);
>svLogic svGetLogicArrElem1(const svHandle s, int indx1);
>svLogic svGetLogicArrElem2(const svHandle s, int indx1, int indx2);
>svLogic svGetLogicArrElem3(const svHandle s, int indx1, int indx2, int indx3);
>
>void svPutLogicArrElem (const svHandle d, svLogic value, int indx1, ...);
>void svPutLogicArrElem1(const svHandle d, svLogic value, int indx1);
>void svPutLogicArrElem2(const svHandle d, svLogic value, int indx1, int
>indx2);
>void svPutLogicArrElem3(const svHandle d, svLogic value,
> int indx1, int
> indx2, int indx3);
>
>void svPutBitArrElem (const svHandle d, svBit value, int indx1, ...);
>void svPutBitArrElem1(const svHandle d, svBit value, int indx1);
>void svPutBitArrElem2(const svHandle d, svBit value, int indx1, int indx2);
>void svPutBitArrElem3(const svHandle d, svBit value, int indx1, int indx2,
>int indx3);
>
>
>
>8.7 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 "svc_bin.h"
>
> typedef struct {int i; ... } MyType;
>
> void foo(const svHandle h)
> {
> MyType my_value;
> int i, j;
> int lo1 = svLow(h, 1);
> int hi1 = svHigh(h, 1);
> int lo2 = svLow(h, 2);
> int hi2 = svHigh(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;
> ...
> }
> ...
> }
> }
>
>
>
>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(const svHandle hin, const svHandle hout)
> {
> int count = svLength(hin, 1);
> MyType *s = (MyType *)svGetArrayPtr(hin);
> MyType *d = (MyType *)svGetArrayPtr(hout);
>
> if (s && d) { /* both arrays have C layout */
>
> /* an efficient solution using pointer arithmetics */
> while (count--)
> *d++ = *s++;
>
> /* even more efficient:
> memcpy(d, s, svSizeOfArray(hin));
> */
>
> } else { /* less efficient yet implementation independent */
>
> int i = svLow(hin, 1);
> int j = svLow(hout, 1);
> while (i <= svHigh(hin, 1)) {
> *(MyType *)svGetArrElemPtr1(hout, j++) =
> *(MyType *)svGetArrElemPtr1(hin, i++);
> }
>
> }
>
> }
>
>
>Example 5 - access to packed arrays
>===================================
>
>SV:
> extern void foo(input logic [127:0]);
> extern void boo(input logic [127:0] i []); // open array of
> 128-bit
>
>
>C:
> #include "svc_bin.h"
>
> /* one 128-bit packed vector */
> void foo(const svLogicPackedArrRef packed_vec_128_bit)
> {
> svLogicVec32 arr[sv_CANONICAL_SIZE(128)]; /* canonical
> representation */
>
> svGetLogicVec32(arr, packed_vec_128_bit, 128);
> ...
> }
>
>
> /* open array of 128-bit packed vectors */
> void boo(const svHandle h)
> {
> int i;
> svLogicVec32 arr[sv_CANONICAL_SIZE(128)]; /* canonical
> representation */
>
> for (i = svLow(h, 1); i <= svHigh(h, 1); i++) {
>
> svLogicPackedArrRef ptr =
> (svLogicPackedArrRef)svGetArrElemPtr1(h, i);
> /* user need not know the vendor representation! */
>
> svGetLogicVec32(arr, ptr, 128);
> ...
> }
> ...
> }
>
>--------------------------------------------------------------



This archive was generated by hypermail 2b28 : Wed Feb 05 2003 - 08:54:52 PST