|
This is an excerpt from the Chapter 1 of the book
Principles of Verilog PLI by Swapnajit Mittra
published from Kluwer Academic Publishers. ISBN: 0-7923-8477-6
[All copyright reserved. No portion of this text can be used for
for commercial purpose without explicit permission from
the author nor can it be used for re-print in hardcopy
or electronic form.] Order the book here.
|
PLI - A QUICK TOUR
Previous | Next
FOUR STEPS FOR WRITING A PLI ROUTINE
Step 3 of 4: The essential data structure
There are a number of data structures that must be defined in a PLI
program. These are the variables through which Verilog communicates with
the C code. Although OVI (Open Verilog International - the organization
responsible for standardizing Verilog) recommends only one mandatory datastructure
(veriusertfs), the exact number
and syntax of these data structures vary from simulator to simulator. Verilog-XL
from Cadence Design Systems, for example, requires four such data structures
and functions for any PLI routine to work, whereas VCS, from Chronologic
needs none, but needs a separate input file. Going by the popularity ofVerilog
XL, we are going to mention all four of them here; the users of Chronologic
VCS and Veriwell may ignore the them. These data structures, in the order
they should appear, are given below.
veriuser_version_str
This character pointer can be used to indicate a version of the compiled
Verilog for your reference. It can be also set to NULL string.The string
appears on standard out as well as goes to the Verilog log file when you
run your compiled Verilog. A typical example of using it is shown below.
char *veriuser_version_str ="\n\
=============================\n\
VERILOG PLI FIRST_ATTEMPT \n\
($print_reg) \n\
=============================\n";
endofcompile_routines
This data structure, as the name suggests, can be used for declaring
functions that will be invoked at the end of the simulation. The present
example does not need it. Nonetheless there has to be a default definition
as shown below.
int (*endofcompile_routines[])() ={0};
err_intercept
This function, which returns either true or false (i.e. a boolean type),
can be used to enhance the error detection mechnism of the code and can
be ignored for small applications. A typical example of this routine would
be as shown below.
bool err_intercept(level, facility,code)
int level; char * facility; char *code;
{ return (true); }
veriusertfs
The main interaction between the C-code that one writes and the Verilog
simulator is done through a table. The Verilog simulator looks at this
table and figures out the properties that the system call corresponding
to this PLI routine would be associated with. This array, called veriusertfs
in Verilog XL, may not be called by any other name as the simulator
will not recognize that. Each element of veriusertfs has a distinct function
and is very important to achieve the overall objective of writing the PLI
routine.
The number of rows in veriusertfs is same as that of the number of user-defined
system calls, plus one for the last entry, which is a mandatory {0} .
In the present case, the veriusertfs array should look like:
s_tfcell veriusertfs[] =
{
/*** Template for an entry :
{usertask|userfunction,
data,
checktf(),
sizetf(),
calltf(),
misctf(),
"$tfname"
},
***/
{usertask, 0, my_checktf, 0, my_calltf,0,
"$print_reg"},
{0} /* Final entry must be zero */
}
In the above data-structure my_checktf
and my_calltf are the names
ofthe two functions that we will use to implement the system call $print_reg.
my_checktf is the routine which
checks the validity of the passed parametersetc and my_calltf
actually executes the system call. These names are arbitrary and
could have been something else. The first entry usertask indicates that
the system call does not return anything and is equivalent to procedure
in Pascal or function returning void in C. Note that :
-
The relative positions of these names in veriusertfs are very important-
for example my_checktf (or any
other name ) has to be the 3rd element,as long as we want to use it as
a checking function.
-
Any function that we do not use (e.g. misctf
in our example. The objective of providing so many functions will
be discussed in Chapter 2) should be replaced by a '0'.
-
We need to define a separate entry in veriusertfs for each system call
in case there are more than one.
This table, in case of VCS, is written in a separate file, usually called
PLI.tab (once again the name could be anything) whose content, in the present
example, will be as shown below.
$print_reg check=my_checktf call=my_calltf
Previous | Next
|