Section D.1

LRM-132

Add (changes in red and blue):

      Functions implemented in SystemVerilog and specified in export declarations can be called from C; such functions are referred to as exported functions.

 

      Tasks implemented in SystemVerilog and specified in export declarations can be called from C; such functions are referred to as exported tasks.

 

      Functions implemented in C which can be called from SystemVerilog, and can in turn call exported tasks, are referred to as imported tasks.

Section D.3

LRM-132

Add (changes in red and blue):

Depending on the data types used for imported or exported tasks or functions, the C code can be binary-level or source-level compatible. Applications that do not use SystemVerilog packed types are always binary compatible. Applications that don’t mix SystemVerilog packed and unpacked types in the same data type can be written to guarantee binary compatibility. Open arrays with both packed and unpacked parts are also binary compatible.

 

The values of SystemVerilog packed types can be accessed via interface tasks or functions using the canonical representation of 2-state and 4-state packed arrays, or directly through pointers using the implementation representation. The former mode assures binary level compatibility; the latter one allows for tool-specific, performance-oriented tuning of an application, though it also requires recompiling with the implementation-dependent definitions provided by the vendor and shipped with the simulator.

Section D.5

LRM-132

Add (changes in red and blue):

Formal and actual arguments of both imported tasks and functions and exported tasks and functions are bound by the principle “What You Specify Is What You Get.” This principle is binding both for the caller and for the callee, in C code and in SystemVerilog code. For the callee, it guarantees the actual arguments are as specified for the formal ones. For the caller, it means the function call arguments shall conform with the types of the formal arguments, which might require type-coercion on the caller side.

 

Another way to state this is that no compiler (either C or SystemVerilog) can make argument coercions between a caller’s declared formals and the callee’s declared the formals. This is because the callee’s formal arguments are declared in a different language than the caller’s formal arguments; hence there is no visible relationship between the two sets of formals. Users are expected to understand all argument relationships and provide properly matched types on both sides of the interface (see Annex D.6.2).

 

In SystemVerilog code, the compiler can change the formal arguments of a native SystemVerilog tasks or function and modify its code accordingly, because of optimizations, compiler pragmas, or command line switches. The situation is different for imported tasks and functions. A SystemVerilog compiler cannot modify the C code, perform any coercions, or make any changes whatsoever to the formal arguments of an imported task or function.

 

A SystemVerilog compiler shall provide any necessary coercions for the actual arguments of every imported task and function call. For example, a SystemVerilog compiler might truncate or extend bits of a packed array if the widths of the actual and formal arguments are different. Similarly, a C compiler can provide coercion for C types based on the relationship of the arguments in the exported task and function’s C prototype (formals) and the exported tasks and function’s C call site (actuals). However, a C compiler cannot provide such coercion for SystemVerilog types.

 

Thus, in each case of an inter-language function call, either C to SystemVerilog or SystemVerilog to C, the compilers expect but cannot enforce that the types on either side are compatible. It is therefore the user’s responsibility to ensure that the imported/exported task or function types exactly match the types of the corresponding functions in the foreign language.

Section D.5.5

LRM-132

Add (changes in red and blue):

D.5.5 context and non-context tasks and functions

 

Also refer to Section 27.4.3.

 

Some DPI imported tasks or functions, or other interface's functions called from them, require that the context of their call be known. It takes special instrumentation of their call instances to provide such context; for example, a variable referring to the “current instance” might need to be set. To avoid any unnecessary overhead, imported task and function calls in SystemVerilog code are not instrumented unless the imported task or function is specified as context in its SystemVerilog import declaration.

 

All DPI export tasks and functions require that the context of their call is known. This occurs since SystemVerilog task and function declarations always occur in instantiable scopes, hence allowing a multiplicity of unique task and function instances in the simulator’s elaborated database. Thus, there is no such thing as a non-context export task or function.

 

For the sake of simulation performance, a non-context imported task or function call shall not block SystemVerilog compiler optimizations. An imported task or function not specified as context shall not access any data objects from SystemVerilog other then its actual arguments. Only the actual arguments can be affected (read or written) by its call. Therefore, a call of non-context imported task or function is not a barrier for optimizations. A context imported task or function, however, can access (read or write) any SystemVerilog data objects by calling PLI/VPI, nor by calling an embedded export task or function. Therefore, a call to a context task or function is a barrier for SystemVerilog compiler optimizations.

 

Only the calls of context imported tasks and functions are properly instrumented and cause conservative optimizations; therefore, only those task and functions can safely call all functions from other APIs, including PLI and VPI functions or exported SystemVerilog functions. For imported functions not specified as context, the effects of calling PLI, VPI, or SystemVerilog tasks or functions can be unpredictable and such calls can crash if the callee requires a context that has not been properly set.

 

Special DPI utility functions exist that allow imported tasks and functions to retrieve and operate on their context. For example, the C implementation of an imported task or function can use svGetScope() to retrieve an svScope corresponding to the instance scope of its corresponding SystemVerilog import declaration. See Annex D.8 for more details.

Section D.7.2

LRM-132

Add (changes in red and blue):

D.7.2 Calling SystemVerilog tasks and functions from C

 

There is no difference in argument passing between calls from SystemVerilog to C and calls from C to SystemVerilog. Functions Tasks and functions exported from SystemVerilog cannot have open arrays as arguments. Apart from this restriction, the same types of formal arguments can be declared in SystemVerilog for exported tasks and functions and imported tasks and functions. A task or function exported from SystemVerilog shall have the same function header in C as would an imported function with the same function result type and same formal argument list. In the case of arguments passed by reference, an actual argument to SystemVerilog task and function called from C shall be allocated using the same layout of data as SystemVerilog uses for that type of argument; the caller is responsible for the allocation. It can be done while preserving the binary compatibility, see Annex D.11.5 and Annex D.11.11.

 

Calling a SystemVerilog task from C is the same as calling a SystemVerilog function from C with the exception that the return type of an exported task is an int value which has a special meaning related to disable statements. Please see section 27.8 for details on disable processing by DPI imported tasks and functions.

Section D.8

LRM-132

Add (changes in red and blue):

D.8 Context tasks and functions

 

Some DPI imported tasks and functions require that the context of their call is known. For example, those calls can be associated with instances of C models that have a one-to-one correspondence with instances of SystemVerilog modules that are making the calls. Alternatively, a DPI imported task or function might need to access or modify simulator data structures using PLI or VPI calls, or by making a call back into SystemVerilog via an export task or function. Context knowledge is required for such calls to function properly. It can take special instrumentation of their call to provide such context.

 

To avoid any unnecessary overhead, imported task and function calls in SystemVerilog code are not instrumented unless the task or imported function is specified as context in its SystemVerilog import declaration. A small set of DPI utility functions are available to assist programmers when working with context tasks or functions (see Annex D.8.3). If those utility functions are used with any non-context function, a system error shall result.

Section D.8.1

LRM-132

Add (changes in red and blue):

D.8.1 Overview of DPI and VPI context

 

Both DPI tasks and functions and VPI/PLI functions might need to understand their context. However, the meaning of the term is different for the two categories of tasks and functions.

 

DPI imported tasks and functions are essentially proxies for native SystemVerilog tasks and functions. Native SystemVerilog tasks and functions always operate in the scope of their declaration site. For example, a native SystemVerilog function f() can be declared in a module m which is instantiated as top.i1_m. The top.i1_m instance of f() can be called via hierarchical reference from code in a distant design region. Function f() is said to execute in the context (aka. instantiated scope) of top.i1_m, since it has unqualified visibility only for variables local to that specific instance of m. Function f() does not have unqualified visibility for any variables in the calling code’s scope.

 

DPI imported tasks and functions follow the same model as native SystemVerilog tasks and functions. They execute in the context of their surrounding declarative scope, rather than the context of their call sites. This type of context is termed DPI context.

 

This is in contrast to VPI and PLI functions. Such functions execute in a context associated with their call sites. The VPI/PLI programming model relies on C code’s ability to retrieve a context handle associated with the associated system task’s call site, and then work with the context handle to glean information about arguments, items in the call site’s surrounding declarative scope, etc. This type of context is termed VPI context.

 

Note that all DPI export tasks and functions require that the context of their call is known. This occurs since SystemVerilog task and function declarations always occur in instantiable scopes, hence giving rise to a multiplicity of associated task or function instances in the simulator’s database. Thus, there is no such thing as a non-context export task or function. All export task and function calls must have their execution scope specified in advance by use of a context-setting API function.

Section D.8.2

LRM-132

Add (changes in red and blue):

D.8.2 Context of imported and export tasks and functions

 

DPI imported and export tasks and functions can be declared anywhere a normal SystemVerilog task or function can be declared. Specifically, this means that they can be declared in module, program, interface, or generate declarative scope.

 

A context imported task or function executes in the context of the instantiated scope surrounding its declaration. This means that such tasks and functions can see other variables in that scope without qualification. As explained in Annex D.8.1, this should not be confused with the context of the task’s or function’s call site, which can actually be anywhere in the SystemVerilog design hierarchy. The context of an imported or exported task or function corresponds to the fully qualified name of the task or function, minus the task or function name itself.

 

Note that context is transitive through imported and export context tasks and functions declared in the same scope. That is, if an imported task or function is running in a certain context, and if it in turn calls an exported task or function that is available in the same context, the exported task or function can be called without any use of svSetScope(). For example, consider a SystemVerilog call to a native function f(), which in turn calls a native function g(). Now replace the native function f() with an equivalent imported context C function, f’(). The system shall behave identically regardless if f() or f’() is in the call chain above g(). g() has the proper execution context in both cases.

Section D.8.3

LRM-132

Add (changes in red and blue):

D.8.3 Working with DPI context tasks and functions in C code

 

DPI defines a small set of functions to help programmers work with DPI context tasks and functions. The term scope is used in the task or function names for consistency with other SystemVerilog terminology. The terms scope and context are equivalent for DPI tasks and functions.

 

There are functions that allow the user to retrieve and manipulate the current operational scope. It is an error to use these functions with any C code that is not executing under a call to a DPI context imported task or function.

 

There are also functions that provide users with the power to set data specific to C models into the SystemVerilog simulator for later retrieval. These are the “put” and “get” user data functions, which are similar to facilities provided in VPI and PLI.

 

The put and get user data functions are flexible and allow for a number of use models. Users might wish to share user data across multiple context imported functions defined in the same SV scope. Users might wish to have unique data storage on a per function basis. Shared or unique data storage is controllable by a user-defined key.

 

To achieve shared data storage, a related set of context imported tasks and functions should all use the same userKey. To achieve unique data storage, a context import task or function should use a unique key. Note that it is a requirement on the user that such a key be truly unique from all other keys that could possibly be used by C code. This includes completely unknown C code that could be running in the same simulation. It is suggested that taking addresses of static C symbols (such as a function pointer, or address of some static C data) always be done for user key generation. Generating keys based on arbitrary integers is not a safe practice.

 

Note that it is never possible to share user data storage across different contexts. For example, if a Verilog module m declares a context imported task or function f, and m is instantiated more than once in the SystemVerilog design, then f shall execute under different values of svScope. No such executing instances of f can share user data with each other, at least not using the system-provided user data storage area accessible via svPutUserData().

 

A user wanting to share a data area across multiple contexts must do so by allocating the common data area, then storing the pointer to it individually for each of the contexts in question via multiple calls to svPutUserData(). This is because, although a common user key can be used, the data must be associated with the individual scopes (denoted by svScope) of those contexts.

Section D.8.5

LRM-132

Add (changes in red and blue):

D.8.5 Relationship between DPI and VPI/PLI interfaces

 

DPI allows C code to run in the context of a SystemVerilog simulation, thus it is natural for users to consider using VPI/PLI C code from within imported tasks and functions.

 

There is no specific relationship defined between DPI and the existing Verilog programming interfaces (VPI and PLI). Programmers must make no assumptions about how DPI and the other interfaces interact. In particular, note that a vpiHandle is not equivalent to an svOpenArrayHandle, and the two must not be interchanged and passed between functions defined in two different interface standards.

 

If a user wants to call VPI or PLI functions from within an imported task or function, the imported task or function must be flagged with the context qualifier.

 

Not all VPI or PLI functionality is available from within DPI context imported tasks and functions. For example, a SystemVerilog imported task or function is not a system task, and thus making the following call from within an imported task or function would result in an error:

 

/* Get handle to system task call site in preparation for argument scan */

vpiHandle myHandle = vpi_handle(vpiSysTfCall, NULL);

 

Similarly, receiving misctf callbacks and other activities associated with system tasks are not supported inside DPI imported tasks and functions. Users should use VPI or PLI if they wish to accomplish such actions.

 

However, the following kind of code is guaranteed to work from within DPI context imported tasks and functions: