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.


Previous | Next


Step 4: tf routines

The checktf routine
Usually it is a good practice to check two things in a PLI routine

  • whether the total number of parameters are same as what is expected and
  • whether each parameter is of the required type.
For example, in our case, we expect only one parameter to be passedand it must be a register type. This is done in the following function my_checktf().

int my_checktf() {
if (tf_nump() != 1) {
if (tf_typep(1) != tf_readwrite) {
tf_error ("The argument must be a register type\n");

The functions starting with tf_ are the library functions and commonly known as utility routines. (There is another set of library routines which start with acc_ and known as access routines. However, since in the present case only utility routines would be used, we will postpone the discussion of access routines to a later chapter) The library functions that we have used in the above function and their usages are given below.

  • tf_nump(): Determines how many parameters you are passing.
  • tf_typep(): Determines the type of the parameter by its position in the system call (in our case $print_reg) in the Verilog code. Thus tf_typep(1) gives the type of the first parameter, tf_typep(2) will get the type of the second parameter etc. In case the parameter does not exist(like tf_typep(2) in our case) tf_typep() returns error. Since we expect register to be passed, the type should be tf_readwrite. In case of a wire,the type should have been tf_readonly. Note that, to avoid error condition checking, it is a good idea to check the number of parameters first followed by their types.
  • tf_error(): Prints an error message and signals to the simulator to increment its error count.
These library functions and constants are defined in the header files that we included at the top.

The calltf routine
The calltf function is the heart of the PLI routine. Usuallyt he main job of the PLI routine is performed through this function. In our case it should read the value of the register and then print it.

int my_calltf(){
io_printf("$print_reg : The value of the specified register is %d", tf_getp(1));

The library functions used above and their usages are given below.

  • io_printf(): Does the same thing what printf() does in normal C programming- printing the value on standard output.
  • tf_getp(): Gives the integer value of the register.
In real life routines, however the calltf function is the most complicatedand often runs for several hundred lines.
For convenience, let us see the whole program at one place.

#include <veriuser.h>
#include <vxl_veriuser.h>
int my_calltf(), my_checktf();
char *veriuser_version_str ="\n\
($print_reg) \n\
int (*endofcompile_routines[])() ={0};
bool err_intercept(level, facility,code)
int level; char * facility; char *code;
{ return (true); }
s_tfcell veriusertfs[] =
/*** Template for an entry :
{usertask, 0, my_checktf, 0,my_calltf, 0, "$print_reg"},
{0} /* Final entry must be zero*/

int my_checktf() {
if (tf_nump() != 1) {
tf_error ("$print_reg:");
tf_error ("Usage : $print_reg(register_name);\n");
if (tf_typep(1) != tf_readwrite){
tf_error ("$print_reg:");
tf_error ("The argument must be a register type\n");

void my_calltf(){
io_printf("$print_reg : The value of the specified register is %d", tf_getp(1));

Previous | Next Share/Save/Bookmark

Verification Management
Join Verification Management Group

Talk UVM with Friends
Shop Amazon - Contract Cell Phones & Service Plans

Fun Stuffs!