Add VPI examples
This commit is contained in:
parent
d298a14bff
commit
2c8c60429c
2
examples/log2-vpi-common-vpi/.gitignore
vendored
Normal file
2
examples/log2-vpi-common-vpi/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.o
|
||||||
|
*.vpi
|
||||||
16
examples/log2-vpi-common-vpi/utest.vh
Normal file
16
examples/log2-vpi-common-vpi/utest.vh
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
`ifndef UTEST_VERILOG_DEFINES
|
||||||
|
`define UTEST_VERILOG_DEFINES
|
||||||
|
|
||||||
|
// Log level string prefixes for use with $display function.
|
||||||
|
// Example usage: $display("%sError message", `LOG_ERR);
|
||||||
|
`define LOG_INFO "INFO#"
|
||||||
|
`define LOG_WARN "WARN#"
|
||||||
|
`define LOG_ERR "FAIL#"
|
||||||
|
|
||||||
|
// Dirty hacked redefine of $display function. Must be used with two parentheses.
|
||||||
|
// Example usage: `log_info(("Information message"));
|
||||||
|
`define log_quiet(msg) begin $display({$sformatf msg}); end
|
||||||
|
`define log_info(msg) begin $display({`LOG_INFO, $sformatf msg}); end
|
||||||
|
`define log_warn(msg) begin $display({`LOG_WARN, $sformatf msg}); end
|
||||||
|
`define log_error(msg) begin $display({`LOG_ERR, $sformatf msg}); end
|
||||||
|
`endif
|
||||||
67
examples/log2-vpi-common-vpi/vpi_log2.c
Normal file
67
examples/log2-vpi-common-vpi/vpi_log2.c
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <vpi_user.h>
|
||||||
|
|
||||||
|
/* --------------------------- VPI INTERFACE -------------------------------- */
|
||||||
|
|
||||||
|
#define MAX_ARGS 8
|
||||||
|
|
||||||
|
static int calltf(char *user_data)
|
||||||
|
{
|
||||||
|
vpiHandle systfref, arg_iter;
|
||||||
|
vpiHandle arg_hndl[MAX_ARGS];
|
||||||
|
struct t_vpi_value argval;
|
||||||
|
int arg_cnt = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_ARGS; i++)
|
||||||
|
arg_hndl[i] = NULL;
|
||||||
|
|
||||||
|
systfref = vpi_handle(vpiSysTfCall, NULL);
|
||||||
|
arg_iter = vpi_iterate(vpiArgument, systfref);
|
||||||
|
|
||||||
|
/* ---- Get agruments ---- */
|
||||||
|
if (arg_iter != NULL)
|
||||||
|
while (arg_cnt < MAX_ARGS &&
|
||||||
|
NULL != (arg_hndl[arg_cnt] = vpi_scan(arg_iter)))
|
||||||
|
arg_cnt++;
|
||||||
|
|
||||||
|
// function $log2
|
||||||
|
if (arg_cnt != 1)
|
||||||
|
vpi_printf("ERROR: $log2() wrong argument count\n");
|
||||||
|
else {
|
||||||
|
double arg, ret;
|
||||||
|
|
||||||
|
// get argument
|
||||||
|
argval.format = vpiRealVal;
|
||||||
|
vpi_get_value(arg_hndl[0], &argval);
|
||||||
|
arg = argval.value.real;
|
||||||
|
|
||||||
|
ret = log2(arg);
|
||||||
|
|
||||||
|
// put return value
|
||||||
|
argval.format = vpiRealVal;
|
||||||
|
argval.value.real = ret;
|
||||||
|
vpi_put_value(systfref, &argval, NULL, vpiNoDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_ARGS; i++)
|
||||||
|
if (arg_hndl[i]) vpi_free_object(arg_hndl[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void register_interface(void)
|
||||||
|
{
|
||||||
|
s_vpi_systf_data tf_data;
|
||||||
|
|
||||||
|
tf_data.type = vpiSysFunc;
|
||||||
|
tf_data.sysfunctype = vpiRealFunc;
|
||||||
|
tf_data.compiletf = 0;
|
||||||
|
tf_data.sizetf = 0;
|
||||||
|
tf_data.calltf = calltf;
|
||||||
|
tf_data.tfname = "$log2";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*stfunc)(void);
|
||||||
|
stfunc vlog_startup_routines[] = {register_interface, 0};
|
||||||
22
examples/log2-vpi-common-vpi/vpi_log2.sv
Normal file
22
examples/log2-vpi-common-vpi/vpi_log2.sv
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
`timescale 1ps/1ps
|
||||||
|
|
||||||
|
`include "utest.vh"
|
||||||
|
|
||||||
|
module vpi_log2 #(parameter ARGUMENT = 1.0,
|
||||||
|
parameter SIGMA = 1e-6);
|
||||||
|
real dut, gold;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
gold = $ln(ARGUMENT) / $ln(2);
|
||||||
|
dut = $log2(ARGUMENT);
|
||||||
|
|
||||||
|
`log_info(("Gold: %0f", gold));
|
||||||
|
`log_info((" DUT: %0f", dut));
|
||||||
|
|
||||||
|
if ($abs(gold - dut) > SIGMA)
|
||||||
|
`log_error(("FAIL"));
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // vpi_log2
|
||||||
25
examples/log2-vpi-common-vpi/vpi_log2.utest
Normal file
25
examples/log2-vpi-common-vpi/vpi_log2.utest
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
;; -*- scheme -*-
|
||||||
|
|
||||||
|
;; Uses one common VPI module compiled in the testbench base directory
|
||||||
|
|
||||||
|
(let ((top "vpi_log2"))
|
||||||
|
;; compile VPI module in the base directory
|
||||||
|
(if (utest/iverilog-compile-vpi "vpi_log2.c"
|
||||||
|
#:output-dir (utest/base-path)
|
||||||
|
#:name top #:libs "m")
|
||||||
|
(map
|
||||||
|
(lambda (arg)
|
||||||
|
(utest/tb
|
||||||
|
((format "log2_~a" arg))
|
||||||
|
|
||||||
|
(utest/run-simulation-iverilog
|
||||||
|
"vpi_log2.sv"
|
||||||
|
top
|
||||||
|
|
||||||
|
#:parameters `((ARGUMENT ,arg))
|
||||||
|
#:vpimods top
|
||||||
|
;; VPI modules search path
|
||||||
|
#:vpipaths (utest/base-path))))
|
||||||
|
(iota 20))
|
||||||
|
|
||||||
|
#f))
|
||||||
16
examples/log2-vpi/utest.vh
Normal file
16
examples/log2-vpi/utest.vh
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
`ifndef UTEST_VERILOG_DEFINES
|
||||||
|
`define UTEST_VERILOG_DEFINES
|
||||||
|
|
||||||
|
// Log level string prefixes for use with $display function.
|
||||||
|
// Example usage: $display("%sError message", `LOG_ERR);
|
||||||
|
`define LOG_INFO "INFO#"
|
||||||
|
`define LOG_WARN "WARN#"
|
||||||
|
`define LOG_ERR "FAIL#"
|
||||||
|
|
||||||
|
// Dirty hacked redefine of $display function. Must be used with two parentheses.
|
||||||
|
// Example usage: `log_info(("Information message"));
|
||||||
|
`define log_quiet(msg) begin $display({$sformatf msg}); end
|
||||||
|
`define log_info(msg) begin $display({`LOG_INFO, $sformatf msg}); end
|
||||||
|
`define log_warn(msg) begin $display({`LOG_WARN, $sformatf msg}); end
|
||||||
|
`define log_error(msg) begin $display({`LOG_ERR, $sformatf msg}); end
|
||||||
|
`endif
|
||||||
67
examples/log2-vpi/vpi_log2.c
Normal file
67
examples/log2-vpi/vpi_log2.c
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <vpi_user.h>
|
||||||
|
|
||||||
|
/* --------------------------- VPI INTERFACE -------------------------------- */
|
||||||
|
|
||||||
|
#define MAX_ARGS 8
|
||||||
|
|
||||||
|
static int calltf(char *user_data)
|
||||||
|
{
|
||||||
|
vpiHandle systfref, arg_iter;
|
||||||
|
vpiHandle arg_hndl[MAX_ARGS];
|
||||||
|
struct t_vpi_value argval;
|
||||||
|
int arg_cnt = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_ARGS; i++)
|
||||||
|
arg_hndl[i] = NULL;
|
||||||
|
|
||||||
|
systfref = vpi_handle(vpiSysTfCall, NULL);
|
||||||
|
arg_iter = vpi_iterate(vpiArgument, systfref);
|
||||||
|
|
||||||
|
/* ---- Get agruments ---- */
|
||||||
|
if (arg_iter != NULL)
|
||||||
|
while (arg_cnt < MAX_ARGS &&
|
||||||
|
NULL != (arg_hndl[arg_cnt] = vpi_scan(arg_iter)))
|
||||||
|
arg_cnt++;
|
||||||
|
|
||||||
|
// function $log2
|
||||||
|
if (arg_cnt != 1)
|
||||||
|
vpi_printf("ERROR: $log2() wrong argument count\n");
|
||||||
|
else {
|
||||||
|
double arg, ret;
|
||||||
|
|
||||||
|
// get argument
|
||||||
|
argval.format = vpiRealVal;
|
||||||
|
vpi_get_value(arg_hndl[0], &argval);
|
||||||
|
arg = argval.value.real;
|
||||||
|
|
||||||
|
ret = log2(arg);
|
||||||
|
|
||||||
|
// put return value
|
||||||
|
argval.format = vpiRealVal;
|
||||||
|
argval.value.real = ret;
|
||||||
|
vpi_put_value(systfref, &argval, NULL, vpiNoDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_ARGS; i++)
|
||||||
|
if (arg_hndl[i]) vpi_free_object(arg_hndl[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void register_interface(void)
|
||||||
|
{
|
||||||
|
s_vpi_systf_data tf_data;
|
||||||
|
|
||||||
|
tf_data.type = vpiSysFunc;
|
||||||
|
tf_data.sysfunctype = vpiRealFunc;
|
||||||
|
tf_data.compiletf = 0;
|
||||||
|
tf_data.sizetf = 0;
|
||||||
|
tf_data.calltf = calltf;
|
||||||
|
tf_data.tfname = "$log2";
|
||||||
|
vpi_register_systf(&tf_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*stfunc)(void);
|
||||||
|
stfunc vlog_startup_routines[] = {register_interface, 0};
|
||||||
22
examples/log2-vpi/vpi_log2.sv
Normal file
22
examples/log2-vpi/vpi_log2.sv
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
`timescale 1ps/1ps
|
||||||
|
|
||||||
|
`include "utest.vh"
|
||||||
|
|
||||||
|
module vpi_log2 #(parameter ARGUMENT = 1.0,
|
||||||
|
parameter SIGMA = 1e-6);
|
||||||
|
real dut, gold;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
gold = $ln(ARGUMENT) / $ln(2);
|
||||||
|
dut = $log2(ARGUMENT);
|
||||||
|
|
||||||
|
`log_info(("Gold: %0f", gold));
|
||||||
|
`log_info((" DUT: %0f", dut));
|
||||||
|
|
||||||
|
if ($abs(gold - dut) > SIGMA)
|
||||||
|
`log_error(("FAIL"));
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // vpi_log2
|
||||||
19
examples/log2-vpi/vpi_log2.utest
Normal file
19
examples/log2-vpi/vpi_log2.utest
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
;; -*- scheme -*-
|
||||||
|
|
||||||
|
;; Compile VPI module for each test
|
||||||
|
|
||||||
|
(let ((top "vpi_log2"))
|
||||||
|
(map
|
||||||
|
(lambda (arg)
|
||||||
|
(utest/tb
|
||||||
|
((format "log2_~a" arg))
|
||||||
|
|
||||||
|
(if (utest/iverilog-compile-vpi "vpi_log2.c" #:name top #:libs "m")
|
||||||
|
(utest/run-simulation-iverilog
|
||||||
|
"vpi_log2.sv"
|
||||||
|
top
|
||||||
|
#:parameters `((ARGUMENT ,arg))
|
||||||
|
#:vpimods top)
|
||||||
|
|
||||||
|
#f)))
|
||||||
|
(iota 20)))
|
||||||
1
examples/simple-counter/.gitignore
vendored
Normal file
1
examples/simple-counter/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/work
|
||||||
Loading…
x
Reference in New Issue
Block a user