diff --git a/emulator/core/src/devices.rs b/emulator/core/src/devices.rs index 018d1b4..28fb24c 100644 --- a/emulator/core/src/devices.rs +++ b/emulator/core/src/devices.rs @@ -175,11 +175,11 @@ pub trait Inspectable { pub type DeviceId = u32; -pub trait Resource: Any + 'static + Transmutable {} +pub trait DynDevice: Any + 'static + Transmutable {} -pub type Device = Rc>; +pub type Device = Rc>; -impl Resource for T where T: Transmutable + 'static {} +impl DynDevice for T where T: Transmutable + 'static {} pub trait Transmutable { #[inline] @@ -209,12 +209,12 @@ pub trait Transmutable { } // Taken from deno_core -fn is(field: &dyn Resource) -> bool { +fn is(field: &dyn DynDevice) -> bool { field.type_id() == TypeId::of::() } // Taken from deno_core -pub fn downcast_rc_refc<'a, T: Resource>(field: &'a Device) -> Option<&'a Rc>> { +pub fn downcast_rc_refc<'a, T: DynDevice>(field: &'a Device) -> Option<&'a Rc>> { if is::(field.borrow().deref()) { let ptr = field as *const Rc> as *const Rc>; #[allow(clippy::undocumented_unsafe_blocks)] @@ -232,54 +232,12 @@ pub fn wrap_transmutable(value: T) -> TransmutableBox static NEXT_ID: AtomicU32 = AtomicU32::new(1); -pub fn get_next_id() -> u32 { +pub fn get_next_device_id() -> u32 { let next = NEXT_ID.load(Ordering::Acquire); NEXT_ID.store(next + 1, Ordering::Release); next } -// #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -// pub struct DeviceId(usize); - -// impl DeviceId { -// pub fn new() -> Self { -// let next = NEXT_ID.load(Ordering::Acquire); -// NEXT_ID.store(next + 1, Ordering::Release); -// Self(next) -// } -// } - -// impl Default for DeviceId { -// fn default() -> Self { -// Self::new() -// } -// } - -// #[derive(Clone)] -// pub struct Device(DeviceId, TransmutableBox); - -// impl Device { -// pub fn new(value: T) -> Self -// where -// T: Transmutable + 'static, -// { -// Self(DeviceId::new(), wrap_transmutable(value)) -// } - -// pub fn id(&self) -> DeviceId { -// self.0 -// } - -// pub fn borrow_mut(&self) -> RefMut<'_, Box> { -// self.1.borrow_mut() -// } - -// pub fn try_borrow_mut(&self) -> Result>, BorrowMutError> { -// self.1.try_borrow_mut() -// } -// } - - /* #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct DeviceId(usize); diff --git a/emulator/core/src/lib.rs b/emulator/core/src/lib.rs index 0f4e6ae..9db26dc 100644 --- a/emulator/core/src/lib.rs +++ b/emulator/core/src/lib.rs @@ -7,7 +7,7 @@ mod memory; mod system; pub use crate::devices::{ - Address, Addressable, Steppable, Interruptable, Debuggable, Inspectable, Transmutable, TransmutableBox, Resource + Address, Addressable, Steppable, Interruptable, Debuggable, Inspectable, Transmutable, TransmutableBox, DynDevice }; pub use crate::devices::{ read_beu16, read_beu32, read_leu16, read_leu32, write_beu16, write_beu32, write_leu16, write_leu32, wrap_transmutable, diff --git a/emulator/core/src/system.rs b/emulator/core/src/system.rs index f4f2070..e2ea657 100644 --- a/emulator/core/src/system.rs +++ b/emulator/core/src/system.rs @@ -3,7 +3,7 @@ use std::cell::{RefCell, RefMut}; use std::collections::{BTreeMap, HashMap}; use femtos::{Instant, Duration}; -use crate::devices::{downcast_rc_refc, get_next_id, Device, DeviceId, Resource}; +use crate::devices::{downcast_rc_refc, get_next_device_id, Device, DeviceId, DynDevice}; use crate::{Address, Bus, Error, InterruptController}; @@ -47,6 +47,12 @@ pub struct DeviceSettings { impl Default for DeviceSettings { fn default() -> Self { + Self::new() + } +} + +impl DeviceSettings { + fn new() -> Self { Self { name: None, address: None, @@ -54,6 +60,26 @@ impl Default for DeviceSettings { queue: false, } } + + fn with_address(&mut self, addr: Address) -> &mut Self { + self.address = Some(addr); + self + } + + fn with_name(&mut self, name: String) -> &mut Self { + self.name = Some(name); + self + } + + fn debuggable(&mut self, debuggable: bool) -> &mut Self { + self.debuggable = debuggable; + self + } + + fn queue(&mut self, queue: bool) -> &mut Self { + self.queue = queue; + self + } } impl System { @@ -65,7 +91,11 @@ impl System { self.interrupt_controller.borrow_mut() } - pub fn get_device(&self, device: DeviceId) -> Result>, Error> { + pub fn get_id_from_name(&self, name: &str) -> Option { + self.id_to_name.iter().find_map(|(key, &ref val)| if val == name { Some(*key)} else { None }) + } + + pub fn get_device(&self, device: DeviceId) -> Result>, Error> { self.devices .get(&device) .and_then(|rc| downcast_rc_refc::(rc)) @@ -73,10 +103,9 @@ impl System { .ok_or_else(|| Error::new(format!("system: bad device id {}", device))) } - pub fn get_device_by_name(&self, name: &str) -> Result>, Error> { - let id = self.id_to_name.iter().find_map(|(key, &ref val)| if val == name { Some(key)} else { None }); - if let Some(id) = id { - self.get_device(*id) + pub fn get_device_by_name(&self, name: &str) -> Result>, Error> { + if let Some(id) = self.get_id_from_name(name) { + self.get_device(id) } else { Err(Error::new(format!("system: could not find device {}", name))) } @@ -90,25 +119,24 @@ impl System { } pub fn get_dyn_device_by_name(&self, name: &str) -> Result { - let id = self.id_to_name.iter().find_map(|(key, &ref val)| if val == name { Some(key)} else { None }); - if let Some(id) = id { - self.get_dyn_device(*id) + if let Some(id) = self.get_id_from_name(name) { + self.get_dyn_device(id) } else { Err(Error::new(format!("system: could not find device {}", name))) } } - pub fn add_device(&mut self, device: T, settings: DeviceSettings) -> Result { + pub fn add_device(&mut self, device: T, settings: DeviceSettings) -> Result { self.add_device_rc_ref(Rc::new(RefCell::new(device)), settings) } - pub fn add_device_rc_ref(&mut self, device: Rc>, settings: DeviceSettings) -> Result { + pub fn add_device_rc_ref(&mut self, device: Rc>, settings: DeviceSettings) -> Result { let device = device as Device; self.add_device_rc_dyn(device, settings) } pub fn add_device_rc_dyn(&mut self, device: Device, settings: DeviceSettings) -> Result { - let id = get_next_id(); + let id = get_next_device_id(); self.id_to_name.insert(id, settings.name.unwrap_or_default()); self.devices.insert(id, device.clone()); @@ -125,7 +153,7 @@ impl System { Ok(id) } - pub fn add_named_device(&mut self, name: &str, device: T) -> Result { + pub fn add_named_device(&mut self, name: &str, device: T) -> Result { self.add_device(device, DeviceSettings { name: Some(name.to_owned()), queue: true, @@ -133,7 +161,7 @@ impl System { }) } - pub fn add_addressable_device(&mut self, addr: Address, device: T) -> Result { + pub fn add_addressable_device(&mut self, addr: Address, device: T) -> Result { self.add_device(device, DeviceSettings { name: Some(format!("mem{:x}", addr)), address: Some(addr), @@ -142,7 +170,7 @@ impl System { }) } - pub fn add_peripheral(&mut self, name: &str, addr: Address, device: T) -> Result { + pub fn add_peripheral(&mut self, name: &str, addr: Address, device: T) -> Result { self.add_device(device, DeviceSettings { name: Some(name.to_owned()), address: Some(addr), @@ -151,7 +179,7 @@ impl System { }) } - pub fn add_interruptable_device(&mut self, name: &str, device: T) -> Result { + pub fn add_interruptable_device(&mut self, name: &str, device: T) -> Result { self.add_device(device, DeviceSettings { name: Some(name.to_owned()), queue: true, @@ -194,7 +222,7 @@ impl System { loop { self.step()?; - if self.get_next_event_device() == device { + if self.get_next_event_device_id() == device { break; } } @@ -206,7 +234,7 @@ impl System { loop { self.step()?; - if self.get_dyn_device(self.get_next_event_device()).unwrap().borrow_mut().as_debuggable().is_some() { + if self.get_dyn_device(self.get_next_event_device_id()).unwrap().borrow_mut().as_debuggable().is_some() { break; } } @@ -244,7 +272,7 @@ impl System { } } - pub fn get_next_event_device(&self) -> DeviceId { + pub fn get_next_event_device_id(&self) -> DeviceId { self.event_queue[self.event_queue.len() - 1].device }