2021-10-06 23:14:56 +00:00
|
|
|
|
2021-10-27 04:32:25 +00:00
|
|
|
use std::rc::Rc;
|
2021-10-24 05:22:02 +00:00
|
|
|
use std::cmp::Ordering;
|
2021-10-06 23:14:56 +00:00
|
|
|
use std::cell::{RefCell, RefMut};
|
2021-10-24 05:22:02 +00:00
|
|
|
use std::collections::BinaryHeap;
|
2021-10-06 23:14:56 +00:00
|
|
|
|
|
|
|
use crate::error::Error;
|
2021-10-17 03:30:50 +00:00
|
|
|
use crate::memory::Bus;
|
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};
|
2021-10-06 23:14:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
pub struct System {
|
|
|
|
pub clock: Clock,
|
2021-10-17 17:39:43 +00:00
|
|
|
pub devices: Vec<TransmutableBox>,
|
2021-10-24 05:22:02 +00:00
|
|
|
pub event_queue: BinaryHeap<EventDevice>,
|
2021-10-27 04:32:25 +00:00
|
|
|
pub bus: Rc<RefCell<Bus>>,
|
2021-10-09 18:00:32 +00:00
|
|
|
pub interrupt_controller: RefCell<InterruptController>,
|
2021-10-06 23:14:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl System {
|
|
|
|
pub fn new() -> System {
|
|
|
|
System {
|
|
|
|
clock: 0,
|
2021-10-07 18:35:15 +00:00
|
|
|
devices: vec![],
|
2021-10-24 05:22:02 +00:00
|
|
|
event_queue: BinaryHeap::new(),
|
2021-10-27 04:32:25 +00:00
|
|
|
bus: Rc::new(RefCell::new(Bus::new())),
|
2021-10-09 18:00:32 +00:00
|
|
|
interrupt_controller: RefCell::new(InterruptController::new()),
|
2021-10-06 23:14:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-07 16:41:01 +00:00
|
|
|
pub fn get_bus(&self) -> RefMut<'_, Bus> {
|
|
|
|
self.bus.borrow_mut()
|
2021-10-06 23:14:56 +00:00
|
|
|
}
|
|
|
|
|
2021-10-09 18:00:32 +00:00
|
|
|
pub fn get_interrupt_controller(&self) -> RefMut<'_, InterruptController> {
|
|
|
|
self.interrupt_controller.borrow_mut()
|
|
|
|
}
|
|
|
|
|
2021-10-17 17:39:43 +00:00
|
|
|
pub fn add_addressable_device(&mut self, addr: Address, device: TransmutableBox) -> Result<(), Error> {
|
|
|
|
let length = device.borrow_mut().as_addressable().unwrap().len();
|
2021-10-07 16:41:01 +00:00
|
|
|
self.bus.borrow_mut().insert(addr, length, device.clone());
|
2021-10-24 05:22:02 +00:00
|
|
|
self.insert_steppable_device(device.clone());
|
2021-10-17 17:39:43 +00:00
|
|
|
self.devices.push(device);
|
2021-10-07 18:35:15 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-10-17 17:39:43 +00:00
|
|
|
pub fn add_interruptable_device(&mut self, device: TransmutableBox) -> Result<(), Error> {
|
2021-10-10 00:35:23 +00:00
|
|
|
self.interrupt_controller.borrow_mut().set_target(device.clone())?;
|
2021-10-24 05:22:02 +00:00
|
|
|
self.insert_steppable_device(device.clone());
|
2021-10-17 17:39:43 +00:00
|
|
|
self.devices.push(device);
|
2021-10-07 16:41:01 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2021-10-06 23:14:56 +00:00
|
|
|
|
2021-10-24 05:22:02 +00:00
|
|
|
fn insert_steppable_device(&mut self, device: TransmutableBox) -> Result<(), Error> {
|
|
|
|
if device.borrow_mut().as_steppable().is_some() {
|
|
|
|
let event_device = EventDevice::new(device);
|
|
|
|
self.event_queue.push(event_device);
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-10-06 23:14:56 +00:00
|
|
|
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)?;
|
|
|
|
self.event_queue.push(event_device);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run_for(&mut self, clocks: Clock) -> Result<(), Error> {
|
|
|
|
let target = self.clock + clocks;
|
|
|
|
|
|
|
|
while self.clock < target {
|
|
|
|
match self.step() {
|
|
|
|
Ok(()) => { }
|
|
|
|
Err(err) => {
|
|
|
|
self.exit_error();
|
|
|
|
println!("{:?}", err);
|
|
|
|
return Err(err);
|
|
|
|
},
|
2021-10-17 17:39:43 +00:00
|
|
|
}
|
2021-10-06 23:14:56 +00:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
2021-10-07 18:35:15 +00:00
|
|
|
|
2021-10-24 05:22:02 +00:00
|
|
|
pub fn run_loop(&mut self) {
|
|
|
|
self.run_for(u64::MAX);
|
|
|
|
}
|
|
|
|
|
2021-10-07 18:35:15 +00:00
|
|
|
pub fn exit_error(&mut self) {
|
|
|
|
for dev in &self.devices {
|
2021-10-17 17:39:43 +00:00
|
|
|
match dev.borrow_mut().as_steppable() {
|
|
|
|
Some(dev) => dev.on_error(&self),
|
|
|
|
None => { },
|
2021-10-07 18:35:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-15 04:16:31 +00:00
|
|
|
|
|
|
|
pub fn debug(&mut self) -> Result<(), Error> {
|
|
|
|
for dev in &self.devices {
|
2021-10-17 17:39:43 +00:00
|
|
|
match dev.borrow_mut().as_steppable() {
|
|
|
|
Some(dev) => dev.on_debug(),
|
|
|
|
None => { },
|
2021-10-15 04:16:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
2021-10-24 05:22:02 +00:00
|
|
|
}
|
2021-10-19 18:33:51 +00:00
|
|
|
|
2021-10-24 05:22:02 +00:00
|
|
|
|
|
|
|
pub struct EventDevice {
|
|
|
|
pub next_clock: Clock,
|
|
|
|
pub device: TransmutableBox,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EventDevice {
|
|
|
|
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
|
|
|
}
|
2021-10-22 04:55:27 +00:00
|
|
|
|
2021-10-24 05:22:02 +00:00
|
|
|
impl Ord for EventDevice {
|
|
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
|
|
// NOTE this is reversed so that an event with a lower clock will be higher
|
|
|
|
other.next_clock.cmp(&self.next_clock)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd for EventDevice {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for EventDevice {}
|
|
|
|
|
|
|
|
impl PartialEq for EventDevice {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
self.next_clock == other.next_clock
|
2021-10-22 04:55:27 +00:00
|
|
|
}
|
2021-10-07 18:35:15 +00:00
|
|
|
}
|
|
|
|
|