diff --git a/examples/log2-vpi-common-vpi/.gitignore b/examples/log2-vpi-common-vpi/.gitignore new file mode 100644 index 0000000..55024ff --- /dev/null +++ b/examples/log2-vpi-common-vpi/.gitignore @@ -0,0 +1,2 @@ +*.o +*.vpi diff --git a/examples/log2-vpi-common-vpi/utest.vh b/examples/log2-vpi-common-vpi/utest.vh new file mode 100644 index 0000000..fc316ce --- /dev/null +++ b/examples/log2-vpi-common-vpi/utest.vh @@ -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 diff --git a/examples/log2-vpi-common-vpi/vpi_log2.c b/examples/log2-vpi-common-vpi/vpi_log2.c new file mode 100644 index 0000000..41aff13 --- /dev/null +++ b/examples/log2-vpi-common-vpi/vpi_log2.c @@ -0,0 +1,67 @@ +#include +#include +#include + +/* --------------------------- 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}; diff --git a/examples/log2-vpi-common-vpi/vpi_log2.sv b/examples/log2-vpi-common-vpi/vpi_log2.sv new file mode 100644 index 0000000..a579637 --- /dev/null +++ b/examples/log2-vpi-common-vpi/vpi_log2.sv @@ -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 diff --git a/examples/log2-vpi-common-vpi/vpi_log2.utest b/examples/log2-vpi-common-vpi/vpi_log2.utest new file mode 100644 index 0000000..acf6f64 --- /dev/null +++ b/examples/log2-vpi-common-vpi/vpi_log2.utest @@ -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)) diff --git a/examples/log2-vpi/utest.vh b/examples/log2-vpi/utest.vh new file mode 100644 index 0000000..fc316ce --- /dev/null +++ b/examples/log2-vpi/utest.vh @@ -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 diff --git a/examples/log2-vpi/vpi_log2.c b/examples/log2-vpi/vpi_log2.c new file mode 100644 index 0000000..41aff13 --- /dev/null +++ b/examples/log2-vpi/vpi_log2.c @@ -0,0 +1,67 @@ +#include +#include +#include + +/* --------------------------- 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}; diff --git a/examples/log2-vpi/vpi_log2.sv b/examples/log2-vpi/vpi_log2.sv new file mode 100644 index 0000000..a579637 --- /dev/null +++ b/examples/log2-vpi/vpi_log2.sv @@ -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 diff --git a/examples/log2-vpi/vpi_log2.utest b/examples/log2-vpi/vpi_log2.utest new file mode 100644 index 0000000..d101f83 --- /dev/null +++ b/examples/log2-vpi/vpi_log2.utest @@ -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))) diff --git a/examples/simple-counter/.gitignore b/examples/simple-counter/.gitignore new file mode 100644 index 0000000..ccf6a49 --- /dev/null +++ b/examples/simple-counter/.gitignore @@ -0,0 +1 @@ +/work