Factor out common parts of backplane memory code

This commit is contained in:
pjht 2022-11-11 07:36:04 -06:00
parent 41af1a55d9
commit ec7db304b8

View File

@ -1,4 +1,4 @@
use nullable_result::GeneralIterExt; use nullable_result::{GeneralIterExt, NullableResult};
use serde_yaml::Mapping; use serde_yaml::Mapping;
use thiserror::Error; use thiserror::Error;
@ -48,77 +48,65 @@ impl Backplane {
} }
pub fn read_word(&mut self, address: u32) -> Result<u16, BusError> { pub fn read_word(&mut self, address: u32) -> Result<u16, BusError> {
match address { self.mem_helper(
(0..=0x00fe_ffff) | (0x0100_0000..=0xFFFF_FFFF) => self address,
.cards |card| card.read_word(address),
.iter_mut() |card| card.read_word_io(address as u8),
.try_find_map(|card| card.read_word(address)) 0,
.result(BusError), )
(0x00ff_0000..=0x00ff_00ff) => Ok(0),
(0x00ff_0100..=0x00ff_ffff) => self
.cards
.get_mut(((address >> 8) as u8 - 1) as usize)
.map_or(Ok(0), |card| {
card.read_word_io(address as u8)
.optional_result()
.unwrap_or(Ok(0))
}),
}
} }
pub fn read_byte(&mut self, address: u32) -> Result<u8, BusError> { pub fn read_byte(&mut self, address: u32) -> Result<u8, BusError> {
match address { self.mem_helper(
(0..=0x00fe_ffff) | (0x0100_0000..=0xFFFF_FFFF) => self address,
.cards |card| card.read_byte(address),
.iter_mut() |card| card.read_byte_io(address as u8),
.try_find_map(|card| card.read_byte(address)) 0,
.result(BusError), )
(0x00ff_0000..=0x00ff_00ff) => Ok(0),
(0x00ff_0100..=0x00ff_ffff) => self
.cards
.get_mut(((address >> 8) as u8 - 1) as usize)
.map_or(Ok(0), |card| {
card.read_byte_io(address as u8)
.optional_result()
.unwrap_or(Ok(0))
}),
}
} }
pub fn write_word(&mut self, address: u32, data: u16) -> Result<(), BusError> { pub fn write_word(&mut self, address: u32, data: u16) -> Result<(), BusError> {
match address { self.mem_helper(
(0..=0x00fe_ffff) | (0x0100_0000..=0xFFFF_FFFF) => self address,
.cards |card| card.write_word(address, data),
.iter_mut() |card| card.write_word_io(address as u8, data),
.try_find_map(|card| card.write_word(address, data)) (),
.result(BusError), )
(0x00ff_0000..=0x00ff_00ff) => Ok(()),
(0x00ff_0100..=0x00ff_ffff) => self
.cards
.get_mut(((address >> 8) as u8 - 1) as usize)
.map_or(Ok(()), |card| {
card.write_word_io(address as u8, data)
.optional_result()
.unwrap_or(Ok(()))
}),
}
} }
pub fn write_byte(&mut self, address: u32, data: u8) -> Result<(), BusError> { pub fn write_byte(&mut self, address: u32, data: u8) -> Result<(), BusError> {
self.mem_helper(
address,
|card| card.write_byte(address, data),
|card| card.write_byte_io(address as u8, data),
(),
)
}
fn mem_helper<T, M, I>(
&mut self,
address: u32,
mut mem_func: M,
mut io_func: I,
io_default: T,
) -> Result<T, BusError>
where
M: FnMut(&mut Box<dyn Card>) -> NullableResult<T, BusError>,
I: FnMut(&mut Box<dyn Card>) -> NullableResult<T, BusError>,
T: Copy,
{
match address { match address {
(0..=0x00fe_ffff) | (0x0100_0000..=0xFFFF_FFFF) => self (0..=0x00fe_ffff) | (0x0100_0000..=0xffff_ffff) => self
.cards .cards
.iter_mut() .iter_mut()
.try_find_map(|card| card.write_byte(address, data)) .try_find_map(&mut mem_func)
.result(BusError), .result(BusError),
(0x00ff_0000..=0x00ff_00ff) => Ok(()), (0x00ff_0000..=0x00ff_00ff) => Ok(io_default),
(0x00ff_0100..=0x00ff_ffff) => self (0x00ff_0100..=0x00ff_ffff) => self
.cards .cards
.get_mut(((address >> 8) as u8 - 1) as usize) .get_mut(((address >> 8) as u8 - 1) as usize)
.map_or(Ok(()), |card| { .map_or(Ok(io_default), |card| {
card.write_byte_io(address as u8, data) io_func(card).optional_result().unwrap_or(Ok(io_default))
.optional_result()
.unwrap_or(Ok(()))
}), }),
} }
} }