How to implement math.h functions in Verilog
Contributed by
Chris Spear
Viewlogic Systems, Inc.
Here is a PLI 1.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. (According
to Chris, the hardest part of writing these system calls was to figure
out how to return real type to the Verilog environment, rather than integer ).
This code has been created and run under VCS. For implementation using
PLI2.0 in Verilog-XL, click here.
/*********************************************/
/* math.c - C routines for Verilog PLI */
#include "math.h" /* C Math routines */
#include "vcsuser.h" /* Base Verilog PLI definitions */
/* Definitions specific for math.c */
#define ARG1 1 /* First argument */
#define ARG2 2 /* Second argument */
#define RETURNV 0 /* Return value */
/****************************************************************/
/* Checktf() routine to check for a single real argument */
int math_check1() {
if (tf_nump() != ARG1) {
tf_error("Wrong number of arguments, expecting 1");
return; }
if (tf_typep(ARG1) != tf_readonlyreal &&
tf_typep(ARG1) != tf_readwritereal)
tf_error("The argument must be a real number.");
}
/****************************************************************/
/* Checktf() routine to check for a single real argument */
int math_check2() {
if (tf_nump() != ARG2) {
tf_error("Wrong number of arguments, expecting 2"); return;
}
if (tf_typep(ARG1) != tf_readonlyreal &&
tf_typep(ARG1) != tf_readwritereal)
tf_error("The first argument must be a real number.");
if (tf_typep(ARG2) != tf_readonlyreal &&
tf_typep(ARG2) != tf_readwritereal)
tf_error("The second argument must be a real number."); }
/****************************************************************/
/* Calltf routine for exp or e**x */
exp_call() { tf_putrealp (RETURNV, exp(tf_getrealp(ARG1))); }
/****************************************************************/
/* Calltf routine for natural log */
log_call() { tf_putrealp (RETURNV, log(tf_getrealp(ARG1))); }
/****************************************************************/
/* Calltf routine for log base 10 */
log10_call() { tf_putrealp (RETURNV, log10(tf_getrealp(ARG1))); }
/****************************************************************/
/* Calltf routine for pow function */
pow_call() { tf_putrealp (RETURNV, pow(tf_getrealp(ARG1), tf_getrealp(ARG2))); }
/****************************************************************/
/* Calltf routine for sine function */
sin_call() { tf_putrealp (RETURNV, sin(tf_getrealp(ARG1))); }
/****************************************************************/
/* Calltf routine for sqrt function */
sqrt_call() { tf_putrealp (RETURNV, sqrt(tf_getrealp(ARG1))); }
List1: Listing of the C code
$exp check=math_check1 call=exp_call size=r
$log check=math_check1 call=log_call size=r
$log10 check=math_check1 call=log10_call size=r
$pow check=math_check2 call=pow_call size=r
$sin check=math_check1 call=sin_call size=r
$sqrt check=math_check1 call=sqrt_call size=r
List2 : The math.tab file
module math;
real x;
initial
begin
$display("$exp(2.0) = %f", $exp(2.0));
$display("$log(44.0) = %f", $log(44.0));
$display("$log10(100.0) = %f", $log10(100.0));
$display("$log10(555.0) = %f", $log10(555.0));
$display("$pow(3.1, 4.1) = %f", $pow(3.1, 4.1));
$display("$sin(3.14159) = %f", $sin(3.14159));
$display("$sqrt(169.0) = %f", $sqrt(169.0));
end
endmodule // math.v
List3 : The sample verilog file using the system call
#!/bin/csh
vcs -R -Mupdate math.v -P math.tab -l vcs.log \
math.c -CFLAGS "-I$VCS_HOME/`vcs -platform`/lib"
$exp(2.0) = 7.389056
$log(44.0) = 3.784190
$log10(100.0) = 2.000000
$log10(555.0) = 2.744293
$pow(3.1, 4.1) = 103.414859
$sin(3.14159) = 0.000003
$sqrt(169.0) = 13.000000
List4 : Running the simulation
|