How to implement math.h functions in Verilog
Contributed by
Steve Meyer
Pragmatic C Software Corp.
Here is a PLI 2.0 example. The code below shows a set of functions,
used by their respective system calls. Together they achieve the same functionality
that of their corresponding library function of math.h in C.
The most useful feature to learn from this code is, perhaps, its simplicity.
There are not more than 10-12 lines of actual code in the application.
This shows the power of PLI when it comes to writing application within
Verilog.
This code has been created and run using PLI2.0. For implementation
using PLI1.0 in VCS, click here.
#include <stdio.h>
#include <math.h>
#include "veriuser.h"
#include "cv_veriuser.h"
#include "vpi_user.h"
#include "cv_vpi_user.h"
/* prototypes */
static int my_log10(void);
extern void register_my_systfs(void);
static int my_log10(void)
{
double d1, d2;
vpiHandle systfref, argsiter, argh;
struct t_vpi_value wrkval;
/* get system function that invoked C routine */
systfref = vpi_handle(vpiSysTfCall, NULL);
/* get iterator (list) of passed arguments */
argsiter = vpi_iterate(vpiArgument, systfref);
/* get the one argument - add loop for more args */
argh = vpi_scan(argsiter);
/* get the argument value */
wrkval.format = vpiRealVal;
vpi_get_value(argh, &wrkval);
d1 = wrkval.value.real;
/* any C library function can go here */
d2 = log10(d1);
/* return value by assigning to calling systf handle */
wrkval.value.real = d2;
vpi_put_value(systfref, &wrkval, NULL, vpiNoDelay);
return(0);
}
/* my boiler plate for registering system tasks */
void (*vlog_startup_routines[]) () =
{
register_my_systfs,
0
};
/*
* register my user system tasks and functions
*/
void register_my_systfs(void)
{
p_vpi_systf_data systf_data_p;
static s_vpi_systf_data systf_data_list[] = {
{ vpiSysFunc, vpiSysFuncReal, "$log10", my_log10, NULL, NULL, NULL },
{ 0, 0, NULL, NULL, NULL, NULL, NULL }
};
systf_data_p = &(systf_data_list[0]);
while (systf_data_p->type != 0) vpi_register_systf(systf_data_p++);
}
module top;
initial
begin
// try some easy logs
$display("log 1.0 = %g", $log10(1.0));
$display("log 10.0 = %g", $log10(10.0));
$display("log 100.0 = %g", $log10(100.0));
end
endmodule
List1 : The sample verilog file using the system call
CVER_1.80_1 of 05/22/98 (Linux-elf).
Copyright (c) 1991-1998 Pragmatic C Software Corp.
Compiling source file "vlog10.v"
Highest level modules:
top
log 1.0 = 0
log 10.0 = 1
log 100.0 = 2
1 simulation events and 0 declarative immediate assigns processed.
3 behavioral statements executed (0 procedural suspends).
List2 : Running the simulation
|