Rework MMU trait to allow for full control of MMU issued memory cycles

This commit is contained in:
pjht 2023-03-20 15:06:16 -05:00
parent 5259bbbe3c
commit 3a4d2b0c9d
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
3 changed files with 88 additions and 72 deletions

View File

@ -148,43 +148,51 @@ impl Backplane {
} }
pub fn read_word(&self, address: u32) -> Result<u16, BusError> { pub fn read_word(&self, address: u32) -> Result<u16, BusError> {
self.mem_helper( if let Some(mmu) = self.mmu {
address, self.cards[mmu]
|mut card| card.read_word(address), .borrow_mut()
|mut card| card.read_word_io(address as u8), .try_as_mmu()
false, .unwrap()
false, .read_word(address, self)
) } else {
self.read_word_phys(address)
}
} }
pub fn read_byte(&self, address: u32) -> Result<u8, BusError> { pub fn read_byte(&self, address: u32) -> Result<u8, BusError> {
self.mem_helper( if let Some(mmu) = self.mmu {
address, self.cards[mmu]
|mut card| card.read_byte(address), .borrow_mut()
|mut card| card.read_byte_io(address as u8), .try_as_mmu()
false, .unwrap()
false, .read_byte(address, self)
) } else {
self.read_byte_phys(address)
}
} }
pub fn write_word(&self, address: u32, data: u16) -> Result<(), BusError> { pub fn write_word(&self, address: u32, data: u16) -> Result<(), BusError> {
self.mem_helper( if let Some(mmu) = self.mmu {
address, self.cards[mmu]
|mut card| card.write_word(address, data), .borrow_mut()
|mut card| card.write_word_io(address as u8, data), .try_as_mmu()
false, .unwrap()
true, .write_word(address, data, self)
) } else {
self.write_word_phys(address, data)
}
} }
pub fn write_byte(&self, address: u32, data: u8) -> Result<(), BusError> { pub fn write_byte(&self, address: u32, data: u8) -> Result<(), BusError> {
self.mem_helper( if let Some(mmu) = self.mmu {
address, self.cards[mmu]
|mut card| card.write_byte(address, data), .borrow_mut()
|mut card| card.write_byte_io(address as u8, data), .try_as_mmu()
false, .unwrap()
true, .write_byte(address, data, self)
) } else {
self.write_byte_phys(address, data)
}
} }
pub fn read_word_phys(&self, address: u32) -> Result<u16, BusError> { pub fn read_word_phys(&self, address: u32) -> Result<u16, BusError> {
@ -192,41 +200,30 @@ impl Backplane {
address, address,
|mut card| card.read_word(address), |mut card| card.read_word(address),
|mut card| card.read_word_io(address as u8), |mut card| card.read_word_io(address as u8),
true,
false,
) )
} }
#[allow(dead_code)]
pub fn read_byte_phys(&self, address: u32) -> Result<u8, BusError> { pub fn read_byte_phys(&self, address: u32) -> Result<u8, BusError> {
self.mem_helper( self.mem_helper(
address, address,
|mut card| card.read_byte(address), |mut card| card.read_byte(address),
|mut card| card.read_byte_io(address as u8), |mut card| card.read_byte_io(address as u8),
true,
false,
) )
} }
#[allow(dead_code)]
pub fn write_word_phys(&self, address: u32, data: u16) -> Result<(), BusError> { pub fn write_word_phys(&self, address: u32, data: u16) -> Result<(), BusError> {
self.mem_helper( self.mem_helper(
address, address,
|mut card| card.write_word(address, data), |mut card| card.write_word(address, data),
|mut card| card.write_word_io(address as u8, data), |mut card| card.write_word_io(address as u8, data),
true,
true,
) )
} }
#[allow(dead_code)]
pub fn write_byte_phys(&self, address: u32, data: u8) -> Result<(), BusError> { pub fn write_byte_phys(&self, address: u32, data: u8) -> Result<(), BusError> {
self.mem_helper( self.mem_helper(
address, address,
|mut card| card.write_byte(address, data), |mut card| card.write_byte(address, data),
|mut card| card.write_byte_io(address as u8, data), |mut card| card.write_byte_io(address as u8, data),
true,
true,
) )
} }
@ -235,29 +232,11 @@ impl Backplane {
address: u32, address: u32,
mut mem_func: M, mut mem_func: M,
mut io_func: I, mut io_func: I,
bypass_mmu: bool,
write: bool,
) -> Result<T, BusError> ) -> Result<T, BusError>
where where
M: FnMut(RefMut<'_, dyn Card>) -> NullableResult<T, BusError>, M: FnMut(RefMut<'_, dyn Card>) -> NullableResult<T, BusError>,
I: FnMut(RefMut<'_, dyn Card>) -> NullableResult<T, BusError>, I: FnMut(RefMut<'_, dyn Card>) -> NullableResult<T, BusError>,
{ {
let address = if bypass_mmu {
address
} else if let Some(card_no) = self.mmu {
match self.cards[card_no]
.borrow_mut()
.try_as_mmu()
.unwrap()
.translate_address(self, address, write)
{
NullableResult::Ok(address) => address,
NullableResult::Err(e) => return Err(e),
NullableResult::Null => return Err(BusError),
}
} else {
address
};
let res = match address { let res = match address {
(0..=0x00fe_ffff) | (0x0100_0000..=0xffff_ffff) => self (0..=0x00fe_ffff) | (0x0100_0000..=0xffff_ffff) => self
.cards .cards

View File

@ -141,14 +141,19 @@ pub trait Card: Debug + Display + mopa::Any {
mopafy!(Card); mopafy!(Card);
pub trait Mmu: Debug { pub trait Mmu: Debug {
fn translate_address( fn read_word(&mut self, address: u32, backplane: &Backplane) -> Result<u16, BusError>;
&mut self, fn read_byte(&mut self, address: u32, backplane: &Backplane) -> Result<u8, BusError>;
backplane: &Backplane,
address: u32,
write: bool,
) -> NullableResult<u32, BusError>;
}
fn write_word(
&mut self,
address: u32,
data: u16,
backplane: &Backplane,
) -> Result<(), BusError>;
fn write_byte(&mut self, address: u32, data: u8, backplane: &Backplane)
-> Result<(), BusError>;
}
#[allow(dead_code)] #[allow(dead_code)]
pub const fn u64_set_be_byte(val: u64, idx: u8, byte: u8) -> u64 { pub const fn u64_set_be_byte(val: u64, idx: u8, byte: u8) -> u64 {

View File

@ -173,13 +173,13 @@ impl Display for MmuCard {
} }
} }
impl Mmu for MmuCard { impl MmuCard {
fn translate_address( fn translate_address(
&mut self, &mut self,
backplane: &Backplane,
address: u32, address: u32,
backplane: &Backplane,
write: bool, write: bool,
) -> NullableResult<u32, BusError> { ) -> Result<u32, BusError> {
let print_debug = self.print_debug; let print_debug = self.print_debug;
if self.enabled { if self.enabled {
let page = address >> 12; let page = address >> 12;
@ -197,7 +197,7 @@ impl Mmu for MmuCard {
if print_debug { if print_debug {
println!("No mapping frame for this quarter"); println!("No mapping frame for this quarter");
} }
return NullableResult::Null; return Err(BusError);
} }
let map_frame = self.map_frames[(page >> 10) as usize]; let map_frame = self.map_frames[(page >> 10) as usize];
let entry_address = (map_frame) | ((page & 0x3FF) << 2); let entry_address = (map_frame) | ((page & 0x3FF) << 2);
@ -218,7 +218,7 @@ impl Mmu for MmuCard {
if print_debug { if print_debug {
println!("Entry not writable"); println!("Entry not writable");
} }
return NullableResult::Err(BusError); return Err(BusError);
} }
if print_debug { if print_debug {
println!( println!(
@ -226,17 +226,49 @@ impl Mmu for MmuCard {
(entry.frame << 12) | offset (entry.frame << 12) | offset
); );
} }
NullableResult::Ok((entry.frame << 12) | offset) Ok((entry.frame << 12) | offset)
} else { } else {
if print_debug { if print_debug {
println!("Entry not present"); println!("Entry not present");
} }
NullableResult::Null Err(BusError)
} }
} else { } else {
NullableResult::Ok(address) Ok(address)
} }
} }
} }
impl Mmu for MmuCard {
fn read_word(&mut self, address: u32, backplane: &Backplane) -> Result<u16, BusError> {
let address = self.translate_address(address, backplane, false)?;
backplane.read_word_phys(address)
}
fn read_byte(&mut self, address: u32, backplane: &Backplane) -> Result<u8, BusError> {
let address = self.translate_address(address, backplane, false)?;
backplane.read_byte_phys(address)
}
fn write_word(
&mut self,
address: u32,
data: u16,
backplane: &Backplane,
) -> Result<(), BusError> {
let address = self.translate_address(address, backplane, true)?;
backplane.write_word_phys(address, data)
}
fn write_byte(
&mut self,
address: u32,
data: u8,
backplane: &Backplane,
) -> Result<(), BusError> {
let address = self.translate_address(address, backplane, true)?;
backplane.write_byte_phys(address, data)
}
}
register!(MmuCard, "mmu"); register!(MmuCard, "mmu");