Documente Academic
Documente Profesional
Documente Cultură
VPI
Verilog Procedural Interface(VPI)
PLI2.0: the third generation of PLI library function Remove the inconsistency and incompleteness in both tf and acc routines in PLI1.0
Can not use tf or acc routines to read the condition that makes a while loop to terminate.
Functions in PLI1.0 and PLI2.0 are independent of each other and can co-exist in the same user application.
sizetf
Returns an integer which is same as the number of bits in the returned value of the system call
calltf
The main function which implements the functionality of the system call
compiletf
Initialize a set of variables which can be used later during the entire simulation
typedef struct t_vpi_systf_data { PLI_INT32 type; /* vpiSysTask, vpiSysFunc */ PLI_INT32 sysfunctype; /* vpiSysTask, vpi[Int,Real,Time,Sized, SizedSigned]Func */ PLI_BYTE8 *tfname; /* first character must be `$' */ PLI_INT32 (*calltf)(PLI_BYTE8 *); /* the calltf function name */ PLI_INT32 (*compiletf)(PLI_BYTE8 *); /* the compiletf function name */ PLI_INT32 (*sizetf)(PLI_BYTE8 *); /* for sized function callbacks only */ PLI_BYTE8 *user_data; } s_vpi_systf_data, *p_vpi_systf_data;
A simple exampleexample$add_int()
#include <stdio.h> #include "vpi_user.h" #include "vpi_user_cds.h" /******************************************** * The user C function add_int_calltf() * ********************************************/ int add_int_calltf(); int add_int_calltf() { pintrf(Enter the first integer:; scanf(%d, &n1); printf(Enter the second integer:); scanf(%d, &n2); printf(The sum of two integers: %d\n, n1+n2); }
/******************************** * The registration function * *******************************/ void registration(); void registration() /* Place all the function registration here */ { s_vpi_systf_data task_data_s; /*declare the structure */ task_data_s.type = vpiSysTask; /* No return value for out system call */ task_data_s.tfname =$add_int; /* HDL task name */ task_data_s.calltf = add_int_call_tf; /* The calltf routine */ task_data_s.compiletf = NULL; /* No function, enter NULL */ vpi_register_systf(&task_data_s); /* Registering the task */ } /* ********************************************************** The start-up array, the last element must be a zero. * *************************************************************/ void (*vlog_startup_routines[]) () = {registration, 0};
A simple example- $set_values() example#include "vpi_user.h" #include "vpi_user_cds.h" #include "set_values.h" static s_vpi_systf_data systfList[] = { {vpiSysTask, 0, "$set_values", set_values_calltf, set_values_checktf, 0, 0}, {0}, }; void setup_set_value_callbacks() { p_vpi_systf_data systf_data_p = &(systfList[0]); while (systf_data_p->type) { vpi_register_systf(systf_data_p++); if (vpi_chk_error(NULL)) { vpi_printf("Error occurred while setting up user %s\n", "defined system tasks and functions."); return; } } } void (*vlog_startup_routines[VPI_MAXARRAY])() = { setup_set_value_callbacks, 0 /*** final entry must be 0 ***/ };
Handle declaration
vpiHandle netHandle,mod_Handle, some_Handle, yet_another_Handle
If find out a handle to an object which is in some way related to a given object
Given object: the top level module, an argument to the system call If a handle is available to an object, it is possible to get a handle to any other object related to it. Ex) If a handle is available to a net or a register, it is possible to retrieve a handle pointing to its parent module instance.
VPI handles the one-to-one and the one-to-many relationships vpi_handle_multi(): the many-to-one relation
One-toOne-to-one relationship
Ex) a register and its parent module instance
There can be only one module containing that particular register.
A handle to the second object can be obtained using the library function vpi_handle() and the handle to the first object vpi_handle()
Take the type of relationship and the handle to the first object as its arguments and returns the handle to the second object
parent_module_of_a_reg(regHandle) vpiHandle regHandle; { vpiHandle moduleHandle; moduleHandle = vpi_handle(vpiModule, regHandle); /* moduleHandle can be used here for other purpose */ } handleDest = vpi_handle(vpiObj, handleStart); the handle handleDest to the destination object the starting object handleStart, the symbol for the destination object with a prefix vpi
One-toOne-to-many relationship
EX) the relationship between a module and the registers(or nets), a port and its bits, a module and primitive instances within it vpi_iterate() and vpi_scan()
vpi_iterate()
take the type of one-to-many relationship to traverse and a handle to a reference object as its arguments. Return an iterator handle.
vpi_scan()
Use an iterator handle as its argument in a loop to return a handle to the next object related to the reference object. When all such objects are traversed, it returns a NULL.
itrDest = vpi_iterate(vpiObj, handleStart); /*The handle to the starting object handleStart The iterator handle itrDest to the destination objects with obj The symbol for the destination object with a prefix vpi */ While(handleDest = vpi_scan(itrDest)) { /* process handleDest */ }
Example
int regs_in_a_module(moduleHandle) vpiHandle moduleHandle; { vpiHandle regItr, regHandle; regItr = vpi_iterate(vpiReg, moduleHandle); /* regItr is the iterator handle to all registers inside this module */ if(!regItr) { printf(No reg inside module\n); return 1; } else { /* In each iteration the following while loop returns a handle to the next register instantiate within the module */ while(regHandle = vpi_scan(regItr)) { /* Use regHandle here to process anything related to the register */ } } return 0; }
Method
Access a class from a given object or another class
Unlike a type such as vpiModule, a method is applicable to a general class of objects and does not depend on the type of the returned handle.
Tagged relationship
tag: predefined keyword used as the first argument for the vpi_handle() or vpi_iterate()
Allow accessing properties of the destination objects(or class) of a specific type Ex) an object of type memory: left and right ranges accessed by using the tags vpiLeftRange and vpiRightRange
The data access interface can be defined in terms of the properties associated with that object or class and the relations it has with other objects/classes The property name and the handle to the current object are passed as arguments.
int currNetType; currNetType = vpi_get(vpiDefNetType, modHandle);
modhandle: the handle to the current module vpiDefNetType: an integer property
Relationships
vpi_handle(), vpi_iterate(): one-to-one, one-to-many The type of the destination object(or, a tag or, in the case of a class, the method)
Getting simulation time Simulation related callbacks User-defined system call routines
Traversing relationships
Displaying messages Getting product invocation information Comparing objects Getting error information Freeing allocated memory
Sources
SUNGHO KWAK