opentitanlib/test_utils/
mem.rs

1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5use anyhow::Result;
6use arrayvec::ArrayVec;
7use std::time::Duration;
8
9use crate::io::console::ConsoleDevice;
10use crate::test_utils::e2e_command::TestCommand;
11use crate::test_utils::rpc::{ConsoleRecv, ConsoleSend};
12use crate::test_utils::status::Status;
13
14// Bring in the auto-generated sources.
15include!(env!("mem"));
16
17impl MemRead32Req {
18    pub fn execute<T>(device: &T, address: u32) -> Result<u32>
19    where
20        T: ConsoleDevice + ?Sized,
21    {
22        TestCommand::MemRead32.send_with_crc(device)?;
23        let op = MemRead32Req { address };
24        op.send_with_crc(device)?;
25        let resp = MemRead32Resp::recv(device, Duration::from_secs(300), false)?;
26        Ok(resp.value)
27    }
28}
29
30impl MemReadReq {
31    pub fn execute<T>(device: &T, start_address: u32, data: &mut [u8]) -> Result<()>
32    where
33        T: ConsoleDevice + ?Sized,
34    {
35        let bytes_to_read = data.len();
36        let mut bytes_read = 0_usize;
37        while bytes_read < bytes_to_read {
38            let size_check = MemReadResp {
39                data_len: 0,
40                data: ArrayVec::new(),
41            };
42            let op_size = std::cmp::min(bytes_to_read - bytes_read, size_check.data.capacity());
43            TestCommand::MemRead.send_with_crc(device)?;
44            let op = MemReadReq {
45                address: start_address + (bytes_read as u32),
46                data_len: op_size.try_into().unwrap(),
47            };
48            op.send_with_crc(device)?;
49            let resp = MemReadResp::recv(device, Duration::from_secs(300), false)?;
50            data[bytes_read..(bytes_read + op_size)].copy_from_slice(resp.data.as_slice());
51            bytes_read += op_size;
52        }
53        Ok(())
54    }
55}
56
57impl MemWrite32Req {
58    pub fn execute<T>(device: &T, address: u32, value: u32) -> Result<()>
59    where
60        T: ConsoleDevice + ?Sized,
61    {
62        TestCommand::MemWrite32.send_with_crc(device)?;
63        let op = MemWrite32Req { address, value };
64        op.send_with_crc(device)?;
65        Status::recv(device, Duration::from_secs(300), false)?;
66        Ok(())
67    }
68}
69
70impl MemWriteReq {
71    pub fn execute<T>(device: &T, start_address: u32, data: &[u8]) -> Result<()>
72    where
73        T: ConsoleDevice + ?Sized,
74    {
75        let bytes_to_write = data.len();
76        let mut bytes_written = 0_usize;
77        while bytes_written < bytes_to_write {
78            TestCommand::MemWrite.send_with_crc(device)?;
79            let mut op = MemWriteReq {
80                address: start_address + (bytes_written as u32),
81                data_len: 0,
82                data: ArrayVec::new(),
83            };
84            let op_size = std::cmp::min(bytes_to_write - bytes_written, op.data.capacity());
85            op.data
86                .try_extend_from_slice(&data[bytes_written..(bytes_written + op_size)])?;
87            op.data_len = op_size.try_into().unwrap();
88            op.send_with_crc(device)?;
89            let _ = Status::recv(device, Duration::from_secs(300), false)?;
90            bytes_written += op_size;
91        }
92        Ok(())
93    }
94}