Skip to content

Commit

Permalink
[dma,dv] Top-level abort test
Browse files Browse the repository at this point in the history
Signed-off-by: Robert Schilling <[email protected]>
  • Loading branch information
Razer6 committed Jan 16, 2024
1 parent 52c6ef7 commit d659f81
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 2 deletions.
9 changes: 8 additions & 1 deletion hw/top_darjeeling/dv/chip_sim_cfg.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -1664,7 +1664,14 @@
uvm_test_seq: chip_sw_dma_spi_hw_handshake_vseq
sw_images: ["//sw/device/tests:dma_inline_hashing:6"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=22_000_000"]
run_opts: ["+sw_test_timeout_ns=22_000_000", "+abort=0"]
}
{
name: chip_sw_dma_abort
uvm_test_seq: chip_sw_dma_spi_hw_handshake_vseq
sw_images: ["//sw/device/tests:dma_abort:6"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=22_000_000", "+abort=1"]
}
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ class chip_sw_dma_spi_hw_handshake_vseq extends chip_sw_base_vseq;

`uvm_object_new

localparam string DMA_FSM_STATE_PATH =
"tb.dut.top_darjeeling.u_dma.ctrl_state_q";

task pre_start();
// Setting the byte order to 0 ensures that the 4 byte transaction sent to
// the agent from the DUT is played back in exactly the same order, thus
Expand All @@ -23,12 +26,25 @@ class chip_sw_dma_spi_hw_handshake_vseq extends chip_sw_base_vseq;
spi_device_dma_seq m_device_dma_seq;
bit [31:0] exp_digest[16];
bit[7:0] sha_mode_arr[1];
bit [7:0] kSoftwareBarrier[] = '{0};
bit abort = 1'b0;
int retval;
bit [$bits(dma_pkg::dma_ctrl_state_e)-1:0] dma_state;
time dma_busy_timeout = 120_000_000; // 120ms

spi_device_dma_seq::data_t msg;

super.body();
`uvm_info(`gfn, "Testing with spi host 0", UVM_LOW)

void'($value$plusargs("abort=%0d", abort));

if (abort) begin
`uvm_info(`gfn, "Testing abort mode", UVM_LOW)
end else begin
`uvm_info(`gfn, "Testing normal DMA transfer", UVM_LOW)
end

// enable spi agent
cfg.chip_vif.enable_spi_device(.inst_num(0), .enable(1));

Expand Down Expand Up @@ -69,6 +85,39 @@ class chip_sw_dma_spi_hw_handshake_vseq extends chip_sw_base_vseq;
sw_symbol_backdoor_overwrite("kShaMode", sha_mode_arr);
sw_symbol_backdoor_overwrite("kShaDigestExpData", {<<8{{<<32{exp_digest}}}});

fork m_device_dma_seq.start(p_sequencer.spi_device_sequencer_hs[0]); join_none
fork
begin
m_device_dma_seq.start(p_sequencer.spi_device_sequencer_hs[0]);
end
begin
if (abort) begin
// Wait until the DMA performs the first transfer
`DV_SPINWAIT(while (dma_state != dma_pkg::DmaWaitReadResponse) begin
retval = uvm_hdl_read(DMA_FSM_STATE_PATH, dma_state);
`DV_CHECK_EQ(retval, 1, $sformatf("uvm_hdl_read failed for %0s", DMA_FSM_STATE_PATH))
cfg.clk_rst_vif.wait_clks(1);
end,
"timeout while wait for test exit complete",
dma_busy_timeout)
// Wait a random delay
cfg.clk_rst_vif.wait_clks($urandom_range(1, 10000));

// Backdoor the SW to perform the abort
kSoftwareBarrier[0] = 1;
`uvm_info(`gfn, $sformatf("Setting kSoftwareBarrier = %0d", 1), UVM_LOW)
sw_symbol_backdoor_overwrite("kSoftwareBarrier", kSoftwareBarrier);

// Stop the running sequence
p_sequencer.spi_device_sequencer_hs[0].stop_sequences();

// Wait for the sw to finish configuring the spi_host DUT
`DV_WAIT(cfg.sw_logger_vif.printed_log == "spi host re-configuration complete",
"Timedout waiting for spi host c configuration.")

// Restart the SPI sequence
m_device_dma_seq.start(p_sequencer.spi_device_sequencer_hs[0]);
end
end
join_none
endtask
endclass : chip_sw_dma_spi_hw_handshake_vseq
19 changes: 19 additions & 0 deletions sw/device/tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,25 @@ opentitan_functest(
],
)

opentitan_functest(
name = "dma_abort",
srcs = ["dma_abort.c"],
targets = [
"dv",
],
deps = [
"//sw/device/lib/testing/test_framework:ottf_main",
"//sw/lib/sw/device/base:macros",
"//sw/lib/sw/device/base:mmio",
"//sw/lib/sw/device/runtime:log",
"//sw/top_darjeeling/sw/device/runtime:print",
"//sw/top_darjeeling/sw/dif:dma",
"//sw/top_darjeeling/sw/dif:spi_host",
"//sw/top_darjeeling/sw/test/utils:dma_testutils",
"//sw/top_darjeeling/sw/test/utils:pinmux_testutils",
],
)

opentitan_functest(
name = "entropy_src_csrng_test",
srcs = ["entropy_src_csrng_test.c"],
Expand Down
107 changes: 107 additions & 0 deletions sw/device/tests/dma_abort.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
#include "sw/device/lib/testing/test_framework/status.h"
#include "sw/ip/base/dif/dif_base.h"
#include "sw/ip/dma/dif/dif_dma.h"
#include "sw/ip/dma/test/utils/dma_testutils.h"
#include "sw/ip/pinmux/test/utils/pinmux_testutils.h"
#include "sw/ip/rv_core_ibex/test/utils/rand_testutils.h"
#include "sw/ip/spi_host/dif/dif_spi_host.h"
#include "sw/lib/sw/device/arch/device.h"
#include "sw/lib/sw/device/base/mmio.h"
#include "sw/lib/sw/device/runtime/hart.h"
#include "sw/lib/sw/device/runtime/log.h"

#include "hw/top_darjeeling/sw/autogen/top_darjeeling.h"
#include "spi_host_regs.h" // Generated.

// The TX_SIZE must be in sync with the data size in spi_device_dma_seq.sv
// 1 SPI segment can only transfer at maximum 512 bytes
#define TX_SIZE 512
#define CHUNK_SIZE 32 * 4 // Half the SPI host FIFO size

OTTF_DEFINE_TEST_CONFIG();

enum {
kSoftwareBarrierTimeoutUsec = 500,
};

// This location will be update from SV
static volatile const uint8_t kSoftwareBarrier = 0;

// Expected digest value gets backdoor'ed from the hardware
// Although not used, we need to keep it here as the shared vseq
// wants to write it.
static volatile uint32_t kShaDigestExpData[16];
static volatile uint8_t kShaMode;

uint32_t digest[16];
uint8_t received_data[TX_SIZE] __attribute__((aligned(4)));

static dif_spi_host_t spi_host;
static dif_pinmux_t pinmux;
static dif_dma_t dma;

bool test_main(void) {
// Initialize the pinmux.
CHECK_DIF_OK(dif_pinmux_init(
mmio_region_from_addr(TOP_DARJEELING_PINMUX_AON_BASE_ADDR), &pinmux));
pinmux_testutils_init(&pinmux);

// Initialise DMA.
CHECK_DIF_OK(
dif_dma_init(mmio_region_from_addr(TOP_DARJEELING_DMA_BASE_ADDR), &dma));

// Setup pinmux if required, enable weak pull-up on relevant pads
setup_pads_spi_host0(&pinmux); // direct

// Setup spi host configuration
CHECK_DIF_OK(dif_spi_host_init(
mmio_region_from_addr(TOP_DARJEELING_SPI_HOST0_BASE_ADDR), &spi_host));
init_spi_host(&spi_host, (uint32_t)kClockFreqHiSpeedPeripheralHz,
CHUNK_SIZE / 4);

// DV sync message
LOG_INFO("spi host configuration complete");

// Dummy assignment to avoid any unused variable warnings
kShaDigestExpData[0] = 0;

setup_spi_dma_transaction(&spi_host, &dma, &received_data[0], CHUNK_SIZE,
TX_SIZE);

CHECK_DIF_OK(dif_dma_start(&dma, kShaMode));

// Wait until the DMA has started to abort the transfer
IBEX_SPIN_FOR(kSoftwareBarrier == 1, kSoftwareBarrierTimeoutUsec);

CHECK_DIF_OK(dif_dma_abort(&dma));

dif_dma_status_t status;
CHECK_DIF_OK(dif_dma_status_get(&dma, &status));

CHECK(status & kDifDmaStatusAborted, "Abort bit not set");

// Reset and re-init the SPI
init_spi_host(&spi_host, (uint32_t)kClockFreqHiSpeedPeripheralHz,
CHUNK_SIZE / 4);
LOG_INFO("spi host re-configuration complete");

// Do the second transaction
setup_spi_dma_transaction(&spi_host, &dma, &received_data[0], CHUNK_SIZE,
TX_SIZE);
CHECK_DIF_OK(dif_dma_start(&dma, kShaMode));
CHECK_DIF_OK(dif_dma_status_poll(&dma, kDifDmaStatusDone));

CHECK_DIF_OK(dif_dma_sha2_digest_get(&dma, kShaMode, digest));

uint32_t digest_len;
CHECK_DIF_OK(dif_dma_get_digest_length(kShaMode, &digest_len));
CHECK_ARRAYS_EQ((uint8_t *)digest, (uint8_t *)kShaDigestExpData, digest_len);

return true;
}

0 comments on commit d659f81

Please sign in to comment.