mirror of
https://github.com/verilator/verilator.git
synced 2025-04-05 04:02:37 +00:00
Tests: Refactor t_vpi_time_cb to avoid shared object
This commit is contained in:
parent
44478a53c2
commit
2feb46fc5d
@ -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},
|
||||||
|
@ -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 { \
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
||||||
|
Loading…
Reference in New Issue
Block a user