Rework MMU trait to allow for full control of MMU issued memory cycles
This commit is contained in:
parent
5259bbbe3c
commit
3a4d2b0c9d
@ -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
|
||||||
|
19
src/card.rs
19
src/card.rs
@ -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 {
|
||||||
|
48
src/mmu.rs
48
src/mmu.rs
@ -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");
|
||||||
|
Loading…
Reference in New Issue
Block a user