mirror of
https://github.com/verilator/verilator.git
synced 2025-02-08 06:32:24 +00:00
vpi_get_value_array: add tests and fix some tests.
Some test were not updated to the new vpiReg & vpiRegArray types. Signed-off-by: Diego Roux <diegoroux04@protonmail.com>
This commit is contained in:
parent
164dd8ec96
commit
f3abf3c385
@ -2936,7 +2936,7 @@ void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < num; i++) {
|
||||
integers[i] = ptr[index++];
|
||||
integers[i] = ptr[index];
|
||||
index = (--index + size) % size;
|
||||
}
|
||||
}
|
||||
@ -2950,7 +2950,7 @@ void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < num; i++) {
|
||||
integers[i] = ptr[index++];
|
||||
integers[i] = ptr[index];
|
||||
index = (--index + size) % size;
|
||||
}
|
||||
}
|
||||
@ -2964,7 +2964,7 @@ void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < num; i++) {
|
||||
integers[i] = ptr[index++];
|
||||
integers[i] = ptr[index];
|
||||
index = (--index + size) % size;
|
||||
}
|
||||
}
|
||||
@ -2998,7 +2998,7 @@ void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < num; i++) {
|
||||
shortints[i] = ptr[index++];
|
||||
shortints[i] = ptr[index];
|
||||
index = (--index + size) % size;
|
||||
}
|
||||
}
|
||||
@ -3012,7 +3012,7 @@ void vl_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < num; i++) {
|
||||
shortints[i] = ptr[index++];
|
||||
shortints[i] = ptr[index];
|
||||
index = (--index + size) % size;
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ static int _mon_check_props(TestVpiHandle& handle, int size, int direction, int
|
||||
}
|
||||
|
||||
// Icarus only supports ranges on memories
|
||||
if (!scalar && !(TestSimulator::is_icarus() && type != vpiMemory)) {
|
||||
if (!scalar && !(TestSimulator::is_icarus() && type != vpiRegArray)) {
|
||||
TestVpiHandle left_h, right_h;
|
||||
|
||||
// check coherency for vectors
|
||||
@ -157,11 +157,11 @@ int mon_check_props() {
|
||||
= {{"onebit", {1, vpiNoDirection, 1, vpiReg}, {0, 0, 0, 0}},
|
||||
{"twoone", {2, vpiNoDirection, 0, vpiReg}, {0, 0, 0, 0}},
|
||||
{"onetwo",
|
||||
{2, vpiNoDirection, 0, TestSimulator::is_verilator() ? vpiReg : vpiMemory},
|
||||
{2, vpiNoDirection, 0, TestSimulator::is_verilator() ? vpiReg : vpiRegArray},
|
||||
{0, 0, 0, 0}},
|
||||
{"fourthreetwoone",
|
||||
{2, vpiNoDirection, 0, vpiMemory},
|
||||
{2, vpiNoDirection, 0, vpiMemoryWord}},
|
||||
{2, vpiNoDirection, 0, vpiRegArray},
|
||||
{2, vpiNoDirection, 0, vpiReg}},
|
||||
{"theint", {32, vpiNoDirection, 0, vpiReg}, {0, 0, 0, 0}},
|
||||
{"clk", {1, vpiInput, 1, vpiPort}, {0, 0, 0, 0}},
|
||||
{"testin", {16, vpiInput, 0, vpiPort}, {0, 0, 0, 0}},
|
||||
@ -184,7 +184,7 @@ int mon_check_props() {
|
||||
return status;
|
||||
if (value->children.size) {
|
||||
int size = 0;
|
||||
TestVpiHandle iter_h = vpi_iterate(vpiMemoryWord, h);
|
||||
TestVpiHandle iter_h = vpi_iterate(vpiReg, h);
|
||||
while (TestVpiHandle word_h = vpi_scan(iter_h)) {
|
||||
// check size and range
|
||||
if (int status
|
||||
|
214
test_regress/t/t_vpi_get_value_array.cpp
Normal file
214
test_regress/t/t_vpi_get_value_array.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2024 by Diego Roux. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef IS_VPI
|
||||
|
||||
#include "verilated.h"
|
||||
#include "verilated_vcd_c.h"
|
||||
#include "verilated_vpi.h"
|
||||
|
||||
#include "Vt_vpi_get_value_array.h"
|
||||
#include "Vt_vpi_get_value_array__Dpi.h"
|
||||
#include "svdpi.h"
|
||||
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
// These require the above. Comment prevents clang-format moving them
|
||||
#include "TestSimulator.h"
|
||||
#include "TestVpi.h"
|
||||
|
||||
// __FILE__ is too long
|
||||
#define FILENM "t_vpi_get_value_array.cpp"
|
||||
|
||||
#define TEST_MSG \
|
||||
if (0) printf
|
||||
|
||||
//======================================================================
|
||||
|
||||
#define CHECK_RESULT_VH(got, exp) \
|
||||
if ((got) != (exp)) { \
|
||||
printf("%%Error: %s:%d: GOT = %p EXP = %p\n", FILENM, __LINE__, (got), (exp)); \
|
||||
return __LINE__; \
|
||||
}
|
||||
|
||||
#define CHECK_RESULT_NZ(got) \
|
||||
if (!(got)) { \
|
||||
printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM, __LINE__); \
|
||||
return __LINE__; \
|
||||
}
|
||||
|
||||
// Use cout to avoid issues with %d/%lx etc
|
||||
#define CHECK_RESULT(got, exp) \
|
||||
if ((got) != (exp)) { \
|
||||
std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \
|
||||
<< " EXP = " << (exp) << std::endl; \
|
||||
return __LINE__; \
|
||||
}
|
||||
|
||||
#define CHECK_RESULT_HEX(got, exp) \
|
||||
if ((got) != (exp)) { \
|
||||
std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << std::hex \
|
||||
<< ": GOT = " << (got) << " EXP = " << (exp) << std::endl; \
|
||||
return __LINE__; \
|
||||
}
|
||||
|
||||
#define CHECK_RESULT_CSTR(got, exp) \
|
||||
if (std::strcmp((got), (exp))) { \
|
||||
printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \
|
||||
(got) ? (got) : "<null>", (exp) ? (exp) : "<null>"); \
|
||||
return __LINE__; \
|
||||
}
|
||||
|
||||
#define CHECK_RESULT_CSTR_STRIP(got, exp) CHECK_RESULT_CSTR(got + strspn(got, " "), exp)
|
||||
|
||||
int mon_check_props(void) {
|
||||
s_vpi_arrayvalue arrayVal = {0, 0, NULL};
|
||||
int indexArr[2] = {0};
|
||||
int num = 4;
|
||||
|
||||
{
|
||||
vpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"TOP.test.read_bytes", NULL);
|
||||
|
||||
arrayVal.format = vpiRawTwoStateVal;
|
||||
vpi_get_value_array(object, &arrayVal, indexArr, num);
|
||||
|
||||
PLI_BYTE8* ptr = arrayVal.value.rawvals;
|
||||
|
||||
PLI_BYTE8 expected[4] = {0xde, 0xad, 0xbe, 0xef};
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
CHECK_RESULT_HEX(ptr[i], expected[i]);
|
||||
}
|
||||
|
||||
{
|
||||
vpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"TOP.test.read_shorts", NULL);
|
||||
|
||||
arrayVal.format = vpiShortIntVal;
|
||||
vpi_get_value_array(object, &arrayVal, indexArr, num);
|
||||
|
||||
PLI_UINT16* ptr = (PLI_UINT16*)arrayVal.value.shortints;
|
||||
|
||||
PLI_UINT16 expected[4] = {0xdead, 0xbeef, 0xbeef, 0xdead};
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
CHECK_RESULT_HEX(ptr[i], expected[i]);
|
||||
}
|
||||
|
||||
{
|
||||
vpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"TOP.test.read_integers", NULL);
|
||||
|
||||
arrayVal.format = vpiIntVal;
|
||||
vpi_get_value_array(object, &arrayVal, indexArr, num);
|
||||
|
||||
PLI_UINT32* ptr = (PLI_UINT32*)arrayVal.value.integers;
|
||||
|
||||
PLI_UINT32 expected[4] = {0x00000000, 0xdeadbeef, 0x00000000, 0xdeadbeef};
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
CHECK_RESULT_HEX(ptr[i], expected[i]);
|
||||
}
|
||||
|
||||
{
|
||||
vpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"TOP.test.read_integers_rl", NULL);
|
||||
|
||||
arrayVal.format = vpiIntVal;
|
||||
vpi_get_value_array(object, &arrayVal, indexArr, num);
|
||||
|
||||
PLI_UINT32* ptr = (PLI_UINT32*)arrayVal.value.integers;
|
||||
|
||||
PLI_UINT32 expected[4] = {0xdeadbeef, 0x00000000, 0x00000000, 0xdeadbeef};
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
CHECK_RESULT_HEX(ptr[i], expected[i]);
|
||||
}
|
||||
|
||||
{
|
||||
vpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"TOP.test.read_longs", NULL);
|
||||
|
||||
arrayVal.format = vpiLongIntVal;
|
||||
vpi_get_value_array(object, &arrayVal, indexArr, num);
|
||||
|
||||
PLI_UINT64* ptr = (PLI_UINT64*)arrayVal.value.longints;
|
||||
|
||||
PLI_UINT64 expected[4] = {0x00000000deadbeef, 0x0000000000000000,
|
||||
0x00000000beefdead, 0x0000000000000000};
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
CHECK_RESULT_HEX(ptr[i], expected[i]);
|
||||
}
|
||||
|
||||
{
|
||||
vpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"TOP.test.read_words", NULL);
|
||||
|
||||
arrayVal.format = vpiRawFourStateVal;
|
||||
vpi_get_value_array(object, &arrayVal, indexArr, num);
|
||||
|
||||
PLI_UINT64* ptr = (PLI_UINT64*)arrayVal.value.rawvals;
|
||||
|
||||
PLI_UINT64 expected[16] = {0x0000000000000000, 0x0000000000000000, 0x00, 0x00,
|
||||
0xbeefdead00000000, 0x00000000deadbeef, 0x00, 0x00,
|
||||
0x0000000000000000, 0x00000000beefdead, 0x00, 0x00,
|
||||
0xbeefdeaddeadbeef, 0xbeefdeaddeadbeef, 0x00, 0x00};
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
CHECK_RESULT_HEX(ptr[i], expected[i]);
|
||||
}
|
||||
|
||||
{
|
||||
vpiHandle object = vpi_handle_by_name((PLI_BYTE8*)"TOP.test.read_integers", NULL);
|
||||
|
||||
arrayVal.format = vpiVector;
|
||||
vpi_get_value_array(object, &arrayVal, indexArr, num);
|
||||
|
||||
p_vpi_vecval ptr = (p_vpi_vecval)arrayVal.value.vectors;
|
||||
|
||||
s_vpi_vecval expected[4] = {{0x00000000, 0x000000},
|
||||
{0xdeadbeef, 0x00000000}, {0x00000000, 0x00000000},
|
||||
{0xdeadbeef, 0x00000000}};
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
CHECK_RESULT_HEX(ptr[i].aval, expected[i].aval);
|
||||
CHECK_RESULT_HEX(ptr[i].bval, expected[i].bval);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int mon_check(void) {
|
||||
return mon_check_props();
|
||||
}
|
||||
|
||||
#ifndef IS_VPI
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
|
||||
const std::unique_ptr<VM_PREFIX> top{new VM_PREFIX{contextp.get()}};
|
||||
|
||||
#ifdef TEST_VERBOSE
|
||||
contextp->internalsDump();
|
||||
#endif
|
||||
|
||||
while (!contextp->gotFinish()) {
|
||||
top->eval();
|
||||
VerilatedVpi::callValueCbs();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
23
test_regress/t/t_vpi_get_value_array.py
Normal file
23
test_regress/t/t_vpi_get_value_array.py
Normal file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2024 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(make_top_shell=False,
|
||||
make_main=False,
|
||||
make_pli=True,
|
||||
verilator_flags2=["--exe --vpi --no-l2name", test.pli_filename],
|
||||
iv_flags2=["-g2005-sv -D USE_VPI_NOT_DPI"],
|
||||
v_flags2=["+define+USE_VPI_NOT_DPI +define+VERILATOR_COMMENTS"])
|
||||
|
||||
test.execute(use_libvpi=True)
|
||||
|
||||
test.passes()
|
77
test_regress/t/t_vpi_get_value_array.v
Normal file
77
test_regress/t/t_vpi_get_value_array.v
Normal file
@ -0,0 +1,77 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// Copyright 2024 by Diego Roux. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
`ifdef VERILATOR_COMMENTS
|
||||
`define PUBLIC_FLAT_RD /*verilator public_flat_rd*/
|
||||
`define PUBLIC_FLAT_RW /*verilator public_flat_rw @(posedge clk)*/
|
||||
`else
|
||||
`define PUBLIC_FLAT_RD
|
||||
`define PUBLIC_FLAT_RW
|
||||
`endif
|
||||
|
||||
module test #(
|
||||
parameter WIDTH `PUBLIC_FLAT_RD = 32
|
||||
) (input clk);
|
||||
|
||||
`ifdef VERILATOR
|
||||
`systemc_header
|
||||
extern "C" int mon_check();
|
||||
`verilog
|
||||
`endif
|
||||
|
||||
reg [7:0] read_bytes [0:3] `PUBLIC_FLAT_RD;
|
||||
reg [15:0] read_shorts [0:3] `PUBLIC_FLAT_RD;
|
||||
reg [31:0] read_integers [0:3] `PUBLIC_FLAT_RD;
|
||||
reg [31:0] read_integers_rl [3:0] `PUBLIC_FLAT_RD;
|
||||
reg [63:0] read_longs [0:3] `PUBLIC_FLAT_RD;
|
||||
reg [127:0] read_words [0:3] `PUBLIC_FLAT_RD;
|
||||
|
||||
integer status;
|
||||
|
||||
initial begin
|
||||
read_bytes[0] = 8'hde;
|
||||
read_bytes[1] = 8'had;
|
||||
read_bytes[2] = 8'hbe;
|
||||
read_bytes[3] = 8'hef;
|
||||
|
||||
read_shorts[0] = 16'hdead;
|
||||
read_shorts[1] = 16'hbeef;
|
||||
read_shorts[2] = 16'hbeef;
|
||||
read_shorts[3] = 16'hdead;
|
||||
|
||||
read_integers[0] = 32'h00000000;
|
||||
read_integers[1] = 32'hdeadbeef;
|
||||
read_integers[2] = 32'h00000000;
|
||||
read_integers[3] = 32'hdeadbeef;
|
||||
|
||||
read_integers_rl[0] = 32'hdeadbeef;
|
||||
read_integers_rl[1] = 32'hdeadbeef;
|
||||
read_integers_rl[2] = 32'h00000000;
|
||||
read_integers_rl[3] = 32'h00000000;
|
||||
|
||||
read_longs[0] = 64'h00000000deadbeef;
|
||||
read_longs[1] = 64'h0000000000000000;
|
||||
read_longs[2] = 64'h00000000beefdead;
|
||||
read_longs[3] = 64'h0000000000000000;
|
||||
|
||||
read_words[0] = 128'h00000000000000000000000000000000;
|
||||
read_words[1] = 128'hbeefdead0000000000000000deadbeef;
|
||||
read_words[2] = 128'h000000000000000000000000beefdead;
|
||||
read_words[3] = 128'hbeefdeaddeadbeefbeefdeaddeadbeef;
|
||||
|
||||
status = $c32("mon_check()");
|
||||
|
||||
if (status != 0) begin
|
||||
$write("%%Error: t_vpi_get.cpp:%0d: C Test failed\n", status);
|
||||
$stop;
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
@ -86,8 +86,8 @@ void _mem_check(const char* name, int size, int left, int right, int words) {
|
||||
TEST_CHECK_NZ(mem_h);
|
||||
// check type
|
||||
int vpitype = vpi_get(vpiType, mem_h);
|
||||
if (vpitype != vpiMemory && vpitype != vpiReg) {
|
||||
printf("%%Error: %s:%d vpiType neither vpiMemory or vpiReg: %d\n", FILENM, __LINE__,
|
||||
if (vpitype != vpiRegArray && vpitype != vpiReg) {
|
||||
printf("%%Error: %s:%d vpiType neither vpiRegArray or vpiReg: %d\n", FILENM, __LINE__,
|
||||
vpitype);
|
||||
errors++;
|
||||
}
|
||||
@ -99,9 +99,9 @@ void _mem_check(const char* name, int size, int left, int right, int words) {
|
||||
}
|
||||
}
|
||||
// iterate and store
|
||||
if (vpitype == vpiMemory) {
|
||||
if (vpitype == vpiRegArray) {
|
||||
_mon_check_range(mem_h, words, words, 1);
|
||||
TestVpiHandle iter_h = vpi_iterate(vpiMemoryWord, mem_h);
|
||||
TestVpiHandle iter_h = vpi_iterate(vpiReg, mem_h);
|
||||
int cnt = 0;
|
||||
while (TestVpiHandle lcl_h = vpi_scan(iter_h)) {
|
||||
value.format = vpiIntVal;
|
||||
@ -121,9 +121,9 @@ void _mem_check(const char* name, int size, int left, int right, int words) {
|
||||
vpi_put_value(mem_h, &value, NULL, vpiNoDelay);
|
||||
TEST_CHECK_Z(vpi_chk_error(&e));
|
||||
}
|
||||
if (vpitype == vpiMemory) {
|
||||
if (vpitype == vpiRegArray) {
|
||||
// iterate and accumulate
|
||||
TestVpiHandle iter_h = vpi_iterate(vpiMemoryWord, mem_h);
|
||||
TestVpiHandle iter_h = vpi_iterate(vpiReg, mem_h);
|
||||
int cnt = 0;
|
||||
while (TestVpiHandle lcl_h = vpi_scan(iter_h)) {
|
||||
++cnt;
|
||||
@ -138,7 +138,7 @@ void _mem_check(const char* name, int size, int left, int right, int words) {
|
||||
value.format = vpiBinStrVal;
|
||||
vpi_get_value(mem_h, &value);
|
||||
TEST_CHECK_Z(vpi_chk_error(&e));
|
||||
TEST_CHECK_EQ(std::string{value.value.str}, binStr);
|
||||
TEST_CHECK_EQ(std::string(value.value.str), binStr);
|
||||
}
|
||||
|
||||
// don't care for non verilator
|
||||
@ -151,7 +151,7 @@ void _mem_check(const char* name, int size, int left, int right, int words) {
|
||||
{
|
||||
// make sure trying to get properties that don't exist
|
||||
// doesn't crash
|
||||
TestVpiHandle iter_h = vpi_iterate(vpiMemoryWord, mem_h);
|
||||
TestVpiHandle iter_h = vpi_iterate(vpiReg, mem_h);
|
||||
int should_be_undefined = vpi_get(vpiSize, iter_h);
|
||||
TEST_CHECK_EQ(should_be_undefined, vpiUndefined);
|
||||
should_be_undefined = vpi_get(vpiIndex, iter_h);
|
||||
@ -163,7 +163,7 @@ void _mem_check(const char* name, int size, int left, int right, int words) {
|
||||
should_be_NULL = vpi_handle(vpiScope, iter_h);
|
||||
TEST_CHECK_EQ(should_be_NULL, 0);
|
||||
}
|
||||
if (vpitype == vpiMemory) {
|
||||
if (vpitype == vpiRegArray) {
|
||||
// check vpiRange
|
||||
TestVpiHandle iter_h = vpi_iterate(vpiRange, mem_h);
|
||||
TEST_CHECK_NZ(iter_h);
|
||||
|
Loading…
Reference in New Issue
Block a user