Previous
Contents
Next
8. PLI 1.0 (acc_/tf_) routines
8.1 PLI differences
At this point we support PLI 1.0. We also don't
fully support the PLI routines that support:
- $save/$restart (tf_write_save/tf_read_restart)
- specify blocks (many acc_* routines)
- CLI support - (acc_*_interactive* etc)
We do support $dumpvars and friends but you must include "-P /usr/local/lib/vcomp/vcd.tab"
in your vcomp command line if you wish to use them.
8.2 Writing your own PLIs
Writing your own PLIs is relatively simple and encouraged. Simply compile
up you PLI on our system using GCC to make a .o file (use the veriuser.h and
acc_user.h that we provide in /usr/include). Include the name of the
.o file in the vcomp command line along with your source files.
Next create a PLI table file to describe each PLI routine's interface, our file's
format is compatible with those used by VCS® - include this file in the
vcomp command line introduced with a '-P' flag. You can include as many -P files as
you wish.
PLI table files have one line for each routine, it starts with the full name
of the PLI routine ('$' included), this is followed by one or more of the following
attributes:
- data=<number> - an integer value that's passed as the second parameter to
PLI callback routines
- check=<entry-point> - entry point for the 'check' routines - these are called
at the beginning of time prior to the start of simulation
- call=<entry-point> - call routine
- misc=<entry-point> - misc routine
- vpi=<entry-point> - vpi init routine (non-standard - vcomp only, not VCS®)
- size=<number> - size (in bits) of the value returned by a real function
- size=r - indicates that the routine is a function that returns a real result
- signed - indicates that the routine returns a signed value (required for v2k - non-standard - vcomp only, not VCS®)
- nocallback - add this is you will not need to schedule value change callbacks
on the parameters passed to instances of this task - we recommend that you
always add this if possible - because not adding it means that many compiler
optimizations are inhibited for any variable passed to an instance
A <entry-point> above is the name of a C-language routine you have compiled
into the .o file you created. Entry points you don't declare will never get called.
Finally the line can optionally contains an access capabilities field that describes
what sort of simulation accesses (via tf_* or acc_* routines) that a PLI task
may wish to accomplish. The format of this field looks like one of the following:
- acc+=<access list> - add to the global access list
- acc-=<access list> - remove from the access list (seldom used)
- acc:=<access list> - set the global access list (also seldom used)
The <access list> part consists of a comma separated list of capabilities
followed by a colon and then a comma separated list of scopes to which they will apply.
The capabilities selected can grossly change the amount of information collected for use at run time,
the amount of storage required for variables at runtime and most importantly
the number of different optimizations that the compiler can perform. For this reason
you should specify the minimum capabilities that you need, those marked '[*]' in the list
below should be particularly avoided. The supported capabilities are:
- read - you wish to be able to read values in the specified scopes
- read_write - you wish to be able to read and write values in the specified scopes
- callback - you wish to be able to have value change callbacks for all variables
in the specified scopes [*]
- callback_all - you wish to be able to have value change callbacks for all variables
and primitive terminals in the specified scopes [*]
- force - you wish to be able to force variables in the specified scopes [*]
- timing_check_backannotation - you wish to be able to do timing check back annotation
for variables in the specified scopes (not yet supported)
- gate_backannotation - you wish to be able to do gate back annotation
for variables in the specified scopes (not yet supported)
- module_path_backannotation - you wish to be able to do module path back annotation
for variables in the specified scopes (not yet supported)
- module_input_port_backannotation - you wish to be able to do module input port back annotation
for variables in the specified scopes (not yet supported)
- module_input_port__bitbackannotation - you wish to be able to do module input port bit back annotation
for variables in the specified scopes (not yet supported)
A scope can be the name of an instance, an instance name followed by a '+' indicating
that instance an all it's children, '*' indicating all module instances, '%TASK' indicating
only the modules in which this PLI task or function is used or %CELL meaning only
those modules tagged with a `celldefine macro.
8.3 An example
Here's a simple example of a couple of PLI routines, how to add them
to our environment and how to use them.
First the C source of the PLI routines in test.c:
#include
#include
#include
//
// first a simple example showing a simple C call
// it prints out the 'data' value of 1234 declared in the table
//
int
call_hello_world(int reason, int data)
{
printf("hello world\n"); // simple version
tf_message(ERR_MESSAGE, "User", "Hi Mom", "Hello world - data was %d\n", data);
}
//
// Now a more complex version - it attaches a VCD callback
// to the parameter passed and reports when it changes
//
int
check_listen(int reason, int data)
{
if (tf_nump() != 1) {
tf_message(ERR_ERROR, "User", "BAD", "must pass 1 parameter to $listen");
}
}
int
call_listen(int reason, int data)
{
tf_asynchon(); // enable async callbacks when parameters change
}
int
misc_listen(int reason, int data, int param)
{
switch (reason) {
case reason_paramvc:
tf_rosynchronize(); // wait until it stops changing at the end of the
break; // current time period
case reason_rosynch:
printf("value changed to %d\n", tf_getp(1));
break;
}
}
Compile it with "gcc -c test.c". Next create a PLI table file 'test.tab'
containing:
$hello_world call=call_hello_world data=1234 nocallback
$listen check=check_listen call=call_listen misc=misc_listen acc+=callback:*
And a verilog® test bench in test.v:
module test;
reg [7:0]a;
integer i;
initial begin
a = 0;
$hello_world;
$listen(a);
for (i = 0; i < 10; i=i+1)
#10 a = a + 1;
end
endmodule
Now use vcomp to compile them with the command "vcomp -o test test.v test.o -P test.tab".
Finally run the binary 'test' to give:
hello world
MESSAGE Hello world - data was 1234 [User-Hi Mom]
File 'pt.v', line 8
value changed to 1
value changed to 2
value changed to 3
value changed to 4
value changed to 5
value changed to 6
value changed to 7
value changed to 8
value changed to 9
value changed to 10
Notice how $hello_world printed out 'hello world' two different ways, while
$listen attached a value-change callback to the variable 'a' and printed out it's
new value every time it changed.
Previous
Contents
Next
|