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"), cmd=>[($ENV{VERILATOR_VCS}||"vcs"),
@{$param{vcs_flags}}, @{$param{vcs_flags}},
@{$param{vcs_flags2}}, @{$param{vcs_flags2}},
($opt_verbose ? " -CFLAGS -DTEST_VERBOSE=1":""),
@{$param{v_flags}}, @{$param{v_flags}},
@{$param{v_flags2}}, @{$param{v_flags2}},
$param{top_filename}, $param{top_filename},

View File

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

View File

@ -20,11 +20,8 @@
#include "TestCheck.h" #include "TestCheck.h"
#include <dlfcn.h>
#include <iostream> #include <iostream>
bool errors = false;
unsigned int main_time = 0; 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"); tfp->open(VL_STRINGIFY(TEST_OBJ_DIR) "/simx.vcd");
#endif #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); VerilatedVpi::callCbs(cbStartOfSimulation);
topp->eval(); topp->eval();
topp->clk = 0; topp->clk = 0;
main_time += 1;
while (vl_time_stamp64() < sim_time && !Verilated::gotFinish()) { while (vl_time_stamp64() < sim_time && !Verilated::gotFinish()) {
main_time += 1; main_time += 1;
topp->eval(); topp->eval();
VerilatedVpi::callValueCbs(); VerilatedVpi::callValueCbs();
VerilatedVpi::callTimedCbs(); VerilatedVpi::callTimedCbs();
TEST_CHECK(VerilatedVpi::cbNextDeadline(), main_time + 1); if (main_time > 20) { // Else haven't registered callbacks
topp->clk = !topp->clk; TEST_CHECK_EQ(VerilatedVpi::cbNextDeadline(), main_time + 1);
}
if ((main_time % 5) == 0) topp->clk = !topp->clk;
// mon_do(); // mon_do();
#if VM_TRACE #if VM_TRACE
if (tfp) tfp->dump(main_time); 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); scenarios(simulator => 1);
$Self->{pli_filename} = "t_vpi_time_cb_c.cpp";
compile( compile(
make_top_shell => 0, make_top_shell => 0,
make_main => 0, make_main => 0,
make_pli => 1,
sim_time => 2100, sim_time => 2100,
v_flags2 => ["t/t_vpi_time_cb_c.cpp"],
iv_flags2 => ["-g2005-sv -DWAVES -DIVERILOG"], 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( execute(
use_libvpi => 1,
check_finished => 1, check_finished => 1,
); );

View File

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

View File

@ -20,16 +20,17 @@
#include "TestSimulator.h" #include "TestSimulator.h"
#include "TestVpi.h" #include "TestVpi.h"
bool errors = false; int errors = 0;
unsigned int callback_count_time1 = 3; unsigned int callback_count1 = 0;
unsigned int callback_count_time2 = 4; unsigned int callback_count2 = 0;
unsigned int callback_count_start_of_sim = 0; unsigned int callback_time1 = 0;
unsigned int callback_time2 = 0;
//====================================================================== //======================================================================
static int _never_cb(p_cb_data cb_data) { 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; return 0;
} }
@ -38,8 +39,9 @@ static int _time_cb1(p_cb_data cb_data) {
t.type = vpiSimTime; t.type = vpiSimTime;
vpi_get_time(0, &t); vpi_get_time(0, &t);
TEST_VERBOSE_PRINTF("time_cb1: %d\n", t.low); TEST_VERBOSE_PRINTF("time_cb1: %d\n", t.low);
TEST_CHECK(callback_count_time1, t.low); ++callback_count1;
callback_count_time1++; if (callback_time1) TEST_CHECK_EQ(callback_time1, t.low);
callback_time1 = t.low + 1; // Next call
t_cb_data cb_data_n; t_cb_data cb_data_n;
bzero(&cb_data_n, sizeof(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.time = &t;
cb_data_n.cb_rtn = _time_cb1; cb_data_n.cb_rtn = _time_cb1;
TestVpiHandle cb_data_n1_h = vpi_register_cb(&cb_data_n); 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 // 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) { static int _time_cb2(p_cb_data cb_data) {
// One-shot
s_vpi_time t; s_vpi_time t;
t.type = vpiSimTime; t.type = vpiSimTime;
vpi_get_time(0, &t); vpi_get_time(0, &t);
TEST_VERBOSE_PRINTF("time_cb2: %d\n", t.low); TEST_VERBOSE_PRINTF("time_cb2: %d\n", t.low);
TEST_CHECK(callback_count_time2, t.low); if (callback_time2) TEST_CHECK_EQ(callback_time2, t.low);
callback_count_time2++; ++callback_count2;
t_cb_data cb_data_n; t_cb_data cb_data_n;
bzero(&cb_data_n, sizeof(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.time = &t;
cb_data_n.cb_rtn = _time_cb2; cb_data_n.cb_rtn = _time_cb2;
TestVpiHandle cb_data_n2_h = vpi_register_cb(&cb_data_n); 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; return 0;
} }
static int _start_of_sim_cb(p_cb_data cb_data) { extern "C" void dpii_init() {
TEST_VERBOSE_PRINTF("-_start_of_sim_cb\n"); TEST_VERBOSE_PRINTF("-dpii_init()\n");
t_cb_data cb_data_n1, cb_data_n2; t_cb_data cb_data_n1, cb_data_n2;
bzero(&cb_data_n1, sizeof(cb_data_n1)); 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.time = &t1;
cb_data_n1.cb_rtn = _time_cb1; cb_data_n1.cb_rtn = _time_cb1;
TestVpiHandle cb_data_n1_h = vpi_register_cb(&cb_data_n1); 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; cb_data_n2.reason = cbAfterDelay;
t2.type = vpiSimTime; 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.time = &t2;
cb_data_n2.cb_rtn = _time_cb2; cb_data_n2.cb_rtn = _time_cb2;
TestVpiHandle cb_data_n2_h = vpi_register_cb(&cb_data_n2); 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) { extern "C" void dpii_final() {
TEST_CHECK(callback_count_start_of_sim, 1); TEST_VERBOSE_PRINTF("-dpii_final()\n");
if (!errors) fprintf(stdout, "*-* All Finished *-*\n");
return 0;
}
extern "C" void vpi_compat_bootstrap(void) { // Allow some slop as cb might be before/after this call
t_cb_data cb_data; TEST_CHECK(callback_count1, 1010,
bzero(&cb_data, sizeof(cb_data)); (callback_count1 >= 1000 && callback_count1 <= 1020));
{ TEST_CHECK(callback_count2, 1010,
TEST_VERBOSE_PRINTF("register _start_of_sim_cb_h\n"); (callback_count2 >= 1000 && callback_count2 <= 1020));
cb_data.reason = cbStartOfSimulation;
cb_data.time = 0; if (errors) {
cb_data.cb_rtn = _start_of_sim_cb; vpi_control(vpiStop);
TestVpiHandle _start_of_sim_cb_h = vpi_register_cb(&cb_data); } else {
} printf("*-* All Finished *-*\n");
{
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();
} }
} }
#ifdef IVERILOG
// icarus entry
void (*vlog_startup_routines[])() = {vpi_compat_bootstrap, 0};
#endif