Sunteți pe pagina 1din 23

Principles of PLI

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.

A PLI Routine Using VPI


User C functions: applications
The main body of a PLI routine Implement the functionality of the corresponding system call Include a header file called vpi_user.h A set of pre-specified but user-defined functions
sizetf, calltf, compiletf: The actual name is completely user-defined.

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

A PLI Routine Using VPI


The registration function
Registering the associated functions and other properties of a system call
First: the names of the associated functions and other properties of the system call are assigned to different fields of a structure of type s_vpi_systf_data Second: using the library function vpi_register_systf()

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 PLI Routine Using VPI


The start-up array vlog_startup_routines[]
Lists all the registration functions Presents them to the simulator An array of pointers to functions returning void types The last element in this array should be zero.

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 ***/ };

Integrating user application with Verilog simulator


The same as what has been described in Chapter 2, Section 6.1 Verilog-XL
vconfig generate a shell script generate the compiled binary

Handle and its declaration


handle: the basic data structure for all data access
Set up a handle to that object to access the properties of an object An equivalent of a C language pointing to the data structure of the object A way to use indirect addressing All references to that object such as getting its value, traversing a relationship etc. using its handle Whenever an object is required to be passed to a function, its handle is passed as an argument Defined in vpi_user.h as vpiHande Irrespective of the nature of the object

The data type of a handle

Handle declaration
vpiHandle netHandle,mod_Handle, some_Handle, yet_another_Handle

Associating a handle to an object


Associate the handle with the object If we know the name of the object and the handle to its scope
Vpi_handle_by_name() Ex) handle my_handle; my_handle = vpi_handle_by_name(my_reg, scope_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.

Relationship between two objects


Relationship between two objects
Not related One-to-one. One-to-many Many-to-one

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; }

Class and method


Class: objects of similar nature
A class named primitive: object types gate, switch and UDPs

Method
Access a class from a given object or another class

How to get a handle to a member of a class starting from an object


The class regs
comprises of register and individual bit of a register array. The relationship between a register bit and its parent array of registers is one-to-one. To obtain a handle to the register array from the handle to the register bit
reg_array_handle = vpi_handle(vpiParent, reg_bit_handle); The method vpiParent is used to get the handle reg_array_handle to the parent object within the class regs.

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

Getting Handles to basic objects


How a handle can be obtained to some of the most commonly referenced objects(basic objects) without taking the help of any other handle. These objects provide a starting point for traversing a relationship.

Getting handles to the top level modules


int get_top_mods() { vpiHandle top_mod_iterator, top_mod_handle; top_mod_iterator = vpi_iterate(vpiModule, NULL); if(!top_mod)iterator) { printf(No top-level module found\n); return 1; } else while(top_mod_handle = vpi_scan(top_mod_iterator)) printf(Top module: %s\n, vpi_get_str(vpiName, top_mod_handle)); return 0 }

Getting handle to the parameters passed to the current system


int list_param() { vpiHandle tf_param_iterator, tf_param_handle; vpiHandle syscall_handle; int pin = 1; syscall_handle = vpi_handle(vpiSysTfCall, NULL); if(!syscall_handle) { printf(No handle to the system call\n); return 1; } else { tf_param_iterator = vpi_iterate(vpiArgument,syscall_handle); if(!tf_param_iterator) { printf(No arg. to the system call\n); return 1; } else while(tf_param_handle = vpi_scan(tf_param_iterator)) printf(Parameter %d: %s\n, pin++, vpi_get_str(vpiName, tf_param_handle)); return 0; }

Design Objects-Properties and Relationships Objects Properties


Three categories
Boolean and integer: vpi_get() String: vpi_string_get() Complex

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)

Remainders: each type of object and class defined in Verilog HDL


Describe the properties and relations associated with it using a tabular format
The type/method for each object/class is mentioned in parenthesis along with its name in the header Ex) object Module: associated with a type vpiModule
The first argument of the vpi_handle() or vpi_iterate()

Summary of functions and their properties


Purpose Accessing an object from its properties VPI function vpi_handle_by_name() vpi_handle_by_index() vpi_get() vpi_get_str() vpi_get_value() vpi_put_value() vpi_get_delays() vpi_put_delays() vpi_get_time() vpi_register_cb() vpi_remove_cb() vpi_register_systf() vpi_get_systf_info() vpi_handle() vpi_iterate() vpi_scan() vpi_handle_multi() vpi_mcd_open() vpi_mcd_close() vpi_mcd_print() vpi_mcd_name() vpi_printf() vpi_get_vlog_info() vpi_compare_objects() vpi_chk_error() vpi_free_objects()

Accessing properties of an object

Getting simulation time Simulation related callbacks User-defined system call routines

Traversing relationships

File related activities

Displaying messages Getting product invocation information Comparing objects Getting error information Freeing allocated memory

Sources

SUNGHO KWAK

S-ar putea să vă placă și