
This section describes the Verilog Procedural Interface (VPI) routines, explaining their function, syntax, and usage. The routines are listed in alphabetical order. The following conventions are used in the definitions of the VPI routines.
Synopsis: A brief description of the PLI routine functionality, intended to be used as a quick reference when searching for PLI routines to perform specific tasks.
Syntax: The exact name of the PLI routine and the order of the arguments passed to the routine.
Returns: The definition of the value returned when the PLI routine is called, along with a brief description of what the value represents. The return definition contains the fields
· Type: The data type of the C value which is returned. The data type is either a standard ANSI C type or a special type defined within the PLI.
· Description: A brief description of what the value represents.
Arguments: The definition of the arguments passed with a call to the PLI routine. The argument definition contains the fields
· Type: The data type of the C values which are passed as arguments. The data type is either a standard ANSI C type or a special type defined within the PLI.
· Name: The name of the argument used in the Syntax definition.
· Description: A brief description of what the value represents.
All arguments shall be considered mandatory unless specifically noted in the definition of the PLI routine. Two tags are used to indicate arguments that might not be required:
· Conditional: Arguments tagged as conditional shall be required only if a previous argument is set to a specific value or if a call to another PLI routine has configured the PLI to require the arguments. The PLI routine definition explains when conditional arguments are required.
· Optional: Arguments tagged as optional can have default values within the PLI, but they can be required if a previous argument is set to a specific value, or if a call to another PLI routine has configured the PLI to require the arguments. The PLI routine definition explains the default values and when optional arguments are required.
Related routines: A list of PLI routines which are typically used with, or provide similar functionality to, the PLI routine being defined. This list is provided as a convenience to facilitate finding information in this standard. It is not intended to be all-inclusive and it does not imply the related routines have to be used.
2.1 vpi_chk_error()
The VPI routine vpi_chk_error() shall return an integer constant representing an error severity level if the previous call to a VPI routine resulted in an error. The error constants are shown in Table 131. If the previous call to a VPI routine did not result in an error, then vpi_chk_error() shall return FALSE. The error status shall be reset by any VPI routine call except vpi_chk_error(). Calling vpi_chk_error() shall have no effect on the error status.
Error constant Severity level
If an error occurred, the s_vpi_error_info structure shall contain information about the error. If the error information is not needed, a NULL can be passed to the routine. The s_vpi_error_info structure used by vpi_chk_error() is defined in vpi_user.h and is listed in Figure 131.
![]()
2.2 vpi_compare_objects()
The VPI routine vpi_compare_objects() shall return TRUE if the two handles refer to the same object. Otherwise, FALSE shall be returned. Handle equivalence can not be determined with a C `==' comparison.
2.3 vpi_free_object()
Synopsis:
Free memory allocated by VPI routines. Syntax:
vpi_free_object(obj)
Returns:
true on success and false on failure
Arguments:
Handle of an object
The VPI routine vpi_free_object() shall free memory allocated for objects. It shall generally be used to free memory created for iterator objects. The iterator object shall automatically be freed when vpi_scan() returns NULL either because it has completed an object traversal or encountered an error condition. If neither of these conditions occur (which can happen if the code breaks out of an iteration loop before it has scanned every object), vpi_free_object() needs to be called to free any memory allocated for the iterator. This routine can also optionally be used for implementations which have to allocate memory for objects. The routine shall return TRUE on success and FALSE on failure.
2.4 vpi_get()
The VPI routine vpi_get() shall return the value of object properties, for properties of type int and bool (bool shall be defined to int). Object properties of type bool shall return 1 for TRUE and 0 for FALSE. For object properties of type int such as vpiSize, any integer shall be returned. For object properties of type int which return a defined value, refer to Annex C of the IEEE 1364-1995 Verilog HDL specification for the value that shall be returned. Note for object property vpiTimeUnit or vpiTimePrecision, if the object is NULL, then the simulation time unit shall be returned. Should an error occur, vpi_get() shall return vpiUndefined.
2.5 vpi_get_cb_info()
The VPI routine vpi_get_cb_info() shall return information about a simulation-related callback in an s_cb_data structure. The memory for this structure shall be allocated by the user.
The s_cb_data structure used by vpi_get_cb_info() is defined in vpi_user.h and is listed in Figure 132.
![]()
2.6 vpi_get_analog_delta()
The VPI routine vpi_get_analog_delta() shall be used determine the size of the analog time step being attempted. It returns the elapsed time between the latest converged and accepted solution and the solution being calculated. The function shall return zero (0) during DC or the time zero transient solution.
2.7 vpi_get_analog_freq()
The VPI routine vpi_get_analog_freq() shall be used determine the current frequency used in the small-signal analysis. The function shall return zero (0) during DC or transient analysis.
2.8 vpi_get_analog_time()
Synopsis:
Get the time of the current solution. Syntax:
vpi_get_analog_time()
Returns:
time associated with the current solution
Arguments:
this function accepts no arguments
The VPI routine vpi_get_analog_time() shall be used determine the time of the solution attempted or of the latest converged and accepted solution otherwise. The function shall return zero (0) during DC or the time zero transient solution.
2.9 vpi_get_analog_value()
The VPI routine vpi_get_analog_value() shall retrieve the simulation value of VPI analog vpiFlow or vpiPotential (node or branch) quantity objects. The value shall be placed in an s_vpi_analog_value structure, which has been allocated by the user. The format of the value shall be set by the format field of the structure.
The buffer this routine uses for string values shall be different from the buffer which vpi_get_str() shall use. The string buffer used by vpi_get_analog_value() is overwritten with each call. If the value is needed, it needs to be saved by the application.
The s_vpi_analog_value structure used by vpi_get_analog_value() is defined in vpi_user.h and listed in Figure 133.
![]()
The memory for the union members str and misc of the value for real and imaginary unions in the s_vpi_analog_value structure shall be provided by the routine vpi_get_analog_value(). This memory shall only be valid until the next call to vpi_get_analog_value().
Note: The user shall provide the memory for these members when calling vpi_put_value().
2.10 vpi_get_delays()
The VPI routine vpi_get_delays() shall retrieve the delays or pulse limits of an object and place them in an s_vpi_delay structure which has been allocated by the user. The format of the delay information shall be controlled by the time_type flag in the s_vpi_delay structure. This routine shall ignore the value of the type flag in the s_vpi_time structure.
The s_vpi_delay and s_vpi_time structures used by both vpi_get_delays() and vpi_put_delays() are defined in vpi_user.h and are listed in Figures 134 and 135.
![]()
![]()
The da field of the s_vpi_delay structure shall be a user-allocated array of s_vpi_time structures. This array shall store delay values returned by vpi_get_delays(). The number of elements in this array shall be determined by
· The number of delays to be retrieved
· The mtm_flag setting
· The pulsere_flag setting
The number of delays to be retrieved shall be set in the no_of_delays field of the s_vpi_delay structure. Legal values for the number of delays shall be determined by the type of object.
· For primitive objects, the no_of_delays value shall be 2 or 3.
· For path delay objects, the no_of_delays value shall be 1, 2, 3, 6, or 12.
· For timing check objects, the no_of_delays value shall match the number of limits existing in the timing check.
· For inter-module path objects, the no_of_delays value shall be 2 or 3.
The user-allocated s_vpi_delay array shall contain delays in the same order in which they occur in the Verilog-AMS HDL description. The number of elements for each delay shall be determined by the flags mtm_flag and pulsere_flag, as shown in Table 133.
The delay structure has to be allocated before passing a pointer to vpi_get_delays().
Examples:
In the following example, a static structure, prim_da, is allocated for use by each call to the vpi_get_delays() function.
display_prim_delays(prim)
vpiHandle prim;t2
{
static s_vpi_time prim_da[3];
static s_vpi_delay delay_s = {NULL, 3, vpiScaledRealTime};
static p_vpi_delay delay_p = &delay_s;
delay_s.da = &prim_da;
vpi_get_delays(prim, delay_p);
vpi_printf("Delays for primitive %s: %6.2f %6.2f %6.2f\n",
vpi_get_str(vpiFullName, prim)
delay_p->da[0].real, delay_p->da[1].real,
delay_p->da[2].real);
}
2.11 vpi_get_str()
The VPI routine vpi_get_str() shall return string property values. The string shall be placed in a temporary buffer which shall be used by every call to this routine. If the string is to be used after a subsequent call, the string needs to be copied to another location. A different string buffer shall be used for string values returned through the s_vpi_value structure.
Examples:
The following example illustrates the usage of vpi_get_str().
char *str;
vpiHandle mod = vpi_handle_by_name("top.mod1",NULL);
vpi_printf ("Module top.mod1 is an instance of %s\n",
vpi_get_str(vpiDefName, mod));
2.12 vpi_get_analog_systf_info()
The VPI routine vpi_get_analog_systf_info() shall return information about a user-defined analog system task or function callback in an s_vpi_analog_systf_data structure. The memory for this structure shall be allocated by the user.
The s_vpi_systf_data structure used by vpi_get_analog_systf_info() is defined in vpi_user.h and is listed in Figure 136.
![]()
2.13 vpi_get_systf_info()
The VPI routine vpi_get_systf_info() shall return information about a user-defined system task or function callback in an s_vpi_systf_data structure. The memory for this structure shall be allocated by the user.
The s_vpi_systf_data structure used by vpi_get_systf_info() is defined in vpi_user.h and is listed in Figure 137.
![]()
2.14 vpi_get_time()
Synopsis:
Retrieve the current simulation. Syntax:
vpi_get_time(obj, time_p)
Returns:
Arguments:
Handle to an object
Pointer to a structure containing time information Related routines:
The VPI routine vpi_get_time() shall retrieve the current simulation time, using the time scale of the object. If obj is NULL, the simulation time is retrieved using the simulation time unit. The time_p->type field shall be set to indicate if scaled real, analog, or simulation time is desired. The memory for the time_p structure shall be allocated by the user.
The s_vpi_time structure used by vpi_get_time() is defined in vpi_user.h and is listed in Figure 138 (this is the same time structure as used by vpi_put_value()).
![]()
2.15 vpi_get_value()
The VPI routine vpi_get_value() shall retrieve the simulation value of VPI objects (use vpi_get_analog_value() for the simulation value of VPI analog quantity objects). The value shall be placed in an s_vpi_value structure, which has been allocated by the user. The format of the value shall be set by the format field of the structure.
When the format field is vpiObjTypeVal, the routine shall fill in the value and change the format field based on the object type, as follows:
· For an integer, vpiIntVal
· For a real, vpiRealVal
· For a scalar, either vpiScalar or vpiStrength
· For a time variable, vpiTimeVal with vpiSimTime
· For a vector, vpiVectorVal
The buffer this routine uses for string values shall be different from the buffer which vpi_get_str() shall use. The string buffer used by vpi_get_value() is overwritten with each call. If the value is needed, it needs to be saved by the application.
The s_vpi_value, s_vpi_vecval and s_vpi_strengthval structures used by vpi_get_value() are defined in vpi_user.h and are listed in Figures 139, 1310, and 1311.
![]()
![]()
![]()
For vectors, the p_vpi_vecval field shall point to an array of s_vpi_vecval structures. The size of this array shall be determined by the size of the vector, where array_size = ((vector_size-1)/32 + 1). The lsb of the vector shall be represented by the lsb of the 0-indexed element of s_vpi_vecval array. The 33rd bit of the vector shall be represented by the lsb of the 1-indexed element of the array, and so on. The memory for the union members str, time, vector, strength, and misc of the value union in the s_vpi_value structure shall be provided by the routine vpi_get_value(). This memory shall only be valid until the next call to vpi_get_value(). (The user shall provide the memory for these members when calling vpi_put_value()). When a value change callback occurs for a value type of vpiVectorVal, the system shall create the associated memory (an array of s_vpi_vecval structures) and free the memory upon the return of the callback.
To get the ASCII values of UDP table entries (as explained in Section 8.1.6, Table 8-1 of the IEEE 1364-1995 Verilog HDL specification), the p_vpi_vecval field shall point to an array of s_vpi_vecval structures. The size of this array shall be determined by the size of the table entry (no. of symbols per table entry), where array_size = ((table_entry_size-1)/4 + 1). Each symbol shall require a byte; the ordering of the symbols within s_vpi_vecval shall be the most significant byte of abit first, then the least significant byte of abit, then the most significant byte of bbit, and then the least significant byte of bbit. Each symbol can be either one or two characters; when it is a single character, the second half of the byte shall be an ASCII "\0".
The misc field in the s_vpi_value structure shall provide for alternative value types, which can be implementation specific. If this field is utilized, one or more corresponding format types shall also be provided.
Examples:
In the following example, the binary value of each net which is contained in a particular module and whose name begins with a particular string is displayed. (This function makes use of the strcmp() facility normally declared in a string.h C library.)
void display_certain_net_values(mod, target)
vpiHandle mod;
char *target;
{
static s_vpi_value value_s = {vpiBinStrVal};
static p_vpi_value value_p = &value_s;
vpiHandle net, itr;
itr = vpi_iterate(vpiNet, mod);
while (net = vpi_scan(itr))
{
char *net_name = vpi_get_str(vpiName, net);
if (strcmp(target, net_name) == 0)
{
vpi_get_value(net, value_p);
vpi_printf("Value of net %s: %s\n",
vpi_get_str(vpiFullName, net),value_p->value.str);
}
}
}
The following example illustrates the use of vpi_get_value() to access UDP table entries. Two sample outputs from this example are provided after the example.
/*
* hUDP shall be a handle to a UDP definition
*/
static void dumpUDPTableEntries(vpiHandle hUDP)
{
vpiHandle hEntry, hEntryIter;
s_vpi_value value;
int numb;
int udpType;
int item;
int entryVal;
int *abItem;
int cnt, cnt2;
numb = vpi_get(vpiSize, hUDP);
udpType = vpi_get(vpiPrimType, hUDP);
if (udpType == vpiSeqPrim)
numb++; /* There is one more table entry for state */
numb++; /* There is a table entry for the output */
hEntryIter = vpi_iterate(vpiTableEntry, hUDP);
if (!hEntryIter)
return;
value.format = vpiVectorVal;
while(hEntry = vpi_scan(hEntryIter))
{
vpi_printf("\n");
/* Show the entry as a string */
value.format = vpiStringVal;
vpi_get_value(hEntry, &value);
vpi_printf("%s\n", value.value.str);
/* Decode the vector value format */
value.format = vpiVectorVal;
vpi_get_value(hEntry, &value);
abItem = (int *)value.value.vector;
for(cnt=((numb-1)/2+1);cnt>0;cnt--)
{
entryVal = *abItem;
abItem++;
/* Rip out 4 characters */
for (cnt2=0;cnt2<4;cnt2++)
{
item = entryVal&0xff;
if (item)
vpi_printf("%c", item);
else
vpi_printf("_");
entryVal = entryVal>>8;
}
}
}
vpi_printf("\n");
}
For a UDP table of
1 0 :?:1;
0 (01) :?:-;
(10) 0 :0:1;
The output from the preceding example is
10:1
_0_1___1
01:0
_1_0___0
00:1
_0_0___1
For a UDP table entry of
1 0 :?:1;
0 (01) :?:-;
(10) 0 :0:1;
The output from the preceding example is
10:?:1
_0_1_1_?
0(01):?:-
10_0_-_?
(10)0:0:1
_001_1_0
2.16 vpi_get_vlog_info()
The VPI routine vpi_get_vlog_info() shall obtain the following information about Verilog-AMS product execution:
· The number of invocation options (argc)
· Invocation option values (argv)
· Product and version strings
The information shall be contained in an s_vpi_vlog_info structure. The routine shall return TRUE on success and FALSE on failure.
The s_vpi_vlog_info structure used by vpi_get_vlog_info() is defined in vpi_user.h and is listed in Figure 1312.
![]()
2.17 vpi_get_real()
The VPI routine vpi_get_real() shall return the value of object properties, for properties of type real. Note for object properties shown below, if the object is NULL, then the corresponding value shall be returned.
· vpiStartTime for beginning of transient analysis time
· vpiEndTime for end of transient analysis time
· vpiTransientMaxStep for maximum analog time step
· vpiStartFrequency for the start frequency of AC analysis
· vpiEndFrequency for the end frequency of AC analysis
This function is available to analog tasks and functions only. Should an error occur, vpi_get_real() shall return vpiUndefined.
2.18 vpi_handle()
The VPI routine vpi_handle() shall return the object of type type associated with object ref. The one-to-one relationships which are traversed with this routine are indicated as single arrows in the data model diagrams.
Examples:
The following example application displays each primitive that an input net drives.
void display_driven_primitives(net)
vpiHandle net;
{
vpiHandle load, prim, itr;
vpi_printf("Net %s drives terminals of the primitives: \n",
vpi_get_str(vpiFullName, net));
itr = vpi_iterate(vpiLoad, net);
if (!itr)
return;
while (load = vpi_scan(itr))
{
switch(vpi_get(vpiType, load))
{
case vpiGate:
case vpiSwitch:
case vpiUdp:
prim = vpi_handle(vpiPrimitive, load);
vpi_printf("\t%s\n", vpi_get_str(vpiFullName, prim));
}
}
}
2.19 vpi_handle_by_index()
The VPI routine vpi_handle_by_index() shall return a handle to an object based on the index number of the object within a parent object. This function can be used to access all objects which can access an expression using vpiIndex. Argument obj shall represent the parent of the indexed object. For example, to access a net-bit, obj is the associated net, while for a memory word, obj is the associated memory.
2.20 vpi_handle_by_name()
The VPI routine vpi_handle_by_name() shall return a handle to an object with a specific name. This function can be applied to all objects with a fullname property. The name can be hierarchical or simple. If scope is NULL, then name shall be searched for from the top level of hierarchy. Otherwise, name shall be searched for from scope using the scope search rules defined by the Verilog-AMS HDL.
2.21 vpi_handle_multi()
The VPI routine vpi_handle_multi() shall return a handle to objects of type vpiInterModPath associated with a list of output port and input port reference objects. The ports shall be of the same size and can be at different levels of the hierarchy. This routine performs a many-to-one operation instead of the usual one-to-one or one-to-many.
2.21.1 Derivatives for analog system task/functions
The VPI routine vpi_handle_multi() is used to access the derivative handles associated with analog system task/functions (see also: vpi_register_analog_systf()). The first argument is the type vpiDerivative. The second is the handle for the task/function argument for which a partial derivative is to be declared. The third argument indicates the value with respect to which the derivative being declared shall be calculated. For example, assuming argHandle2 and argHandle3 are handles to the second and third arguments of an analog system task, then vpi_handle_multi(vpiDerivative, argHandle2, argHandle3) indicates the partial derivative of the returned value with respect to the third argument. For vpiDerivative, the vpi_handle_multi() function can only be called for those derivatives allocated during the derivtf phase of execution.
2.21.2 Examples
The following example illustrates the declaration and use of derivative handles in a analog task $resistor(), which implements a conductance relationship. The task can be used as follows:
module resistor(p, n);
electrical p, n;
parameter real r = 1k;
real curr;
analog begin
$resistor(curr, V(p, n), r);
I(p, n) <+ curr;
end
endmodule
The implementation of the analog task can be performed by the resistor_compile_tf() and resistor_call_tf() routines shown below:
#include "vpiutils.h"
/* compiletf() */
static int resistor_compiletf(p_cb_data cb_data) {
vpiHandle funcHandle, i_handle, v_handle, r_handle, didv_handle;
int type;
s_vpi_value value;
double g;
p_resistor_data res;
/* Retrieve handle to current function */
funcHandle = vpi_handle(vpiSysTfCall, NULL);
/* Get the handle on the first function argument*/
i_handle = vpi_handle_by_index(funcHandle, 1);
/* Check that argument exists */
if (!i_handle) {
vpi_error("Not enough arguments for $resistor function.");
}
/* Check that argument #1 is a real variable */
type = vpi_get(vpiType, v_handle);
if (type != vpiRealVar) {
vpi_error("Arg #1 of $resistor should be a real variable");
return 1;
}
/* Get the handle on the second function argument*/
v_handle = vpi_handle_by_index(funcHandle, 2);
/* Check that argument exists */
if (!v_handle) {
vpi_error("Not enough arguments for $resistor function.");
return 1;
}
/* Check that argument #1 is a real valued */
type = vpi_get(vpiType, v_handle);
if (type != vpiRealVar && type != vpiRealVal) {
vpi_error("Arg #2 of $resistor should be a real variable");
return 1;
}
/* Get the handle on the third function argument*/
r_handle = vpi_handle_by_index(funcHandle, 3);
/* Check that argument exists */
if (!v_handle) {
vpi_error("Not enough arguments for $resistor function.");
return 1;
}
/* Check that argument #3 is real valued */
type = vpi_get(vpiType, r_handle);
if (type != vpiRealVar && type != vpiRealVal) {
vpi_error("Arg #3 of $resistor should be a real variable");
return 1;
}
return 0;
}
/* derivtf() */
static p_vpi_stf_partials resistor_derivtf(p_cb_data cb_data) {
static t_vpi_stf_partials derivs;
static int deriv_of[] = { 1 };
static int deriv_to[] = { 2 };
derivs.count = 1;
derivs.derivative_of = deriv_of;
derivs.derivative_to = deriv_to;
return &derivs;
}
/* load() */
static int resistor_calltf(int data, int reason) {
vpiHandle funcHandle, i_handle, v_handle, didv_handle;
double g;
s_vpi_value value;
/* Retrieve handle to current function */
funcHandle = vpi_handle(vpiSysTfCall, NULL);
i_handle = vpi_handle_by_index(funcHandle, 1);
v_handle = vpi_handle_by_index(funcHandle, 2);
didv_handle = vpi_handle_multi(vpiDerivative, i_handle,
v_handle);
/* Get resistance value, compute conductance and store it as*/
/* derivative*/
value.format = vpiRealVal;
vpi_get_value(r_handle, &value);
g = 1.0 / value.value.real;
value.value.real = g;
vpi_put_value(didv_handle, &value, NULL, vpiNoDelay);
/* Get voltage value, compute current and store it into "I"*/
vpi_get_value(v_handle, &value);
value.value.real *= g;
vpi_put_value(i_handle, &value, NULL, vpiNoDelay);
return 0;
}
/*
* Public structure declaring the task
*/
static s_vpi_analog_systf_data resistor_systf = {
vpiSysAnalogTask, /* type: function / task */
0, /* returned type */
"$resistor", /* name */
resistor_calltf, /* calltf callback */
resistor_compiletf, /* compiletf callback */
0, /* unused: sizetf callback */
resistor_derivtf, /* derivtf callback */
0 /* user_data: nothing */
};
2.22 vpi_iterate()
The VPI routine vpi_iterate() shall be used to traverse one-to-many relationships, which are indicated as double arrows in the data model diagrams. The vpi_iterate() routine shall return a handle to an iterator, whose type shall be vpiIterator, which can used by vpi_scan() to traverse all objects of type type associated with object ref. To get the reference object from the iterator object use vpi_handle(vpiUse, iterator_handle). If there are no objects of type type associated with the reference handle ref, then the vpi_iterate() routine shall return NULL.
Examples:
The following example application uses vpi_iterate() and vpi_scan() to display each net (including the size for vectors) declared in the module. The example assumes it shall be passed a valid module handle.
void display_nets(mod)
vpiHandle mod;
{
vpiHandle net;
vpiHandle itr;
vpi_printf("Nets declared in module %s\n",
vpi_get_str(vpiFullName, mod));
itr = vpi_iterate(vpiNet, mod);
while (net = vpi_scan(itr))
{
vpi_printf("\t%s", vpi_get_str(vpiName, net));
if (vpi_get(vpiVector, net))
{
vpi_printf(" of size %d\n", vpi_get(vpiSize, net));
}
else vpi_printf("\n");
}
}
2.23 vpi_mcd_close()
The VPI routine vpi_mcd_close() shall close the file(s) specified by a multichannel descriptor, mcd. Several channels can be closed simultaneously, since channels are represented by discrete bits in the integer mcd. On success this routine returns a zero (0); on error it returns the mcd value of the unclosed channels.
The following descriptors are predefined and can not be closed using vpi_mcd_close():
· descriptor 1 is stdout
· descriptor 2 is stderr
· descriptor 3 is the current log file
2.24 vpi_mcd_name()
The VPI routine vpi_mcd_name() shall return the name of a file represented by a single-channel descriptor, cd. On error, the routine shall return NULL. This routine shall overwrite the returned value on subsequent calls. If the application needs to retain the string, it shall copy it.
2.25 vpi_mcd_open()
The VPI routine vpi_mcd_open() shall open a file for writing and return a corresponding multichannel descriptor number (mcd). The following channel descriptors are predefined and shall be automatically opened by the system:
· Descriptor 1 is stdout
· Descriptor 2 is stderr
· Descriptor 3 is the current log file
The vpi_mcd_open() routine shall return a zero (0) on error. If the file is already opened, vpi_mcd_open() shall return the descriptor number.
2.26 vpi_mcd_printf()
The VPI routine vpi_mcd_printf() shall write to one or more channels (up to 32) determined by the mcd. An mcd of 1 (bit 0 set) corresponds to Channel 1, a mcd of 2 (bit 1 set) corresponds to Channel 2, a mcd of 4 (bit 2 set) corresponds to Channel 3, and so on. Channel 1 is stdout, channel 2 is stderr, and channel 3 is the current log file. Several channels can be written to simultaneously, since channels are represented by discrete bits in the integer mcd. The format strings shall use the same format as the C fprintf() routine.The routine shall return the number of characters printed or EOF if an error occurred.
2.27 vpi_printf()
The VPI routine vpi_printf() shall write to both stdout and the current product log file. The format string shall use the same format as the C printf() routine. The routine shall return the number of characters printed or EOF if an error occurred.
2.28 vpi_put_delays()
The VPI routine vpi_put_delays() shall set the delays or timing limits of an object as indicated in the delay_p structure. The same ordering of delays shall be used as described in the vpi_get_delays() function. If only the delay changes, and not the pulse limits, the pulse limits shall retain the values they had before the delays where altered.
The s_vpi_delay and s_vpi_time structures used by both vpi_get_delays() and vpi_put_delays() are defined in vpi_user.h and are listed in Figures 1313 and 1314.
![]()
![]()
The da field of the s_vpi_delay structure shall be a user-allocated array of s_vpi_time structures. This array shall store the delay values to be written by vpi_put_delays(). The number of elements in this array shall be determined by:
· The number of delays to be retrieved
· The mtm_flag setting
· The pulsere_flag setting
The number of delays to be retrieved shall be set in the no_of_delays field of the s_vpi_delay structure. Legal values for the number of delays shall be determined by the type of object.
· For primitive objects, the no_of_delays value shall be 2 or 3.
· For path delay objects, the no_of_delays value shall be 1, 2, 3, 6, or 12.
· For timing check objects, the no_of_delays value shall match the number of limits existing in the timing check.
· For inter-module path objects, the no_of_delays value shall be 2 or 3.
The user-allocated s_vpi_delay array shall contain delays in the same order in which they occur in the Verilog-AMS HDL description. The number of elements for each delay shall be determined by the flags mtm_flag and pulsere_flag, as shown in Table 135.
Examples:
The following example application accepts a module path handle, rise and fall delays, and replaces the delays of the indicated path.
void set_path_rise_fall_delays(path, rise, fall)
vpiHandle path;
double rise, fall;
{
static s_vpi_time path_da[2];
static s_vpi_delay delay_s = {NULL, 2, vpiScaledRealTime};
static p_vpi_delay delay_p = &delay_s;
delay_s.da = &path_da;
path_da[0].real = rise;
path_da[1].real = fall;
vpi_put_delays(path, delay_p);
}
2.29 vpi_put_value()
The VPI routine vpi_put_value() shall set simulation logic values on an object. The value to be set shall be stored in an s_vpi_value structure which has been allocated. The delay time before the value is set shall be stored in an s_vpi_time structure which has been allocated. The routine can be applied to nets, regs, variables, memory words, system function calls, sequential UDPs, and schedule events. The flags argument shall be used to direct the routine to use one of the following delay modes:
vpiInertialDelay All scheduled events on the object shall be removed before this event is scheduled.
vpiTransportDelay All events on the object scheduled for times later than this event shall be removed (modified transport delay).
vpiPureTransportDelay No events on the object shall be removed (transport delay).
vpiNoDelay The object shall be set to the passed value with no delay. Argument time_p shall be ignored and can be set to NULL.
vpiForceFlag The object shall be forced to the passed value with no delay (same as the Verilog-AMS HDL procedural force). Argument time_p shall be ignored and can be set to NULL.
vpiReleaseFlag The object shall be released from a forced value (same as the Verilog-AMS HDL procedural release). Argument time_p shall be ignored and can be set to NULL. The value_p shall contain the current value of the object.
vpiCancelEvent A previously scheduled event shall be cancelled. The object passed to vpi_put_value() shall be a handle to an object of type vpiSchedEvent.
If the flags argument also has the bit mask vpiReturnEvent, vpi_put_value() shall return a handle of type vpiSchedEvent to the newly scheduled event, provided there is some form of a delay and an event is scheduled. If the bit mask is not used, or if no delay is used, or if an event is not scheduled, the return value shall be NULL.
The handle to the event can be cancelled by calling vpi_put_value() with the flag set to vpiCancelEvent. It shall not be an error to cancel an event which has already occurred. The scheduled event can be tested by calling vpi_get() with the flag vpiScheduled. If an event is cancelled, it shall simply be removed from the event queue. Any effects which were caused by scheduling the event shall remain in effect (e.g., events which were cancelled due to inertial delay).
Calling vpi_free_object() on the handle shall free the handle but shall not effect the event.
Sequential UDPs shall be set to the indicated value with no delay regardless of any delay on the primitive instance.
Note: vpi_put_value() shall only return a function value in a calltf application, when the call to the function is active. The action of vpi_put_value() to a function shall be ignored when the function is not active.
The s_vpi_value and s_vpi_time structures used by vpi_put_value() are defined in vpi_user.h and are listed in Figures 1315 and 1316.
![]()
![]()
For vpiScaledRealTime, the indicated time shall be in the timescale associated with the object.
2.30 vpi_register_cb()
The VPI routine vpi_register_cb() is used for registration of simulation-related callbacks to a user-provided application for a variety of reasons during a simulation. The reasons for which a callback can occur are divided into three categories:
· Simulation event
· Simulation time
· Simulation action or feature
How callbacks are registered for each of these categories is explained in the following paragraphs.
The cb_data_p argument shall point to a s_cb_data structure, which is defined in vpi_user.h and given in Figure 1317.
![]()
For all callbacks, the reason field of the s_cb_data structure shall be set to a predefined constant, such as cbValueChange, cbAtStartOfSimTime, cbEndOfCompile, etc. The reason constant shall determine when the user application shall be called back. Refer to the vpi_user.h file listing in Annex C of the IEEE 1364-1995 Verilog HDL specification for a list of all callback reason constants.
The cb_rtn field of the s_cb_data structure shall be set to the application routine name, which shall be invoked when the simulator executes the callback. The use of the remaining fields are detailed in the following sub clauses.
2.30.1 Simulation-event-related callbacks
The vpi_register_cb() callback mechanism can be registered for callbacks to occur for simulation events, such as value changes on an expression or terminal, or the execution of a behavioral statement. When the cb_data_p->reason field is set to one of the following, the callback shall occur as described below:
cbValueChange After value change on an expression or terminal
cbStmt Before execution of a behavioral statement
cbForce/cbRelease After a force or release has occurred
cbAssign/cbDeassign After a procedural assign or deassign statement has been executed
cbDisable After a named block or task containing a system task or function has been disabled
The following fields shall need to be initialized before passing the s_cb_data structure to vpi_register_cb():
cb_data_p->obj This field shall be assigned a handle to an expression, terminal, or statement for which the callback shall occur. For force and release callbacks, if this is set to NULL, every force and release shall generate a callback.
cb_data_p->time->type This field shall be set to either vpiScaledRealTime or vpiSimTime, depending on what time information the user application requires during the callback. If simulation time information is not needed during the callback, this field can be set to vpiSuppressTime.
cb_data_p->value->format This field shall be set to one of the value formats indicated in Table 136. If value information is not needed during the callback, this field can be set to vpiSuppressVal. For cbStmt callbacks, value information is not passed to the callback routine, so this field shall be ignored.
When a simulation event callback occurs, the user application shall be passed a single argument, which is a pointer to an s_cb_data structure (this is not a pointer to the same structure which was passed to vpi_register_cb()). The time and value information shall be set as directed by the time type and value format fields in the call to vpi_register_cb(). The user_data field shall be equivalent to the user_data field passed to vpi_register_cb(). The user application can use the information in the passed structure and information retrieved from other VPI interface routines to perform the desired callback processing.
For a cbValueChange callback, if the obj is a memory word or a variable array, the value in the s_cb_data structure shall be the value of the memory word or variable select which changed value. The index field shall contain the index of the memory word or variable select which changed value.
For cbForce, cbRelease, cbAssign, and cbDeassign callbacks, the object returned in the obj field shall be a handle to the force, release, assign or deassign statement. The value field shall contain the resultant value of the LHS expression. In the case of a release, the value field shall contain the value after the release has occurred.
Examples:
The following example shows an implementation of a simple monitor functionality for scalar nets, using a simulation-event-related callback.
setup_monitor(net)
vpiHandle net;
{
static s_vpi_time time_s = {vpiScaledRealTime};
static s_vpi_value value_s = {vpiBinStrVal};
static s_cb_data cb_data_s =
{cbValueChange, my_monitor, NULL, &time_s, &value_s};
char *net_name = vpi_get_str(vpiFullName, net);
cb_data_s.obj = net;
cb_data_s.user_data = malloc(strlen(net_name)+1);
strcpy(cb_data_s.user_data, net_name);
vpi_register_cb(&cb_data_s);
}
my_monitor(cb_data_p)
p_cb_data cb_data_p; {
vpi_printf("%d %d: %s = %s\n",
cb_data_p->time->high, cb_data_p->time->low,
cb_data_p->user_data,
cb_data_p->value->value.str);
}
2.30.2 Simulation-time-related callbacks
The vpi_register_cb() can register callbacks to occur for simulation time reasons, include callbacks at the beginning or end of the execution of a particular time queue. The following time-related callback reasons are defined:
cbAtStartOfSimTime Callback shall occur before execution of events in a specified time queue. A callback can be set for any time, even if no event is present.
cbReadWriteSynch Callback shall occur after execution of events for a specified time.
cbReadOnlySynch Same as cbReadWriteSynch, except writing values or scheduling events before the next scheduled event is not allowed.
cbNextSimTime Callback shall occur before execution of events in the next event queue.
cbAfterDelay Callback shall occur after a specified amount of time, before execution of events in a specified time queue. A callback can be set for anytime, even if no event is present.
The following fields shall need to be set before passing the s_cb_data structure to vpi_register_cb():
cb_data_p->time->type This field shall be set to either vpiScaledRealTime or vpiSimTime, depending on what time information the user application requires during the callback.
cb_data_p->[time->low,time->high,time->real]
These fields shall contain the requested time of the callback or the delay before the callback.
The value fields are ignored for all reasons with simulation-time-related callbacks.
When the cb_data_p->time->type is set to vpiScaledRealTime, the cb_data_p->obj field shall be used as the object for determining the time scaling.
For reason cbNextSimTime, the time structure is ignored.
When a simulation-time-related callback occurs, the user callback application shall be passed a single argument, which is a pointer to an s_cb_data structure (this is not a pointer to the same structure which was passed to vpi_register_cb()). The time structure shall contain the current simulation time. The user_data field shall be equivalent to the user_data field passed to vpi_register_cb().
The callback application can use the information in the passed structure and information retrieved from other interface routines to perform the desired callback processing.
2.30.3 Simulator analog and related callbacks
The vpi_register_cb() callback mechanism can be registered for callbacks to occur for analog simulation events, such as acceptance of the initial or final analog solution. When the cb_data_p->reason field is set to one of the following, the callback shall occur as described below:
acbInitialStep Upon acceptance of the first analog solution
acbFinalStep Upon acceptance of the last analog solution
acbAbsTime Upon acceptance of the analog solution for the given time (this callback shall force a solution at that time)
acbElapsedTime Upon acceptance of the solution advanced from the current solution by the given interval (this callback shall force a solution at that time)
acbConvergenceTest Prior acceptance of the analog solution for the given time (this callback allows rejection of the analog solution at that time and backup to an earlier time)
acbAcceptedPoint Upon acceptance of the solution at the given time
2.30.4 Simulator action and feature related callbacks
The vpi_register_cb() can register callbacks to occur for simulator action reasons or simulator feature reasons. Simulator action reasons are callbacks such as the end of compilation or end of simulation. Simulator feature reasons are software-product-specific features, such as restarting from a saved simulation state or entering an interactive mode. Actions are differentiated from features in that actions shall occur in all VPI-compliant products, whereas features might not exist in all VPI-compliant products.
The following action-related callbacks shall be defined:
cbEndOfCompile End of simulation data structure compilation or build
cbStartOfSimulation Start of simulation (beginning of time 0 simulation cycle)
cbEndOfSimulation End of simulation (e.g., $finish system task executed)
cbError Simulation run-time error occurred
cbPLIError Simulation run-time error occurred in a PLI function call
cbTchkViolation Timing check error occurred
Examples of possible feature related callbacks are
cbStartOfSave Simulation save state command invoked
cbEndOfSave Simulation save state command completed
cbStartOfRestart Simulation restart from saved state command invoked
cbEndOfRestart Simulation restart command completed
cbEnterInteractive Simulation entering interactive debug mode (e.g., $stop system task executed)
cbExitInteractive Simulation exiting interactive mode
cbInteractiveScopeChange Simulation command to change interactive scope executed
cbUnresolvedSystf Unknown user-defined system task or function encountered
The only fields in the s_cb_data structure which need to be setup for simulation action/feature callbacks are the reason, cb_rtn, and user_data (if desired) fields.
When a simulation action/feature callback occurs, the user routine shall be passed a pointer to an s_cb_data structure. The reason field shall contain the reason for the callback. For cbTchkViolation callbacks, the obj field shall be a handle to the timing check. For cbInteractiveScopeChange, obj shall be a handle to the new scope. For cbUnresolvedSystf, user_data shall point to the name of the unresolved task or function. On a cbError callback, the routine vpi_chk_error() can be called to retrieve error information.
Examples:
The following example shows a callback application which reports cpu usage at the end of a simulation. If the user routine setup_report_cpu() is placed in the vlog_startup_routines list, it shall be called just after the simulator is invoked.
static int initial_cputime_g;
void report_cpu()
{
int total = get_current_cputime() - initial_cputime_g;
vpi_printf("Simulation complete. CPU time used: %d\n", total);
}
void setup_report_cpu()
{
static s_cb_data cb_data_s = {cbEndOfSimulation, report_cpu};
initial_cputime_g = get_current_cputime();
vpi_register_cb(&cb_data_s);
}
2.31 vpi_register_analog_systf()
The VPI routine vpi_register_analog_systf() shall register callbacks for user-defined analog system tasks or functions. Callbacks can be registered to occur when a user-defined system task or function is encountered during compilation or execution of analog Verilog-AMS HDL source code. Tasks or functions can be registered with either the analog or digital domain. The registration function (vpi_register_analog_systf() or vpi_register_systf()) with which the task or function is registered shall determine the context or contexts from which the task or function can be invoked and how and when the call backs associated with the function shall be called. The task or function name shall be unique in the domain in which it is registered. That is, the same name can be shared by two sets of callbacks, provided that one set is registered in the digital domain and the other is registered in the analog.
The systf_analog_data_p argument shall point to a s_vpi_systf_analog_data structure, which is defined in vpi_user.h and listed in Figure 1318.
![]()
2.31.1 System task and function callbacks
User-defined Verilog-AMS system tasks and functions which use VPI routines can be registered with vpi_register_systf() or vpi_register_analog_systf(). The calltf, compiletf, and sizetf system task/function-related callbacks are defined in vpi_register_systf().
The type field of the s_vpi_systf_data structure shall register the user application to be a system task or a system function. The type field value shall be an integer constant of vpiAnalogSysTask or vpiAnalogSysFunction.
The sysfunctype field of the s_vpi_analog_systf_data structure shall define the type of value which a system function shall return. The sysfunctype field shall be an integer constant of vpiIntFunc of vpiRealFunc. This field shall only be used when the type field is set to vpiAnalogSysFunction.
The compiletf, calltf, sizetf, and derivtf fields of the s_vpi_analog_systf_data structure shall be pointers to the user-provided applications which are to be invoked by the system task/function callback mechanism. One or more of the compiletf, calltf, sizetf, and derivtf fields can be set to NULL if they are not needed. Callbacks to the applications pointed to by the compiletf and sizetf fields shall occur when the simulation data structure is compiled or built (or for the first invocation if the system task or function is invoked from an interactive mode). Callbacks to the applications pointed to by the derivtf fields shall occur when registering partial derivatives for the analog system task/function arguments or return value. Callbacks to the application pointed to by the calltf routine shall occur each time the system task or function is invoked during simulation execution.
The user_data field of the s_vpi_analog_systf_data structure shall specify a user-defined value, which shall be passed back to the compiletf, sizetf, derivtf, and calltf applications when a callback occurs.
The usage of the compiletf, sizetf, and calltf routines for the analog system task/function are identical to those of digital system task/functions registered with vpi_register_systf(). Refer to the description of vpi_register_systf() for more information.
2.31.2 Declaring derivatives for analog system task/functions
Analog system tasks and functions require partial derivatives of the outputs (arguments for system tasks and the return value for system functions). Thus it is possible (though not necessary) to have a partial derivative of the returned value with respect to any or all of the arguments and a partial derivative of any particular argument with respect to any or all of the other arguments.
The derivtf field of the t_vpi_analog_systf_data structure can be called during the build process (similar to sizetf) and returns a pointer to a t_vpi_stf_partials data structure containing the required information. The purpose of this function is declarative only, it does not assign any value to the derivative being declared. Having declared a partial derivative using this function in the derivtf callback, values can then be contributed to the derivative using the vpi_put_value function in the calltf call back.
The t_vpi_stf_partials data structure is defined:
typedef struct t_vpi_stf_partials {
int count;
int *derivative_of; /* 0 = returned value, 1 = 1st arg, etc. */
int *derivative_wrt; /* 1 = 1st arg, 2 = 2nd arg, etc. */
} s_vpi_stf_partials, *p_vpi_stf_partials;
This data structure declares the derivative objects for the associated analog task/function. During the call_tf phase, their handles can be retrieved via calls to vpi_handl_multi().
2.31.3 Examples
The following example illustrates the declaration and use of callbacks in an analog function $sampler() which implements a sample and hold. The task is used as follows:
module sampnhold(out, in);
electrical out, in;
parameter real period = 1e-3;
analog begin
V(out) <+ $sampler(V(in), period);
end
endmodule
The VPI implementation of the sampler is as follows:
typedef struct {
vpiHandle returnHandle; /* Arg #0 (returned value) */
vpiHandle exprHandle; /* Arg #1 (sampled expression) */
double period; /* Arg #2 (static period expression) */
s_cb_data cb_data; /* callback structure */
s_vpi_value value;
/* value structure (holds the expression value) */
} s_sampler_data, *p_sampler_data;
/* Forward declarations */
static int sampler_callback(p_cb_data data);
static void schedule_callback(p_sampler_data sampler,
double currTime);
/* compiletf() */
static int sampler_compiletf(p_cb_data task_cb_data) {
vpiHandle functionHandle, returnHandle, exprHandle, periodHandle;
s_cb_data cb_data;
int type;
p_sampler_data sampler;
s_vpi_value value;
/* Retrieve handle to current function */
functionHandle = vpi_handle(vpiSysTfCall, NULL);
/* Get the handle on the expression argument*/
exprHandle = vpi_handle_by_index(functionHandle, 1);
/* Check that expression argument exists */
if (!exprHandle) {
vpi_error("Not enough arguments for $sampler function.");
}
/* Check that expression argument is of real value */
type = vpi_get(vpiType, exprHandle);
if (type != vpiRealVal && type != vpiRealVar) {
vpi_error("Arg #1 of $sampler should be real valued.");
return 1;
}
/* Get the handle on the period argument */
periodHandle = vpi_handle_by_index(functionHandle, 2);
/* Check that period argument exists */
if (!periodHandle) {
vpi_error("Not enough arguments for $sampler function.");
}
/* Check that period argument has a real value */
type = vpi_get(vpiType, periodHandle);
if (type != vpiRealVal && type != vpiRealVar) {
vpi_error("Arg #2 of $sampler should be real valued");
return 1;
}
/* Schedule callback for time = 0 */
sampler->cb_data.reason = cbEndOfCompile;
sampler->cb_data.cb_rtn = sampler_postcompile_cb;
sampler->cb_data.time.type = 0;
sampler->cb_data.user_data = (char *) functionHandle;
sampler->cb_data.time.real = 0.0;
schedule_callback(sampler, 0.0);
vpi_register_cb(&sampler->cb_data);
return 0;
}
/* calltf */
static int sampler_calltf(int data, int reason) {
vpiHandle funcHandle;
p_sampler_data sampler = (p_sampler_data) data;
s_vpi_value value;
/* Retrieve handle to current function */
funcHandle = vpi_handle(vpiSysTfCall, NULL);
/* Set returned value to held value */
vpi_set_value(sampler->returnHandle, &sampler->value, NULL,
vpiNoDelay);
return 0;
}
/* initialization callback after compile */
static int sampler_postcompile_cb(p_cb_data data) {
vpiHandle functionHandle = (vpiHandle) data;
p_sampler_data sampler;
s_vpi_value value;
/* Allocate the instance data and initialize it*/
sampler = (p_sampler_data)malloc(sizeof(s_sampler_data));
/*Get the handle to the returned value, no need to check that one*/
sampler->returnHandle = vpi_handle_by_index(functionHandle, 0);
sampler->exprHandle = vpi_handle_by_index(functionHandle, 1);
sampler->periodHandle = vpi_handle_by_index(functionHandle, 2);
/* Get the period value, it is assumed to be constant */
/* (but not necessary) */
sampler->value.format = vpiRealVal;
vpi_get_value(periodHandle, &value);
sampler->period = value.value.real;
/* Schedule callback for time = period */
sampler->cb_data.reason = acbElapsedTime;
sampler->cb_data.cb_rtn = sampler_update_cb;
sampler->cb_data.time.type = vpiScaledTme;
sampler->cb_data.user_data = (char *) sampler;
sampler->cb_data.time.real = sampler->period;
schedule_callback(sampler, 0.0);
vpi_register_cb(&sampler->cb_data);
return 0;
}
/* timer callback */
static int sampler_update_cb(p_cb_data data) {
p_sampler_data sampler = (p_sampler_data)data->user_data;
s_vpi_value value;
/* Hold expression value */
vpi_get_value(sampler->exprHandle, &value);
/* Schedule next callback */
sampler->cb_data.reason = acbAbsTime;
sampler->cb_data.cb_rtn = sampler_update_cb;
sampler->cb_data.time.type = vpiScaledTime;
sampler->cb_data.user_data = (char *) sampler;
sampler->cb_data.time.real =
vpi_get_analog_time() + sampler->period;
register_callback(&sampler->cb_data);
return 0;
}
/*
* Public structure declaring the function
*/
static s_vpi_systf_data sampler_systf = {
vpiSysFunc, /* type: function / function */
vpiRealFunc, /* returned type */
"$sampler", /* name */
sampler_calltf, /* calltf callback */
sampler_compiletf, /* compiletf callback */
0, /* unused: sizetf callback */
0, /* unused: derivtf callback */
0 /* user_data: nothing */
};
2.32 vpi_register_systf()
The VPI routine vpi_register_systf() shall register callbacks for user-defined system tasks or functions. Callbacks can be registered to occur when a user-defined system task or function is encountered during compilation or execution of Verilog-AMS HDL source code.
The systf_data_p argument shall point to a s_vpi_systf_data structure, which is defined in vpi_user.h and listed in Figure 1319.
![]()
2.32.1 System task and function callbacks
User-defined Verilog-AMS system tasks and functions which use VPI routines can be registered with vpi_register_systf(). The following system task/function-related callbacks are defined.
The type field of the s_vpi_systf_data structure shall register the user application to be a system task or a system function. The type field value shall be an integer constant of vpiSysTask or vpiSysFunction. vpiSysTask shall register a task with the digital domain. vpiSysFunction shall register a function with the digital domain.
The sysfunctype field of the s_vpi_systf_data structure shall define the type of value the system function returns. The sysfunctype field shall be an integer constant of vpiIntFunc, vpiRealFunc, vpiTimeFunc, or vpiSizedFunc. This field shall only be used when the type field is set to vpiSysFunction.
The compiletf, calltf, and sizetf fields of the s_vpi_systf_data structure shall be pointers to the user-provided applications which are to be invoked by the system task/function callback mechanism. One or more of the compiletf, calltf, and sizetf fields can be set to NULL if they are not needed. Callbacks to the applications pointed to by the compiletf and sizetf fields shall occur when the simulation data structure is compiled or built (or for the first invocation if the system task or function is invoked from an interactive mode). Callbacks to the application pointed to by the calltf routine shall occur each time the system task or function is invoked during simulation execution.
The sizetf application shall only called if the PLI application type is vpiSysFunction and the sysfunctype is vpiSizedFunc. If no sizetf is provided, a user-defined system function of vpiSizedFunc shall return 32-bits.
The user_data field of the s_vpi_systf_data structure shall specify a user-defined value, which shall be passed back to the compiletf, sizetf, and calltf applications when a callback occurs.
Examples:
The following example application demonstrates dynamic linking of a VPI system task. The example uses an imaginary routine, dlink(), which accepts a file name and a function name and then links that function dynamically. This routine derives the target file and function names from the target systf name.
link_systf(target)
char *target;
{
char task_name[strSize];
char file_name[strSize];
char compiletf_name[strSize];
char calltf_name[strSize];
static s_vpi_systf_data task_data_s = {vpiSysTask};
static p_vpi_systf_data task_data_p = &task_data_s;
sprintf(task_name, "$%s", target);
sprintf(file_name, "%s.o", target);
sprintf(compiletf_name, "%s_compiletf", target);
sprintf(calltf_name, "%s_calltf", target);
task_data_p->tfname = task_name;
task_data_p->compiletf = (int (*)()) dlink(file_name,
compiletf_name);
task_data_p->calltf = (int (*)()) dlink(file_name, calltf_name);
vpi_register_systf(task_data_p);
}
2.32.2 Initializing VPI system task/function callbacks
A means of initializing system task/function callbacks and performing any other desired task just after the simulator is invoked shall be provided by placing routines in a NULL-terminated static array, vlog_startup_routines. A C function using the array definition shall be provided as follows:
void (*vlog_startup_routines[]) ();
This C function shall be provided with a VPI-compliant product. Entries in the array shall be added by the user. The location of vlog_startup_routines and the procedure for linking vlog_startup_routines with a software product shall be defined by the product vendor. (Callbacks can also be registered or removed at any time during an application routine, not just at startup time).
This array of C functions shall be for registering system tasks and functions. User tasks and functions which appear in a compiled description shall generally be registered by a routine in this array.
Examples:
The following example uses vlog_startup_routines to register system tasks and functions and to run a user initialization routine.
/*In a vendor product file which contains vlog_startup_routines ...*/
extern void register_my_systfs();
extern void my_init();
void (*vlog_startup_routines[])() =
{
setup_report_cpu,/* user routine example in 23.24.3 */
register_my_systfs, /* user routine listed below */
0 /* shall be last entry in list */
}
/* In a user provided file... */
void register_my_systfs()
{
static s_vpi_systf_data systf_data_list[] = {
{vpiSysTask, 0 "$my_task", my_task_calltf, my_task_compiletf},
{vpiSysFunc, vpiIntFunc,"$my_func", my_func_calltf,
my_func_compiletf},
{vpiSysFunc, vpiRealFunc, "$my_real_func", my_rfunc_calltf,
my_rfunc_compiletf},
{0}
};
p_vpi_systf_data systf_data_p = &(systf_data_list[0]);
while (systf_data_p->type)
vpi_register_systf(systf_data_p++);
}
2.33 vpi_remove_cb()
The VPI routine vpi_remove_cb() shall remove callbacks which were registered with vpi_register_cb(). The argument to this routine shall be a handle to the callback object. The routine shall return a 1 (TRUE) if successful, and a 0 (FALSE) on a failure. After vpi_remove_cb() is called with a handle to the callback, the handle is no longer valid.
2.34 vpi_scan()
The VPI routine vpi_scan() shall traverse the instantiated Verilog-AMS HDL hierarchy and return handles to objects as directed by the iterator itr. The iterator handle shall be obtained by calling vpi_iterate() for a specific object type. Once vpi_scan() returns NULL, the iterator handle is no longer valid and can not be used again.
Examples:
The following example application uses vpi_iterate() and vpi_scan() to display each net (including the size for vectors) declared in the module. The example assumes it shall be passed a valid module handle.
void display_nets(mod)
vpiHandle mod;
{
vpiHandle net;
vpiHandle itr;
vpi_printf("Nets declared in module %s\n",
vpi_get_str(vpiFullName, mod));
itr = vpi_iterate(vpiNet, mod);
while (net = vpi_scan(itr))
{
vpi_printf("\t%s", vpi_get_str(vpiName, net));
if (vpi_get(vpiVector, net))
{
vpi_printf(" of size %d\n", vpi_get(vpiSize, net));
}
else vpi_printf("\n");
}
}
2.35 vpi_sim_control()
The VPI routine vpi_sim_control shall be used to pass information from user code to Verilog simulator. All standard compliant simulators must support the following three operations:
vpiStop - cause $stop built-in Verilog system task to be executed upon return of user function. This operation shall be passed one additional diagnostic message level integer argument that is the same as the argument passed to $stop (see 10.4.2).
vpiFinish - cause $finish built-in Verilog system task to be executed upon return of user function. This operation shall be passed one additional diagnostic message level integer argument that is the same as the argument passed to $finish (see 10.4.1).
vpiReset - cause $reset informative built-in Verilog system task to be executed upon return of user VPI function. This operation shall be passed three integer value arguments: stop_value, reset_value, diagnostic_level that are the same values passed to the $reset system task (see section F.7 of IEEE 1364-1995 Verilog HDL).
vpiSetInteractiveScope - cause interactive scope to be immediately changed to new scope. This operation shall be passed one argument that is a vpiHandle object with type vpiScope.
vpiRejectTransientStep - cause the current analog simulation timepoint to be rejected. This operation shall pass one argument which is the current timestep (delta).
vpiTransientFailConverge - cause the current analog simulation to continue iterating for a (valid) solution.
Because there may be a need for user VPI applications to pass simulator specific information from back from a user application to control simulation, additional operators and operation specific arguments may be defined.
|
Quadralay Corporation http://www.webworks.com Voice: (512) 719-3399 Fax: (512) 719-3606 sales@webworks.com |