Switched to using Rc<RefCell<Box<dyn Trait>>> for devices

This commit is contained in:
transistor 2021-10-07 09:41:01 -07:00
parent e186637f49
commit 73d11ddb79
10 changed files with 149 additions and 155 deletions

View File

@ -1,7 +1,7 @@
use crate::error::Error;
use crate::system::System;
use crate::memory::Address;
use crate::memory::{Address, Addressable};
use super::execute::{MC68010};
@ -108,15 +108,15 @@ impl MC68010 {
if args.len() > 1 {
let addr = u32::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse address"))?;
let len = if args.len() > 2 { u32::from_str_radix(args[2], 16).map_err(|_| Error::new("Unable to parse length"))? } else { 0x20 };
system.dump_memory(addr as Address, len as Address);
system.get_bus().dump_memory(addr as Address, len as Address);
} else {
system.dump_memory(self.state.msp as Address, 0x40 as Address);
system.get_bus().dump_memory(self.state.msp as Address, 0x40 as Address);
}
},
"ds" | "stack" | "dumpstack" => {
println!("Stack:");
for addr in &self.debugger.stack_tracer.calls {
println!(" {:08x}", system.read_beu32(*addr as Address)?);
println!(" {:08x}", system.get_bus().read_beu32(*addr as Address)?);
}
},
"so" | "stepout" => {

View File

@ -2,8 +2,8 @@
use std::fmt;
use crate::error::Error;
use crate::memory::Address;
use crate::system::{System, DeviceRefMut};
use crate::memory::{Address, Addressable};
use crate::system::{System, AddressableDeviceRefMut};
use super::execute::ERR_ILLEGAL_INSTRUCTION;
@ -200,13 +200,13 @@ impl M68kDecoder {
}
pub fn decode_at(system: &System, start: u32) -> Result<M68kDecoder, Error> {
let (mut memory, relative_addr) = system.get_device_in_range(start as Address, 12)?;
let (mut memory, relative_addr) = system.get_bus().get_device_at(start as Address, 12)?;
let mut decoder = M68kDecoder::new(start - relative_addr as u32, start);
decoder.instruction = decoder.decode_one(&mut memory)?;
decoder.instruction = decoder.decode_one(&mut memory.borrow_mut())?;
Ok(decoder)
}
pub fn decode_one(&mut self, system: &mut DeviceRefMut<'_>) -> Result<Instruction, Error> {
pub fn decode_one(&mut self, system: &mut AddressableDeviceRefMut<'_>) -> Result<Instruction, Error> {
let ins = self.read_instruction_word(system)?;
match ((ins & 0xF000) >> 12) as u8 {
@ -609,27 +609,27 @@ impl M68kDecoder {
}
}
fn read_instruction_word(&mut self, system: &mut DeviceRefMut<'_>) -> Result<u16, Error> {
let word = system.read_beu16((self.end - self.base) as Address)?;
fn read_instruction_word(&mut self, device: &mut AddressableDeviceRefMut<'_>) -> Result<u16, Error> {
let word = device.read_beu16((self.end - self.base) as Address)?;
//debug!("{:#010x} {:#06x?}", self.end, word);
self.end += 2;
Ok(word)
}
fn read_instruction_long(&mut self, system: &mut DeviceRefMut<'_>) -> Result<u32, Error> {
let word = system.read_beu32((self.end - self.base) as Address)?;
fn read_instruction_long(&mut self, device: &mut AddressableDeviceRefMut<'_>) -> Result<u32, Error> {
let word = device.read_beu32((self.end - self.base) as Address)?;
//debug!("{:#010x} {:#010x}", self.end, word);
self.end += 4;
Ok(word)
}
fn decode_lower_effective_address(&mut self, system: &mut DeviceRefMut<'_>, ins: u16, size: Option<Size>) -> Result<Target, Error> {
fn decode_lower_effective_address(&mut self, system: &mut AddressableDeviceRefMut<'_>, ins: u16, size: Option<Size>) -> Result<Target, Error> {
let reg = get_low_reg(ins);
let mode = get_low_mode(ins);
self.get_mode_as_target(system, mode, reg, size)
}
fn decode_upper_effective_address(&mut self, system: &mut DeviceRefMut<'_>, ins: u16, size: Option<Size>) -> Result<Target, Error> {
fn decode_upper_effective_address(&mut self, system: &mut AddressableDeviceRefMut<'_>, ins: u16, size: Option<Size>) -> Result<Target, Error> {
let reg = get_high_reg(ins);
let mode = get_high_mode(ins);
self.get_mode_as_target(system, mode, reg, size)
@ -645,7 +645,7 @@ impl M68kDecoder {
(rtype, xreg, data, size)
}
pub fn get_mode_as_target(&mut self, system: &mut DeviceRefMut<'_>, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, Error> {
pub fn get_mode_as_target(&mut self, system: &mut AddressableDeviceRefMut<'_>, mode: u8, reg: u8, size: Option<Size>) -> Result<Target, Error> {
let value = match mode {
0b000 => Target::DirectDReg(reg),
0b001 => Target::DirectAReg(reg),

View File

@ -1,7 +1,7 @@
use crate::error::Error;
use crate::timers::CpuTimer;
use crate::memory::Address;
use crate::memory::{Address, Addressable};
use crate::system::System;
use super::debugger::M68kDebugger;
@ -103,7 +103,7 @@ impl MC68010 {
println!("Current Instruction: {:#010x} {:?}", self.decoder.start, self.decoder.instruction);
println!("");
system.dump_memory(self.state.msp as Address, 0x40);
system.get_bus().dump_memory(self.state.msp as Address, 0x40);
println!("");
}
@ -120,8 +120,8 @@ impl MC68010 {
pub fn init(&mut self, system: &System) -> Result<(), Error> {
println!("Initializing CPU");
self.state.msp = system.read_beu32(0)?;
self.state.pc = system.read_beu32(4)?;
self.state.msp = system.get_bus().read_beu32(0)?;
self.state.pc = system.get_bus().read_beu32(4)?;
self.state.status = Status::Running;
Ok(())
@ -153,7 +153,7 @@ impl MC68010 {
self.push_word(system, self.state.sr)?;
self.state.sr |= FLAGS_SUPERVISOR;
self.state.sr &= !FLAGS_TRACING;
self.state.pc = system.read_beu32((self.state.vbr + offset as u32) as Address)?;
self.state.pc = system.get_bus().read_beu32((self.state.vbr + offset as u32) as Address)?;
Ok(())
}
@ -168,7 +168,7 @@ impl MC68010 {
// Print instruction bytes for debugging
let ins_data: Result<String, Error> =
(0..((self.decoder.end - self.decoder.start) / 2)).map(|offset|
Ok(format!("{:04x} ", system.read_beu16((self.decoder.start + (offset * 2)) as Address)?))
Ok(format!("{:04x} ", system.get_bus().read_beu16((self.decoder.start + (offset * 2)) as Address)?))
).collect();
debug!("{:#010x}: {}\n\t{:?}\n", self.decoder.start, ins_data?, self.decoder.instruction);
}
@ -591,12 +591,12 @@ impl MC68010 {
fn push_word(&mut self, system: &System, value: u16) -> Result<(), Error> {
let reg = self.get_stack_pointer_mut();
*reg -= 2;
system.write_beu16(*reg as Address, value)
system.get_bus().write_beu16(*reg as Address, value)
}
fn pop_word(&mut self, system: &System) -> Result<u16, Error> {
let reg = self.get_stack_pointer_mut();
let value = system.read_beu16(*reg as Address)?;
let value = system.get_bus().read_beu16(*reg as Address)?;
*reg += 2;
Ok(value)
}
@ -604,12 +604,12 @@ impl MC68010 {
fn push_long(&mut self, system: &System, value: u32) -> Result<(), Error> {
let reg = self.get_stack_pointer_mut();
*reg -= 4;
system.write_beu32(*reg as Address, value)
system.get_bus().write_beu32(*reg as Address, value)
}
fn pop_long(&mut self, system: &System) -> Result<u32, Error> {
let reg = self.get_stack_pointer_mut();
let value = system.read_beu32(*reg as Address)?;
let value = system.get_bus().read_beu32(*reg as Address)?;
*reg += 4;
Ok(value)
}
@ -902,9 +902,9 @@ fn get_value_sized(value: u32, size: Size) -> u32 {
fn get_address_sized(system: &System, addr: Address, size: Size) -> Result<u32, Error> {
match size {
Size::Byte => system.read_u8(addr).map(|value| value as u32),
Size::Word => system.read_beu16(addr).map(|value| value as u32),
Size::Long => system.read_beu32(addr),
Size::Byte => system.get_bus().read_u8(addr).map(|value| value as u32),
Size::Word => system.get_bus().read_beu16(addr).map(|value| value as u32),
Size::Long => system.get_bus().read_beu32(addr),
}
}
@ -918,9 +918,9 @@ fn set_value_sized(addr: &mut u32, value: u32, size: Size) {
fn set_address_sized(system: &System, addr: Address, value: u32, size: Size) -> Result<(), Error> {
match size {
Size::Byte => system.write_u8(addr, value as u8),
Size::Word => system.write_beu16(addr, value as u16),
Size::Long => system.write_beu32(addr, value),
Size::Byte => system.get_bus().write_u8(addr, value as u8),
Size::Word => system.get_bus().write_beu16(addr, value as u16),
Size::Long => system.get_bus().write_beu32(addr, value),
}
}

View File

@ -1,6 +1,6 @@
use crate::memory::{Address, MemoryBlock};
use crate::system::System;
use crate::memory::{Address, Addressable, MemoryBlock};
use crate::system::{System, wrap_addressable};
use super::execute::MC68010;
use super::decode::Instruction;
@ -14,9 +14,9 @@ fn init_test() -> (MC68010, System) {
// Insert basic initialization
let data = vec![0; 0x00100000];
let mem = MemoryBlock::new(data);
system.add_device(0x00000000, Box::new(mem)).unwrap();
system.write_beu32(0, INIT_STACK as u32).unwrap();
system.write_beu32(4, INIT_ADDR as u32).unwrap();
system.add_addressable_device(0x00000000, wrap_addressable(mem)).unwrap();
system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap();
system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap();
let mut cpu = MC68010::new();
cpu.step(&system).unwrap();
@ -36,7 +36,7 @@ mod tests {
fn instruction_nop() {
let (mut cpu, mut system) = init_test();
system.write_beu16(INIT_ADDR, 0x4e71).unwrap();
system.get_bus().write_beu16(INIT_ADDR, 0x4e71).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::NOP);
cpu.execute_current(&system).unwrap();
@ -48,8 +48,8 @@ mod tests {
fn instruction_ori() {
let (mut cpu, mut system) = init_test();
system.write_beu16(INIT_ADDR, 0x0008).unwrap();
system.write_beu16(INIT_ADDR + 2, 0x00FF).unwrap();
system.get_bus().write_beu16(INIT_ADDR, 0x0008).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x00FF).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::OR(Target::Immediate(0xFF), Target::DirectAReg(0), Size::Byte));
cpu.execute_current(&system).unwrap();
@ -60,9 +60,9 @@ mod tests {
fn instruction_cmpi_equal() {
let (mut cpu, mut system) = init_test();
system.write_beu16(INIT_ADDR, 0x7020).unwrap();
system.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
system.write_beu16(INIT_ADDR + 4, 0x0020).unwrap();
system.get_bus().write_beu16(INIT_ADDR, 0x7020).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 4, 0x0020).unwrap();
cpu.step(&system).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x20), Target::DirectDReg(0), Size::Byte));
@ -74,9 +74,9 @@ mod tests {
fn instruction_cmpi_greater() {
let (mut cpu, mut system) = init_test();
system.write_beu16(INIT_ADDR, 0x7020).unwrap();
system.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
system.write_beu16(INIT_ADDR + 4, 0x0030).unwrap();
system.get_bus().write_beu16(INIT_ADDR, 0x7020).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 4, 0x0030).unwrap();
cpu.step(&system).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x30), Target::DirectDReg(0), Size::Byte));
@ -88,9 +88,9 @@ mod tests {
fn instruction_cmpi_less() {
let (mut cpu, mut system) = init_test();
system.write_beu16(INIT_ADDR, 0x7020).unwrap();
system.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
system.write_beu16(INIT_ADDR + 4, 0x0010).unwrap();
system.get_bus().write_beu16(INIT_ADDR, 0x7020).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 4, 0x0010).unwrap();
cpu.step(&system).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x10), Target::DirectDReg(0), Size::Byte));
@ -102,8 +102,8 @@ mod tests {
fn instruction_andi_sr() {
let (mut cpu, mut system) = init_test();
system.write_beu16(INIT_ADDR, 0x027C).unwrap();
system.write_beu16(INIT_ADDR + 2, 0xF8FF).unwrap();
system.get_bus().write_beu16(INIT_ADDR, 0x027C).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0xF8FF).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ANDtoSR(0xF8FF));
//cpu.execute_current(&system).unwrap();
@ -114,8 +114,8 @@ mod tests {
fn instruction_muls() {
let (mut cpu, mut system) = init_test();
system.write_beu16(INIT_ADDR, 0xC1FC).unwrap();
system.write_beu16(INIT_ADDR + 2, 0x0276).unwrap();
system.get_bus().write_beu16(INIT_ADDR, 0xC1FC).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0276).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::MUL(Target::Immediate(0x276), Target::DirectDReg(0), Size::Word, Sign::Signed));
//cpu.execute_current(&system).unwrap();
@ -126,7 +126,7 @@ mod tests {
fn instruction_asli() {
let (mut cpu, mut system) = init_test();
system.write_beu16(INIT_ADDR, 0xE300).unwrap();
system.get_bus().write_beu16(INIT_ADDR, 0xE300).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left));
@ -140,7 +140,7 @@ mod tests {
fn instruction_asri() {
let (mut cpu, mut system) = init_test();
system.write_beu16(INIT_ADDR, 0xE200).unwrap();
system.get_bus().write_beu16(INIT_ADDR, 0xE200).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right));
@ -154,7 +154,7 @@ mod tests {
fn instruction_roli() {
let (mut cpu, mut system) = init_test();
system.write_beu16(INIT_ADDR, 0xE318).unwrap();
system.get_bus().write_beu16(INIT_ADDR, 0xE318).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left));
@ -168,7 +168,7 @@ mod tests {
fn instruction_rori() {
let (mut cpu, mut system) = init_test();
system.write_beu16(INIT_ADDR, 0xE218).unwrap();
system.get_bus().write_beu16(INIT_ADDR, 0xE218).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right));
@ -220,7 +220,7 @@ mod tests {
let expected_addr = INIT_ADDR;
let expected = 0x12345678;
system.write_beu32(INIT_ADDR, expected).unwrap();
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b010, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectAReg(2));
@ -237,7 +237,7 @@ mod tests {
let expected_addr = INIT_ADDR;
let expected = 0x12345678;
system.write_beu32(INIT_ADDR, expected).unwrap();
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b011, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegInc(2));
@ -255,7 +255,7 @@ mod tests {
let expected_addr = INIT_ADDR + 4;
let expected = 0x12345678;
system.write_beu32(INIT_ADDR, expected).unwrap();
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b100, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegDec(2));
@ -273,7 +273,7 @@ mod tests {
let size = Size::Word;
let expected = 0x1234;
system.write_beu16(cpu.decoder.end as Address, expected as u16).unwrap();
system.get_bus().write_beu16(cpu.decoder.end as Address, expected as u16).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b111, 0b100, Some(size)).unwrap();
assert_eq!(target, Target::Immediate(expected));

View File

@ -11,7 +11,7 @@ use crate::memory::MemoryBlock;
use crate::cpus::m68k::MC68010;
use crate::peripherals::ata::AtaDevice;
use crate::peripherals::mc68681::MC68681;
use crate::system::{System};
use crate::system::{System, wrap_addressable};
fn main() {
let mut system = System::new();
@ -20,19 +20,19 @@ fn main() {
for byte in monitor.contents.iter() {
print!("{:02x} ", byte);
}
system.add_device(0x00000000, Box::new(monitor)).unwrap();
system.add_addressable_device(0x00000000, wrap_addressable(monitor)).unwrap();
let mut ram = MemoryBlock::new(vec![0; 0x00100000]);
ram.load_at(0, "binaries/kernel.bin").unwrap();
system.add_device(0x00100000, Box::new(ram)).unwrap();
system.add_addressable_device(0x00100000, wrap_addressable(ram)).unwrap();
let mut ata = AtaDevice::new();
ata.load("binaries/disk-with-partition-table.img").unwrap();
system.add_device(0x00600000, Box::new(ata)).unwrap();
system.add_addressable_device(0x00600000, wrap_addressable(ata)).unwrap();
let mut serial = MC68681::new();
serial.open().unwrap();
system.add_device(0x00700000, Box::new(serial)).unwrap();
system.add_addressable_device(0x00700000, wrap_addressable(serial)).unwrap();
let mut cpu = MC68010::new();

View File

@ -2,7 +2,7 @@
use std::fs;
use crate::error::Error;
use crate::system::{Clock, DeviceNumber, Device, System};
use crate::system::{Clock, DeviceNumber, Steppable, AddressableDeviceBox, System};
pub type Address = u64;
@ -91,7 +91,7 @@ impl Addressable for MemoryBlock {
}
}
impl Device for MemoryBlock {
impl Steppable for MemoryBlock {
fn step(&mut self, _system: &System) -> Result<Clock, Error> {
Ok(1)
}
@ -101,7 +101,7 @@ impl Device for MemoryBlock {
pub struct Block {
pub base: Address,
pub length: usize,
pub dev: DeviceNumber,
pub dev: AddressableDeviceBox,
}
pub struct Bus {
@ -115,7 +115,7 @@ impl Bus {
}
}
pub fn insert(&mut self, base: Address, length: usize, dev: DeviceNumber) {
pub fn insert(&mut self, base: Address, length: usize, dev: AddressableDeviceBox) {
let block = Block { base, length, dev };
for i in 0..self.blocks.len() {
if self.blocks[i].base > block.base {
@ -126,12 +126,12 @@ impl Bus {
self.blocks.insert(0, block);
}
pub fn get_device_at(&self, addr: Address, count: usize) -> Result<(DeviceNumber, Address), Error> {
pub fn get_device_at(&self, addr: Address, count: usize) -> Result<(AddressableDeviceBox, Address), Error> {
for block in &self.blocks {
if addr >= block.base && addr <= (block.base + block.length as Address) {
let relative_addr = addr - block.base;
if relative_addr as usize + count <= block.length {
return Ok((block.dev, relative_addr));
return Ok((block.dev.clone(), relative_addr));
} else {
return Err(Error::new(&format!("Error reading address {:#010x}", addr)));
}
@ -140,9 +140,42 @@ impl Bus {
return Err(Error::new(&format!("No segment found at {:#08x}", addr)));
}
pub fn max_address(&self) -> Address {
pub fn dump_memory(&mut self, mut addr: Address, mut count: Address) {
while count > 0 {
let mut line = format!("{:#010x}: ", addr);
let to = if count < 16 { count / 2 } else { 8 };
for _ in 0..to {
let word = self.read_beu16(addr);
if word.is_err() {
println!("{}", line);
return;
}
line += &format!("{:#06x} ", word.unwrap());
addr += 2;
count -= 2;
}
println!("{}", line);
}
}
}
impl Addressable for Bus {
fn len(&self) -> usize {
let block = &self.blocks[self.blocks.len() - 1];
block.base + block.length as Address
(block.base as usize) + block.length
}
fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
let (dev, relative_addr) = self.get_device_at(addr, count)?;
let result = dev.borrow_mut().read(relative_addr, count);
result
}
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
let (dev, relative_addr) = self.get_device_at(addr, data.len())?;
let result = dev.borrow_mut().write(relative_addr, data);
result
}
}

View File

@ -3,7 +3,7 @@ use std::fs;
use crate::error::Error;
use crate::memory::{Address, Addressable};
use crate::system::{Clock, Device, System};
use crate::system::{Clock, Steppable, System};
const ATA_REG_DEV_CONTROL: Address = 0x1D;
@ -120,7 +120,7 @@ println!(">> {:x}", data[0]);
}
}
impl Device for AtaDevice {
impl Steppable for AtaDevice {
fn step(&mut self, _system: &System) -> Result<Clock, Error> {
Ok(1)
}

View File

@ -9,7 +9,7 @@ use nix::unistd::sleep;
use nix::fcntl::{fcntl, FcntlArg};
use crate::error::Error;
use crate::system::{Clock, Device, System};
use crate::system::{Clock, Steppable, System};
use crate::memory::{Address, Addressable};
@ -147,7 +147,7 @@ impl Addressable for MC68681 {
}
}
impl Device for MC68681 {
impl Steppable for MC68681 {
fn step(&mut self, system: &System) -> Result<Clock, Error> {
self.step_internal(system)?;
Ok(1)

View File

@ -1,4 +1,5 @@
use std::rc::Rc;
use std::cell::{RefCell, RefMut};
use crate::error::Error;
@ -8,109 +9,63 @@ use crate::memory::{self, Address, Addressable, Bus};
pub type Clock = u64;
pub type DeviceNumber = u8;
pub type DeviceRefMut<'a> = RefMut<'a, Box<dyn AddressableDevice>>;
pub trait Device: Addressable {
pub trait Steppable {
fn step(&mut self, system: &System) -> Result<Clock, Error>;
}
pub trait AddressableDevice: Device + Addressable { }
pub trait Interruptable {
fn handle_interrupt(&mut self, system: &System, number: u8) -> Result<(), Error>;
}
impl<T: Device + Addressable> AddressableDevice for T { }
pub trait AddressableDevice: Addressable + Steppable { }
pub trait InterruptableDevice: Interruptable + Steppable { }
impl<T: Addressable + Steppable> AddressableDevice for T { }
impl<T: Interruptable + Steppable> InterruptableDevice for T { }
pub type AddressableDeviceBox = Rc<RefCell<Box<dyn AddressableDevice>>>;
pub type InterruptableDeviceBox = Rc<RefCell<Box<dyn InterruptableDevice>>>;
pub type AddressableDeviceRefMut<'a> = RefMut<'a, Box<dyn AddressableDevice>>;
pub fn wrap_addressable<T: AddressableDevice + 'static>(value: T) -> AddressableDeviceBox {
Rc::new(RefCell::new(Box::new(value)))
}
pub struct System {
pub clock: Clock,
pub devices: Vec<RefCell<Box<dyn AddressableDevice>>>,
pub bus: Bus,
pub addressable_devices: Vec<AddressableDeviceBox>,
pub bus: RefCell<Bus>,
}
impl System {
pub fn new() -> System {
System {
clock: 0,
devices: vec![],
bus: Bus::new(),
addressable_devices: vec![],
bus: RefCell::new(Bus::new()),
}
}
pub fn add_device(&mut self, addr: Address, device: Box<dyn AddressableDevice>) -> Result<(), Error> {
self.bus.insert(addr, device.len(), self.devices.len() as DeviceNumber);
self.devices.push(RefCell::new(device));
pub fn get_bus(&self) -> RefMut<'_, Bus> {
self.bus.borrow_mut()
}
pub fn add_addressable_device(&mut self, addr: Address, device: AddressableDeviceBox) -> Result<(), Error> {
let length = device.borrow().len();
self.bus.borrow_mut().insert(addr, length, device.clone());
self.addressable_devices.push(device);
Ok(())
}
pub fn step(&mut self) -> Result<(), Error> {
self.clock += 1;
for dev in &self.devices {
for dev in &self.addressable_devices {
dev.borrow_mut().step(&self)?;
}
Ok(())
}
pub fn get_device_in_range(&self, addr: Address, count: usize) -> Result<(DeviceRefMut<'_>, Address), Error> {
let (dev, relative_addr) = self.bus.get_device_at(addr, count)?;
Ok((self.devices[dev as usize].borrow_mut(), relative_addr))
}
pub fn read(&self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
let (dev, relative_addr) = self.bus.get_device_at(addr, count)?;
self.devices[dev as usize].borrow_mut().read(relative_addr, count)
}
pub fn write(&self, addr: Address, data: &[u8]) -> Result<(), Error> {
let (dev, relative_addr) = self.bus.get_device_at(addr, data.len())?;
self.devices[dev as usize].borrow_mut().write(relative_addr, data)
}
pub fn read_u8(&self, addr: Address) -> Result<u8, Error> {
Ok(self.read(addr, 1)?[0])
}
pub fn read_beu16(&self, addr: Address) -> Result<u16, Error> {
Ok(memory::read_beu16(&self.read(addr, 2)?))
}
pub fn read_beu32(&self, addr: Address) -> Result<u32, Error> {
Ok(memory::read_beu32(&self.read(addr, 4)?))
}
pub fn write_u8(&self, addr: Address, value: u8) -> Result<(), Error> {
let data = [value];
self.write(addr, &data)
}
pub fn write_beu16(&self, addr: Address, value: u16) -> Result<(), Error> {
let data = memory::write_beu16(value);
self.write(addr, &data)
}
pub fn write_beu32(&self, addr: Address, value: u32) -> Result<(), Error> {
let data = memory::write_beu32(value);
self.write(addr, &data)
}
pub fn dump_memory(&self, mut addr: Address, mut count: Address) {
while count > 0 {
let mut line = format!("{:#010x}: ", addr);
let to = if count < 16 { count / 2 } else { 8 };
for _ in 0..to {
let word = self.read_beu16(addr);
if word.is_err() {
println!("{}", line);
return;
}
line += &format!("{:#06x} ", word.unwrap());
addr += 2;
count -= 2;
}
println!("{}", line);
}
}
}

View File

@ -1,4 +1,10 @@
* how will you add the cpu, which is not addressable, but is steppable, and also interruptable... what else?
* should you simulate bus arbitration?
* if the bus had an Rc<RefCell<Box<dyn AddressableDevice>>>, then it could be like AddressSpace used to be, with it's own Addressable, and then you could
access one of multiple busses to do an op on it, rather than a single bus per machine
* can you get rid of the duplicate read/write functions in System?
* how do you pass in a mutable system to a mutable device? At the very least, I need the AddressSpace, but that needs access to the devices/memory segments.
I could make System contain refcells for submutability