moa/emulator/core/src/system.rs

206 lines
6.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::debugger::Debugger;
use crate::signals::EdgeSignal;
use crate::error::{Error, ErrorType};
2021-10-09 18:00:32 +00:00
use crate::interrupts::InterruptController;
2021-11-23 19:45:11 +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>,
2021-11-23 19:45:11 +00:00
pub event_queue: Vec<NextStep>,
2021-11-01 23:51:45 +00:00
pub debug_enabled: Cell<bool>,
pub debugger: RefCell<Debugger>,
pub bus: Rc<RefCell<Bus>>,
2021-10-09 18:00:32 +00:00
pub interrupt_controller: RefCell<InterruptController>,
pub break_signal: Option<EdgeSignal>,
}
2023-03-06 04:19:49 +00:00
impl Default for System {
fn default() -> Self {
Self {
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),
2023-03-06 04:19:49 +00:00
debugger: RefCell::new(Debugger::default()),
2023-03-06 04:19:49 +00:00
bus: Rc::new(RefCell::new(Bus::default())),
interrupt_controller: RefCell::new(InterruptController::default()),
break_signal: None,
}
}
2023-03-06 04:19:49 +00:00
}
2023-03-06 04:19:49 +00:00
impl System {
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 get_device(&self, name: &str) -> Result<TransmutableBox, Error> {
self.devices.get(name).cloned().ok_or_else(|| Error::new(&format!("system: no device named {}", name)))
}
2021-11-13 19:39:20 +00:00
pub fn add_device(&mut self, name: &str, device: TransmutableBox) -> Result<(), Error> {
self.try_queue_device(device.clone());
self.devices.insert(name.to_string(), device);
Ok(())
}
pub fn add_addressable_device(&mut self, addr: Address, device: TransmutableBox) -> Result<(), Error> {
self.add_peripheral(&format!("mem{:x}", addr), addr, device)
}
pub fn add_peripheral(&mut self, name: &str, addr: Address, device: TransmutableBox) -> Result<(), Error> {
self.bus.borrow_mut().insert(addr, device.clone());
2021-10-30 03:06:15 +00:00
self.try_queue_device(device.clone());
self.devices.insert(name.to_string(), 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);
self.devices.get("cpu").map(|result| result.try_borrow_mut().map(|mut borrow| borrow.as_debuggable().map(|debug| debug.set_debugging(true))));
2021-11-04 20:32:51 +00:00
self.debugger.borrow_mut().breakpoint_occurred();
2021-11-01 23:51:45 +00:00
}
pub fn disable_debugging(&self) {
self.debug_enabled.set(false);
}
fn process_one_event(&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;
2023-03-06 04:19:49 +00:00
let result = match event_device.device.borrow_mut().as_steppable().unwrap().step(self) {
Ok(diff) => {
event_device.next_clock = self.clock + diff;
Ok(())
},
Err(err) => Err(err),
};
2021-10-30 03:06:15 +00:00
self.queue_device(event_device);
result
2021-10-24 05:22:02 +00:00
}
pub fn step(&mut self) -> Result<(), Error> {
self.check_debugger();
match self.process_one_event() {
Ok(()) => {
if self.get_bus().check_and_reset_watcher_modified() {
self.enable_debugging();
}
},
Err(err) if err.err == ErrorType::Breakpoint => {
println!("Breakpoint reached: {}", err.msg);
self.enable_debugging();
},
Err(err) => {
self.exit_error();
println!("{:?}", err);
return Err(err);
},
}
Ok(())
}
2021-11-23 19:45:11 +00:00
pub fn run_for(&mut self, elapsed: ClockElapsed) -> Result<(), Error> {
let target = self.clock + elapsed;
2021-10-24 05:22:02 +00:00
while self.clock < target {
self.step()?;
}
Ok(())
}
pub fn run_until_break(&mut self) -> Result<(), Error> {
let mut signal = match &self.break_signal {
Some(signal) => signal.clone(),
None => return Ok(()),
};
while !signal.get() {
self.step()?;
}
Ok(())
}
2021-10-24 05:22:02 +00:00
pub fn run_loop(&mut self) {
2021-11-13 19:39:20 +00:00
self.run_for(u64::MAX).unwrap();
2021-10-24 05:22:02 +00:00
}
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() {
2023-03-06 04:19:49 +00:00
Some(dev) => dev.on_error(self),
None => { },
}
}
}
2021-10-15 04:16:31 +00:00
fn check_debugger(&mut self) {
if self.debug_enabled.get() {
let top = self.event_queue[self.event_queue.len() - 1].device.clone();
if top.borrow_mut().as_debuggable().map(|debug| debug.debugging_enabled()).unwrap_or(false) {
2023-03-06 04:19:49 +00:00
if let Err(err) = self.debugger.borrow_mut().run_debugger(self, top.clone()) {
println!("Error: {:?}", err);
}
}
}
}
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-23 19:45:11 +00:00
self.queue_device(NextStep::new(device));
2021-10-30 03:06:15 +00:00
}
}
2021-11-23 19:45:11 +00:00
fn queue_device(&mut self, device_step: NextStep) {
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-23 19:45:11 +00:00
pub struct NextStep {
2021-10-24 05:22:02 +00:00
pub next_clock: Clock,
pub device: TransmutableBox,
}
2021-11-23 19:45:11 +00:00
impl NextStep {
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
}