Tests: Refactor t_vpi_time_cb to avoid shared object

This commit is contained in:
Wilson Snyder 2021-03-12 11:25:42 -05:00
parent 44478a53c2
commit 2feb46fc5d
6 changed files with 49 additions and 80 deletions

View File

@ -1011,6 +1011,7 @@ sub compile {
cmd=>[($ENV{VERILATOR_VCS}||"vcs"),
@{$param{vcs_flags}},
@{$param{vcs_flags2}},
($opt_verbose ? " -CFLAGS -DTEST_VERBOSE=1":""),
@{$param{v_flags}},
@{$param{v_flags2}},
$param{top_filename},

View File

@ -12,7 +12,7 @@
#ifndef TEST_CHECK_H_
#define TEST_CHECK_H_
extern bool errors;
extern int errors;
#ifdef TEST_VERBOSE
static bool verbose = true;
@ -23,12 +23,13 @@ static bool verbose = false;
//======================================================================
// Use cout to avoid issues with %d/%lx etc
#define TEST_CHECK(got, exp) \
if ((got) != (exp)) { \
#define TEST_CHECK(got, exp, test) \
if (!(test)) { \
std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << ": GOT = " << (got) \
<< " EXP = " << (exp) << std::endl; \
errors = true; \
++errors; \
}
#define TEST_CHECK_EQ(got, exp) TEST_CHECK(got, exp, ((got) == (exp)));
#define TEST_VERBOSE_PRINTF(format, ...) \
do { \

View File

@ -20,11 +20,8 @@
#include "TestCheck.h"
#include <dlfcn.h>
#include <iostream>
bool errors = false;
unsigned int main_time = 0;
//======================================================================
@ -52,31 +49,20 @@ int main(int argc, char** argv, char** env) {
tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
#endif
// Load and initialize the PLI application
{
const char* filenamep = VL_STRINGIFY(TEST_OBJ_DIR) "/libvpi.so";
void* lib = dlopen(filenamep, RTLD_LAZY);
void* bootstrap = dlsym(lib, "vpi_compat_bootstrap");
if (!bootstrap) {
std::string msg = std::string("%Error: Could not dlopen ") + filenamep;
vl_fatal(__FILE__, __LINE__, "main", msg.c_str());
}
((void (*)(void))bootstrap)();
}
VerilatedVpi::callCbs(cbStartOfSimulation);
topp->eval();
topp->clk = 0;
main_time += 1;
while (vl_time_stamp64() < sim_time && !Verilated::gotFinish()) {
main_time += 1;
topp->eval();
VerilatedVpi::callValueCbs();
VerilatedVpi::callTimedCbs();
TEST_CHECK(VerilatedVpi::cbNextDeadline(), main_time + 1);
topp->clk = !topp->clk;
if (main_time > 20) { // Else haven't registered callbacks
TEST_CHECK_EQ(VerilatedVpi::cbNextDeadline(), main_time + 1);
}
if ((main_time % 5) == 0) topp->clk = !topp->clk;
// mon_do();
#if VM_TRACE
if (tfp) tfp->dump(main_time);

View File

@ -10,19 +10,16 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
scenarios(simulator => 1);
$Self->{pli_filename} = "t_vpi_time_cb_c.cpp";
compile(
make_top_shell => 0,
make_main => 0,
make_pli => 1,
sim_time => 2100,
v_flags2 => ["t/t_vpi_time_cb_c.cpp"],
iv_flags2 => ["-g2005-sv -DWAVES -DIVERILOG"],
verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --vpi --no-l2name $Self->{t_dir}/t_vpi_time_cb.cpp -LDFLAGS '-ldl -rdynamic'"],
verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --vpi --no-l2name $Self->{t_dir}/t_vpi_time_cb.cpp"],
);
execute(
use_libvpi => 1,
check_finished => 1,
);

View File

@ -6,6 +6,9 @@
// Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import "DPI-C" function void dpii_init();
import "DPI-C" function void dpii_final();
module t (/*AUTOARG*/
// Inputs
clk
@ -19,15 +22,18 @@ module t (/*AUTOARG*/
// Test loop
initial begin
count = 0;
dpii_init();
end
always @(posedge clk) begin
`ifdef TEST_VERBOSE
$display("[%0t] clk", $time);
$display("[%0t] clk @ count %0d", $time, count);
`endif
count <= count + 2;
if (count == 1000) begin
if (count == 200) begin
$display("Final section");
// See C++ code: $write("*-* All Finished *-*\n");
dpii_final();
$finish;
end
end

View File

@ -20,16 +20,17 @@
#include "TestSimulator.h"
#include "TestVpi.h"
bool errors = false;
int errors = 0;
unsigned int callback_count_time1 = 3;
unsigned int callback_count_time2 = 4;
unsigned int callback_count_start_of_sim = 0;
unsigned int callback_count1 = 0;
unsigned int callback_count2 = 0;
unsigned int callback_time1 = 0;
unsigned int callback_time2 = 0;
//======================================================================
static int _never_cb(p_cb_data cb_data) {
TEST_CHECK(0, 1); // Should never get called
TEST_CHECK_EQ(0, 1); // Should never get called
return 0;
}
@ -38,8 +39,9 @@ static int _time_cb1(p_cb_data cb_data) {
t.type = vpiSimTime;
vpi_get_time(0, &t);
TEST_VERBOSE_PRINTF("time_cb1: %d\n", t.low);
TEST_CHECK(callback_count_time1, t.low);
callback_count_time1++;
++callback_count1;
if (callback_time1) TEST_CHECK_EQ(callback_time1, t.low);
callback_time1 = t.low + 1; // Next call
t_cb_data cb_data_n;
bzero(&cb_data_n, sizeof(cb_data_n));
@ -51,7 +53,7 @@ static int _time_cb1(p_cb_data cb_data) {
cb_data_n.time = &t;
cb_data_n.cb_rtn = _time_cb1;
TestVpiHandle cb_data_n1_h = vpi_register_cb(&cb_data_n);
TEST_CHECK(vpi_get(vpiType, cb_data_n1_h), vpiCallback);
TEST_CHECK_EQ(vpi_get(vpiType, cb_data_n1_h), vpiCallback);
}
{
// Test cancelling a callback
@ -69,12 +71,13 @@ static int _time_cb1(p_cb_data cb_data) {
}
static int _time_cb2(p_cb_data cb_data) {
// One-shot
s_vpi_time t;
t.type = vpiSimTime;
vpi_get_time(0, &t);
TEST_VERBOSE_PRINTF("time_cb2: %d\n", t.low);
TEST_CHECK(callback_count_time2, t.low);
callback_count_time2++;
if (callback_time2) TEST_CHECK_EQ(callback_time2, t.low);
++callback_count2;
t_cb_data cb_data_n;
bzero(&cb_data_n, sizeof(cb_data_n));
@ -86,12 +89,12 @@ static int _time_cb2(p_cb_data cb_data) {
cb_data_n.time = &t;
cb_data_n.cb_rtn = _time_cb2;
TestVpiHandle cb_data_n2_h = vpi_register_cb(&cb_data_n);
TEST_CHECK(vpi_get(vpiType, cb_data_n2_h), vpiCallback);
TEST_CHECK_EQ(vpi_get(vpiType, cb_data_n2_h), vpiCallback);
return 0;
}
static int _start_of_sim_cb(p_cb_data cb_data) {
TEST_VERBOSE_PRINTF("-_start_of_sim_cb\n");
extern "C" void dpii_init() {
TEST_VERBOSE_PRINTF("-dpii_init()\n");
t_cb_data cb_data_n1, cb_data_n2;
bzero(&cb_data_n1, sizeof(cb_data_n1));
@ -105,7 +108,7 @@ static int _start_of_sim_cb(p_cb_data cb_data) {
cb_data_n1.time = &t1;
cb_data_n1.cb_rtn = _time_cb1;
TestVpiHandle cb_data_n1_h = vpi_register_cb(&cb_data_n1);
TEST_CHECK(vpi_get(vpiType, cb_data_n1_h), vpiCallback);
TEST_CHECK_EQ(vpi_get(vpiType, cb_data_n1_h), vpiCallback);
cb_data_n2.reason = cbAfterDelay;
t2.type = vpiSimTime;
@ -114,45 +117,20 @@ static int _start_of_sim_cb(p_cb_data cb_data) {
cb_data_n2.time = &t2;
cb_data_n2.cb_rtn = _time_cb2;
TestVpiHandle cb_data_n2_h = vpi_register_cb(&cb_data_n2);
callback_count_start_of_sim++;
return 0;
}
static int _end_of_sim_cb(p_cb_data cb_data) {
TEST_CHECK(callback_count_start_of_sim, 1);
if (!errors) fprintf(stdout, "*-* All Finished *-*\n");
return 0;
}
extern "C" void dpii_final() {
TEST_VERBOSE_PRINTF("-dpii_final()\n");
extern "C" void vpi_compat_bootstrap(void) {
t_cb_data cb_data;
bzero(&cb_data, sizeof(cb_data));
{
TEST_VERBOSE_PRINTF("register _start_of_sim_cb_h\n");
cb_data.reason = cbStartOfSimulation;
cb_data.time = 0;
cb_data.cb_rtn = _start_of_sim_cb;
TestVpiHandle _start_of_sim_cb_h = vpi_register_cb(&cb_data);
}
{
TEST_VERBOSE_PRINTF("register _end_of_sim_cb_h\n");
cb_data.reason = cbEndOfSimulation;
cb_data.time = 0;
cb_data.cb_rtn = _end_of_sim_cb;
TestVpiHandle _end_of_sim_cb_h = vpi_register_cb(&cb_data);
}
{
// Test cancelling a callback
cb_data.reason = cbStartOfSimulation;
cb_data.time = 0;
cb_data.cb_rtn = _never_cb;
TestVpiHandle cb_h = vpi_register_cb(&cb_data);
vpi_remove_cb(cb_h);
cb_h.freed();
// Allow some slop as cb might be before/after this call
TEST_CHECK(callback_count1, 1010,
(callback_count1 >= 1000 && callback_count1 <= 1020));
TEST_CHECK(callback_count2, 1010,
(callback_count2 >= 1000 && callback_count2 <= 1020));
if (errors) {
vpi_control(vpiStop);
} else {
printf("*-* All Finished *-*\n");
}
}
#ifdef IVERILOG
// icarus entry
void (*vlog_startup_routines[])() = {vpi_compat_bootstrap, 0};
#endif