moa/src/system.rs

141 lines
4.0 KiB
Rust
Raw Normal View History

use std::rc::Rc;
2021-11-01 23:51:45 +00:00
use std::cell::{Cell, RefCell, RefMut};
2021-10-30 03:06:15 +00:00
use std::collections::HashMap;
use crate::memory::Bus;
2021-11-01 23:51:45 +00:00
use crate::error::Error;
use crate::debugger::Debugger;
2021-10-09 18:00:32 +00:00
use crate::interrupts::InterruptController;
2021-10-24 05:22:02 +00:00
use crate::devices::{Clock, ClockElapsed, Address, TransmutableBox};
pub struct System {
pub clock: Clock,
2021-11-01 23:51:45 +00:00
pub devices: HashMap<String, TransmutableBox>,
pub event_queue: Vec<DeviceStep>,
pub debug_enabled: Cell<bool>,
pub bus: Rc<RefCell<Bus>>,
2021-10-09 18:00:32 +00:00
pub interrupt_controller: RefCell<InterruptController>,
}
impl System {
pub fn new() -> System {
System {
clock: 0,
2021-11-01 23:51:45 +00:00
devices: HashMap::new(),
2021-10-30 03:06:15 +00:00
event_queue: vec![],
2021-11-01 23:51:45 +00:00
debug_enabled: Cell::new(false),
bus: Rc::new(RefCell::new(Bus::new())),
2021-10-09 18:00:32 +00:00
interrupt_controller: RefCell::new(InterruptController::new()),
}
}
pub fn get_bus(&self) -> RefMut<'_, Bus> {
self.bus.borrow_mut()
}
2021-10-09 18:00:32 +00:00
pub fn get_interrupt_controller(&self) -> RefMut<'_, InterruptController> {
self.interrupt_controller.borrow_mut()
}
pub fn add_addressable_device(&mut self, addr: Address, device: TransmutableBox) -> Result<(), Error> {
let length = device.borrow_mut().as_addressable().unwrap().len();
self.bus.borrow_mut().insert(addr, length, device.clone());
2021-10-30 03:06:15 +00:00
self.try_queue_device(device.clone());
2021-11-01 23:51:45 +00:00
self.devices.insert(format!("ram{:x}", addr), device);
Ok(())
}
2021-11-01 23:51:45 +00:00
pub fn add_interruptable_device(&mut self, name: &str, device: TransmutableBox) -> Result<(), Error> {
self.interrupt_controller.borrow_mut().set_target(device.clone())?;
2021-10-30 03:06:15 +00:00
self.try_queue_device(device.clone());
2021-11-01 23:51:45 +00:00
self.devices.insert(name.to_string(), device);
Ok(())
}
2021-11-01 23:51:45 +00:00
pub fn enable_debugging(&self) {
self.debug_enabled.set(true);
}
pub fn disable_debugging(&self) {
self.debug_enabled.set(false);
}
pub fn step(&mut self) -> Result<(), Error> {
2021-10-24 05:22:02 +00:00
let mut event_device = self.event_queue.pop().unwrap();
self.clock = event_device.next_clock;
event_device.next_clock = self.clock + event_device.device.borrow_mut().as_steppable().unwrap().step(&self)?;
2021-10-30 03:06:15 +00:00
self.queue_device(event_device);
2021-10-24 05:22:02 +00:00
Ok(())
}
pub fn run_for(&mut self, clocks: Clock) -> Result<(), Error> {
let target = self.clock + clocks;
while self.clock < target {
2021-11-01 23:51:45 +00:00
if self.debug_enabled.get() && self.event_queue[self.event_queue.len() - 1].device.borrow_mut().as_debuggable().is_some() {
Debugger::run_debugger(&self, self.event_queue[self.event_queue.len() - 1].device.clone()).unwrap();
}
2021-10-24 05:22:02 +00:00
match self.step() {
Ok(()) => { }
Err(err) => {
self.exit_error();
println!("{:?}", err);
return Err(err);
},
}
}
Ok(())
}
2021-10-24 05:22:02 +00:00
pub fn run_loop(&mut self) {
self.run_for(u64::MAX);
}
pub fn exit_error(&mut self) {
2021-11-01 23:51:45 +00:00
for (_, dev) in self.devices.iter() {
match dev.borrow_mut().as_steppable() {
Some(dev) => dev.on_error(&self),
None => { },
}
}
}
2021-10-15 04:16:31 +00:00
2021-10-30 03:06:15 +00:00
fn try_queue_device(&mut self, device: TransmutableBox) {
if device.borrow_mut().as_steppable().is_some() {
2021-11-01 23:51:45 +00:00
self.queue_device(DeviceStep::new(device));
2021-10-30 03:06:15 +00:00
}
}
2021-11-01 23:51:45 +00:00
fn queue_device(&mut self, device_step: DeviceStep) {
2021-10-30 03:06:15 +00:00
for i in (0..self.event_queue.len()).rev() {
2021-11-01 23:51:45 +00:00
if self.event_queue[i].next_clock > device_step.next_clock {
self.event_queue.insert(i + 1, device_step);
2021-10-30 03:06:15 +00:00
return;
}
}
2021-11-01 23:51:45 +00:00
self.event_queue.insert(0, device_step);
2021-10-30 03:06:15 +00:00
}
2021-10-24 05:22:02 +00:00
}
2021-10-19 18:33:51 +00:00
2021-10-24 05:22:02 +00:00
2021-11-01 23:51:45 +00:00
pub struct DeviceStep {
2021-10-24 05:22:02 +00:00
pub next_clock: Clock,
pub device: TransmutableBox,
}
2021-11-01 23:51:45 +00:00
impl DeviceStep {
2021-10-24 05:22:02 +00:00
pub fn new(device: TransmutableBox) -> Self {
Self {
next_clock: 0,
device,
2021-10-19 18:33:51 +00:00
}
}
2021-10-24 05:22:02 +00:00
}