Simplified event queue

This commit is contained in:
transistor 2021-10-29 20:06:15 -07:00
parent 250c0e83d2
commit c1ca666aa4
4 changed files with 28 additions and 41 deletions

View File

@ -67,8 +67,7 @@ impl M68kDecoder {
pub fn decode_at(&mut self, memory: &mut dyn Addressable, start: u32) -> Result<(), Error> {
self.init(start);
self.instruction = self.decode_one(memory)?;
Ok(())
self.instruction = self.decode_one(memory)
}
pub fn decode_one(&mut self, memory: &mut dyn Addressable) -> Result<Instruction, Error> {

View File

@ -88,7 +88,7 @@ impl M68k {
match self.cycle_one(system) {
Ok(()) => Ok(()),
//Err(Error { err: ErrorType::Processor, native, .. }) => {
// TODO temporary: we are passing illegal instructions upward in order to fix them
// TODO match arm conditional is temporary: illegal instructions generate a top level error in order to debug and fix issues with decode
Err(Error { err: ErrorType::Processor, native, .. }) if native != Exceptions::IllegalInstruction as u32 => {
self.exception(system, native as u8)?;
Ok(())

View File

@ -1,8 +1,7 @@
use std::rc::Rc;
use std::cmp::Ordering;
use std::cell::{RefCell, RefMut};
use std::collections::BinaryHeap;
use std::collections::HashMap;
use crate::error::Error;
use crate::memory::Bus;
@ -13,7 +12,7 @@ use crate::devices::{Clock, ClockElapsed, Address, TransmutableBox};
pub struct System {
pub clock: Clock,
pub devices: Vec<TransmutableBox>,
pub event_queue: BinaryHeap<EventDevice>,
pub event_queue: Vec<SteppableDevice>,
pub bus: Rc<RefCell<Bus>>,
pub interrupt_controller: RefCell<InterruptController>,
}
@ -23,7 +22,7 @@ impl System {
System {
clock: 0,
devices: vec![],
event_queue: BinaryHeap::new(),
event_queue: vec![],
bus: Rc::new(RefCell::new(Bus::new())),
interrupt_controller: RefCell::new(InterruptController::new()),
}
@ -40,31 +39,23 @@ impl System {
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());
self.insert_steppable_device(device.clone());
self.try_queue_device(device.clone());
self.devices.push(device);
Ok(())
}
pub fn add_interruptable_device(&mut self, device: TransmutableBox) -> Result<(), Error> {
self.interrupt_controller.borrow_mut().set_target(device.clone())?;
self.insert_steppable_device(device.clone());
self.try_queue_device(device.clone());
self.devices.push(device);
Ok(())
}
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(())
}
pub fn step(&mut self) -> Result<(), Error> {
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);
self.queue_device(event_device);
Ok(())
}
@ -106,15 +97,32 @@ impl System {
}
Ok(())
}
fn try_queue_device(&mut self, device: TransmutableBox) {
if device.borrow_mut().as_steppable().is_some() {
self.queue_device(SteppableDevice::new(device));
}
}
fn queue_device(&mut self, event_device: SteppableDevice) {
for i in (0..self.event_queue.len()).rev() {
if self.event_queue[i].next_clock > event_device.next_clock {
self.event_queue.insert(i + 1, event_device);
return;
}
}
self.event_queue.insert(0, event_device);
}
}
pub struct EventDevice {
pub struct SteppableDevice {
pub next_clock: Clock,
pub device: TransmutableBox,
}
impl EventDevice {
impl SteppableDevice {
pub fn new(device: TransmutableBox) -> Self {
Self {
next_clock: 0,
@ -123,24 +131,3 @@ impl EventDevice {
}
}
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
}
}

View File

@ -13,6 +13,7 @@
* modify the interrupt handling to make the interrupted device acknowledge the interrupt, probably via the interrupt controller somehow. It might need to be async
such that the cpu tells the int_controller it's acknowledged, and then the interrupting device can check the interrupt controller if it needs to see the ack.
The ym7101 could use the ack as the "off" signal, and perhaps use that for the vsync int bit
* there's potentially an issue with interrupts for m68k where it might not properly mask interrupts causing overlapping interrupts that cause problems (eventually executing RAM in Sonic)
* each device that can make a bus request should have a BusPort which is used to access the bus. Not sure how it'll be created or passed to the device, since