使用 Kristen 框架,您可以生成一些可供重用的测试台代码。下面是来自该测试平台的一个名为 test_support.vh 的文件。该文件包含显示错误和计算错误的函数。我建议您在比较内存位置时使用 === 或 !== ,因为未定义的信号可能会无意中匹配。在测试结束时,您调用 display_test_final_status,这将在日志文件中为您创建一个总体测试报告。完全回归完成后,您现在可以在日志文件上运行 grep 以查找 ERROR,它会以一致的方式显示任何失败的内容。
我有一个主要的 Perl 回归脚本,它运行我的所有测试并自动执行 grep 并发送成功或失败的电子邮件。
在每个测试的基础上,您需要设置一些定义来指示测试名称,以及您是否希望错误立即停止测试。
祝你好运。
// -----------------------------------------------------------
// test_support.vh
// Generated file specifies which numerical test cases to run.
// Kristen Software License - Version 1.0 - January 1st, 2019
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// GENERATED FILE - DO NOT MODIFY THIS FILE MANUALLY.
// -----------------------------------------------------------
logic[63:0] error_count = 0;
logic[63:0] lcl_error_count = 0;
logic bool_quick_mode = 0;
logic[511:0] support_test_passes;
logic[15:0] support_test_fails [0:511];
logic[511:0] support_test_was_run;
task test_init;
error_count = 0;
lcl_error_count = 0;
endtask
task display_test_begin_status;
begin
`ifdef QUICK_MODE
bool_quick_mode = 1;
`endif
$display("=========================================================================");
$display("| Test: %s QUICK_MODE = %s", `TEST_NAME_STR, bool_quick_mode ? "ON" : "OFF");
$display("| VERBOSE = %0d", `VERBOSE);
$display("=========================================================================");
end
endtask
task display_test_start;
input[31:0] test_id;
input string test_description;
begin
lcl_error_count = 0;
$display("=========================================================================");
$display("%0t: Test %0d : %s.", $time, test_id, test_description);
$display("=========================================================================");
end
endtask
task display_test_end;
input[31:0] test_id;
begin
$display("=========================================================================");
$display("%0t: Test %0d Complete with %0d ERRORS.", $time, test_id, lcl_error_count);
$display("=========================================================================");
support_test_was_run[test_id] = 1'b1;
if (lcl_error_count == 0)
support_test_passes[test_id] = 1'b1;
else
support_test_fails[test_id] = lcl_error_count;
end
endtask
task display_error_inc;
input string error_description;
begin
error_count++;
lcl_error_count++;
//$display("=========================================================================");
$display("%0t: ERROR: %s : error_count: %0d",$time, error_description, error_count );
//$display("=========================================================================");
`ifdef TEST_STOP_ON_ERROR
if (error_count >= `TEST_STOP_ON_ERROR_LIMIT) begin
$display("%0t, Stopping on error count = %d, %m", $time, error_count);
$finish();
end
`endif
end
endtask
task display_test_final_status;
//input string testname;
begin
$display("=========================================================================");
$display("%0t: Test %s %s with %0d ERRORS",$time, `TEST_NAME_STR, error_count > 0 ? "FAILS" : "PASSES",error_count);
$display("=========================================================================");
if (error_count !== 'h0)
begin
$display("Test failures:");
for (int err_fail_cnt = 0;err_fail_cnt < 512; err_fail_cnt = err_fail_cnt + 1)
begin
if (support_test_was_run[err_fail_cnt] == 1'b1 && support_test_passes[err_fail_cnt] != 1'b1)
begin
$display("Test %d, fails with %d errors", err_fail_cnt, support_test_fails[err_fail_cnt]);
end
end
end
end
endtask
task display_no_test_found;
input[31:0] test_id;
input string test_description;
begin
lcl_error_count = 0;
$display("=========================================================================");
$display("%0t: Test %0d : %s NOT FOUND SKIPPING.", $time, test_id, test_description);
$display("=========================================================================");
end
endtask
从 Kristen 生成的测试台中,当检测到 RAM 单元时,这就是运行的测试。我会将其视为一种算法解决方案,因为您必须生成几个向量字符串和将这些字符串转换为地址的附加函数。
xreg_v1_0_0_write_mpi_test 是写入 RAM 的任务,而 xreg_v1_0_0_read_mpi_test 是从 RAM 读取的任务。有一个比较任务 xreg_v1_0_0_register_compare_with_error 显然会产生错误。我也会在下面展示。
// This is a casex snippet from the RAM test
7'd2: begin
// xreg_v1_0_0_mem_ack test
$display("%0t, xreg_v1_0_0_mem_ack test", $time);
oo_limit = get_entries_by_index(tc_index) > 256 ? 256 : get_entries_by_index(tc_index); //Max number of entries for this test
mm_step = get_entry_offset(tc_index);
nn_limit = perfect_by_datawidth(get_size_by_index(get_address_by_index(tc_index)),DATAPATH_WIDTH)/8; // Number of bytes for this entry
nn_step = DATAPATH_WIDTH == 8 ? 1 : DATAPATH_WIDTH == 16 ? 2 : DATAPATH_WIDTH == 32 ? 4 : 8;
for(oo = 0; oo < oo_limit; oo = oo + 1) // Move through each entry we will be testing
begin
for (nn = 0; nn < nn_limit; nn = nn + nn_step) // Walk through each access of a given entry
begin
test_address = get_address_by_index(tc_index) + (oo*mm_step) + nn;
expected = oo[7:0] ^ nn[7:0] ^ mm_step[7:0] ^ nn_step[7:0];
expected = {expected[6:0],expected[7],expected[2:0],expected[7:3],expected[5],expected[3],expected[1],expected[7],expected[0],expected[2],expected[6],expected[4],expected[7:0]};
xreg_v1_0_0_write_mpi_test(aclk, test_address, expected);
end
end
for(oo = 0; oo < oo_limit; oo = oo + 1) // Move through each entry we will be testing
begin
for (nn = 0; nn < nn_limit; nn = nn + nn_step) // Walk through each access of a given entry
begin
test_address = get_address_by_index(tc_index) + (oo*mm_step) + nn;
mask = get_entry_mask_by_index(tc_index);
expected = oo[7:0] ^ nn[7:0] ^ mm_step[7:0] ^ nn_step[7:0];
expected = {expected[6:0],expected[7],expected[2:0],expected[7:3],expected[5],expected[3],expected[1],expected[7],expected[0],expected[2],expected[6],expected[4],expected[7:0]} & (get_entry_mask_by_index(tc_index) >> (nn*8));
xreg_v1_0_0_read_mpi_test(aclk, test_address, result);
xreg_v1_0_0_register_compare_with_error(test_address,expected,result);
end
end
end
以下是一些参考任务,它们显示了已实现的写入、读取和比较。我认为其中一些是 System Verilog,因此您必须将其视为算法。
task automatic xreg_v1_0_0_read_mpi_test;
ref logic clock;
input [`TEST_ADDR_WIDTH-1:0] address;
output [`TEST_DATA_WIDTH-1:0] result;
begin
$display("ENTER >>> xreg_v1_0_0_read_mpi_test");
repeat(1) @(posedge clock);
`TEST_MPI_ADDR = address;
`TEST_MPI_RD_REQ = 1'b1;
`TEST_MPI_ENABLE = 1'b1;
while (!`TEST_MPI_ACK) repeat(1) @(posedge clock);
`TEST_MPI_ADDR = 'h0;
`TEST_MPI_RD_REQ = 1'b0;
`TEST_MPI_ENABLE = 1'b0;
result = `TEST_MPI_RD_DATA;
$display("WAITING ACK <<< xreg_v1_0_0_read_mpi_test");
while (`TEST_MPI_ACK) repeat(1) @(posedge clock);
$display("EXIT <<< xreg_v1_0_0_read_mpi_test");
end
endtask
task automatic xreg_v1_0_0_write_mpi_test;
ref logic clock;
input [`TEST_ADDR_WIDTH-1:0] address;
input [`TEST_DATA_WIDTH-1:0] data;
begin
$display("ENTER >>> xreg_v1_0_0_write_mpi_test");
repeat(1) @(posedge clock);
`TEST_MPI_ADDR = address;
`TEST_MPI_WR_DATA = data;
`TEST_MPI_WR_REQ = 1'b1;
`TEST_MPI_ENABLE = 1'b1;
while (!`TEST_MPI_ACK) repeat(1) @(posedge clock);
`TEST_MPI_ADDR = 'h0;
`TEST_MPI_WR_DATA = 'h0;
`TEST_MPI_WR_REQ = 1'b0;
`TEST_MPI_ENABLE = 1'b0;
$display("WAITING ACK <<< xreg_v1_0_0_write_mpi_test");
while (`TEST_MPI_ACK) repeat(1) @(posedge clock);
$display("EXIT <<< xreg_v1_0_0_write_mpi_test");
end
endtask
task automatic xreg_v1_0_0_register_compare_with_error;
input [`TEST_ADDR_WIDTH-1:0] address;
input [`TEST_DATA_WIDTH-1:0] expected;
input [`TEST_DATA_WIDTH-1:0] result;
begin
$display("ENTER >>> xreg_v1_0_0_register_compare_with_error");
if (expected !== result)
begin
$display("%0t, Address = 0x%X", $time, address);
$display("%0t, Expected 0x%X", $time, expected);
$display("%0t, Read 0x%X", $time, result);
display_error_inc("xreg_v1_0_0_rdconst_test: Mismatch between read and expected data.");
end
$display("EXIT <<< xreg_v1_0_0_register_compare_with_error");
end
endtask