Skip to content

Commit

Permalink
sw-emulator: Fix RRI and DMA
Browse files Browse the repository at this point in the history
- Fix FIFO operations
- Make sure hw-mode also has a handle_dma bus operation
- Hook up recovery image later, because with real hardware it's also not
  statically available.
- Add more tests for derive handle_dma_fn
- Update recovery register interface to have some registers as RW
  • Loading branch information
ArthurHeymans committed Oct 25, 2024
1 parent b677f54 commit 163d728
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 47 deletions.
3 changes: 3 additions & 0 deletions hw-model/src/bus_logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,7 @@ impl<TBus: Bus> Bus for BusLogger<TBus> {
fn update_reset(&mut self) {
self.bus.update_reset();
}
fn handle_dma(&mut self) {
self.bus.handle_dma();
}
}
18 changes: 17 additions & 1 deletion hw-model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ fn trace_path_or_env(trace_path: Option<PathBuf>) -> Option<PathBuf> {

pub struct BootParams<'a> {
pub fuses: Fuses,
pub active_mode: bool,
pub fw_image: Option<&'a [u8]>,
pub initial_dbg_manuf_service_reg: u32,
pub initial_repcnt_thresh_reg: Option<CptraItrngEntropyConfig1WriteVal>,
Expand All @@ -260,6 +261,7 @@ impl<'a> Default for BootParams<'a> {
fn default() -> Self {
Self {
fuses: Default::default(),
active_mode: false,
fw_image: Default::default(),
initial_dbg_manuf_service_reg: Default::default(),
initial_repcnt_thresh_reg: Default::default(),
Expand Down Expand Up @@ -541,7 +543,11 @@ pub trait HwModel: SocManager {
}
writeln!(self.output().logger(), "ready_for_fw is high")?;
self.cover_fw_mage(fw_image);
self.upload_firmware(fw_image)?;
if boot_params.active_mode {
self.upload_firmware_rri(fw_image)?;
} else {
self.upload_firmware(fw_image)?;
}
}

Ok(())
Expand Down Expand Up @@ -1031,6 +1037,16 @@ pub trait HwModel: SocManager {
Ok(())
}

/// HW-model function to place the image in rri
fn put_firmware_in_rri(&mut self, firmware: &[u8]) -> Result<(), ModelError>;

/// Upload fw image to RRI.
fn upload_firmware_rri(&mut self, firmware: &[u8]) -> Result<(), ModelError> {
self.put_firmware_in_rri(firmware)?;
// TODO Add method to inform caliptra to start fetching from the RRI
Ok(())
}

fn wait_for_mailbox_receive(&mut self) -> Result<MailboxRecvTxn<Self>, ModelError>
where
Self: Sized,
Expand Down
5 changes: 5 additions & 0 deletions hw-model/src/model_emulated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,4 +290,9 @@ impl HwModel for ModelEmulated {
self.cpu.warm_reset();
self.step();
}

fn put_firmware_in_rri(&mut self, firmware: &[u8]) -> Result<(), ModelError> {
self.cpu.bus.bus.recovery.cms_data = Some(Rc::new(firmware.to_vec()));
Ok(())
}
}
5 changes: 5 additions & 0 deletions hw-model/src/model_fpga_realtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::time::{Duration, Instant};
use uio::{UioDevice, UioError};

use crate::EtrngResponse;
use crate::ModelError;
use crate::Output;
use crate::{HwModel, SecurityState, SocManager, TrngMode};

Expand Down Expand Up @@ -528,6 +529,10 @@ impl HwModel for ModelFpgaRealtime {
.write_volatile(pauser);
}
}

fn put_firmware_in_rri(&mut self, firmware: &[u8]) -> Result<(), ModelError> {
todo!()
}
}

impl ModelFpgaRealtime {
Expand Down
4 changes: 4 additions & 0 deletions hw-model/src/model_verilated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,4 +440,8 @@ impl ModelVerilated {
self.v.input.itrng_valid = false;
}
}

fn put_firmware_in_rri(&mut self, firmware: &[u8]) -> Result<(), ModelError> {
todo!()
}
}
12 changes: 10 additions & 2 deletions sw-emulator/lib/derive/tests/derive_bus_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl From<MyCustomField> for RvData {

#[derive(Bus)]
#[poll_fn(poll)]
#[handle_dma_fn(handle_dma)]
#[allow(clippy::manual_non_exhaustive)]
struct MyBus {
pub log: Log,
Expand Down Expand Up @@ -161,6 +162,10 @@ impl MyBus {
fn poll(&self) {
write!(self.log.w(), "poll; ").unwrap();
}

fn handle_dma(&self) {
write!(self.log.w(), "dma; ").unwrap();
}
}

#[test]
Expand Down Expand Up @@ -517,7 +522,7 @@ fn test_write_dispatch() {
}

#[test]
fn test_poll() {
fn test_poll_and_dma() {
let mut bus = MyBus {
rom: Ram::new(vec![0u8; 65536]),
sram: Ram::new(vec![0u8; 65536]),
Expand Down Expand Up @@ -547,5 +552,8 @@ fn test_poll() {
};
Bus::poll(&mut bus);
assert_eq!(bus.log.take(), "poll; ");
assert_eq!(bus.fake.log.take(), "poll()\n")
assert_eq!(bus.fake.log.take(), "poll()\n");

Bus::handle_dma(&mut bus);
assert_eq!(bus.log.take(), "dma; ");
}
38 changes: 24 additions & 14 deletions sw-emulator/lib/periph/src/dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use caliptra_emu_types::{RvAddr, RvData, RvSize};
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;
use tock_registers::interfaces::{Readable, Writeable};
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
use tock_registers::register_bitfields;

use crate::CaliptraRootBus;
Expand Down Expand Up @@ -66,7 +66,7 @@ register_bitfields! [
/// Control
Control [
GO OFFSET(0) NUMBITS(1) [],
FLUSH OFFSET(0) NUMBITS(1) [],
FLUSH OFFSET(1) NUMBITS(1) [],
READ_ROUTE OFFSET(16) NUMBITS(2) [
DISABLE = 0b00,
MAILBOX = 0b01,
Expand Down Expand Up @@ -177,7 +177,7 @@ impl DmaRegs {
pub fn new(clock: &Clock) -> Self {
Self {
name: ReadOnlyRegister::new(Self::NAME),
capabilities: ReadOnlyRegister::new(Self::FIFO_SIZE as u32), // MAX FIFO DEPTH
capabilities: ReadOnlyRegister::new(Self::FIFO_SIZE as u32 - 1), // MAX FIFO DEPTH
control: ReadWriteRegister::new(0),
status0: ReadOnlyRegister::new(0),
status1: ReadOnlyRegister::new(0),
Expand Down Expand Up @@ -206,6 +206,7 @@ impl DmaRegs {
if self.control.reg.is_set(Control::FLUSH) {
self.fifo.clear();
self.status0.reg.write(Status0::DMA_FSM_PRESENT_STATE::IDLE);
self.control.reg.set(0);
}

if self.control.reg.is_set(Control::GO) {
Expand All @@ -222,7 +223,7 @@ impl DmaRegs {
);
self.status0
.reg
.write(Status0::DMA_FSM_PRESENT_STATE::WAIT_DATA);
.write(Status0::BUSY::SET + Status0::DMA_FSM_PRESENT_STATE::WAIT_DATA);
}

Ok(())
Expand All @@ -238,17 +239,18 @@ impl DmaRegs {

pub fn on_read_data(&mut self, size: RvSize) -> Result<RvData, BusError> {
let range = 0..size as usize;
let bytes = range.fold(0, |mut acc, b| {
acc |= self.fifo.pop_front().unwrap_or(
let bytes: RvData = range.fold(0, |mut acc, b| {
acc |= (self.fifo.pop_front().unwrap_or(
// self.status0
// .reg
// .write(Status0::DMA_FSM_PRESENT_STATE::ERROR);
// TODO write status in interrupt
0,
) << (8 * b);
) as RvData)
<< (8 * b);
acc
});
Ok(bytes as RvData)
Ok(bytes)
}

fn write_to_mailbox(&mut self, data: Vec<u8>, root_bus: &mut CaliptraRootBus) {
Expand All @@ -265,7 +267,7 @@ impl DmaRegs {

data.chunks(RvSize::Word as usize).for_each(|c| {
mailbox_regs
.write_din(RvSize::Word, u32::from_ne_bytes(c.try_into().unwrap()))
.write_din(RvSize::Word, u32::from_le_bytes(c.try_into().unwrap()))
.unwrap()
});
}
Expand All @@ -278,7 +280,11 @@ impl DmaRegs {
let read_data =
// Special case for putting stuff image in the mailbox from recovery register interface
if read_addr == Self::RRI_BASE + Self::RRI_FIFO_OFFSET && read_addr_fixed {
(*root_bus.recovery.cms_data).clone()
if let Some(data) = root_bus.recovery.cms_data.clone() {
(*data).clone()
} else {
vec![]
}
} else {
let range = read_addr..read_addr + self.byte_count.reg.get();
range
Expand All @@ -290,14 +296,13 @@ impl DmaRegs {
.unwrap()
.to_le_bytes()
}).collect()

};
match self.control.reg.read_as_enum(Control::READ_ROUTE) {
Some(Control::READ_ROUTE::Value::MAILBOX) => {
self.write_to_mailbox(read_data, root_bus);
}
Some(Control::READ_ROUTE::Value::AHB_FIFO) => {
if self.fifo.len() + read_data.len() <= Self::FIFO_SIZE {
if self.fifo.len() + read_data.len() > Self::FIFO_SIZE {
self.status0
.reg
.write(Status0::DMA_FSM_PRESENT_STATE::ERROR);
Expand All @@ -307,6 +312,9 @@ impl DmaRegs {
} else {
read_data.iter().for_each(|b| self.fifo.push_back(*b));
}
self.status0
.reg
.modify(Status0::FIFO_DEPTH.val(self.fifo.len() as u32));
}
Some(Control::READ_ROUTE::Value::AXI_WR) => {
todo!()
Expand Down Expand Up @@ -343,7 +351,9 @@ impl DmaRegs {
_ => {}
}

self.status0.reg.write(Status0::DMA_FSM_PRESENT_STATE::DONE);
self.status0
.reg
.modify(Status0::BUSY::CLEAR + Status0::DMA_FSM_PRESENT_STATE::DONE);
}
}

Expand All @@ -370,6 +380,6 @@ mod tests {
let mut dma = Dma::new(&clock);

let capabilities = dma.read(RvSize::Word, CAPABILITIES_OFFSET).unwrap();
assert_eq!(capabilities, 0x1000);
assert_eq!(capabilities, 0xfff);
}
}
Loading

0 comments on commit 163d728

Please sign in to comment.