use core::num::NonZeroU16;
use core::fmt::{self, Debug};
use core::any::TypeId;
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
#[cfg(feature = "snapshot")]
use serde::{Serialize, Deserialize};
mod dynbus;
use crate::clock::VFrameTs;
pub use dynbus::*;
impl<T: 'static> dyn NamedBusDevice<T> {
#[inline]
pub fn downcast<D: 'static>(self: Box<Self>) -> Result<Box<D>, Box<dyn NamedBusDevice<T>>>
where D: NamedBusDevice<T>
{
if self.is::<D>() {
unsafe {
let raw: *mut dyn NamedBusDevice<T> = Box::into_raw(self);
Ok(Box::from_raw(raw as *mut D))
}
} else {
Err(self)
}
}
}
impl<T: 'static> dyn NamedBusDevice<T> + 'static {
#[inline]
pub fn is<D: NamedBusDevice<T> + 'static>(&self) -> bool {
TypeId::of::<D>() == self.type_id()
}
pub fn downcast_ref<D: NamedBusDevice<T> + 'static>(&self) -> Option<&D> {
if self.is::<D>() {
unsafe {
Some(&*(self as *const dyn NamedBusDevice<T> as *const D))
}
} else {
None
}
}
pub fn downcast_mut<D: NamedBusDevice<T> + 'static>(&mut self) -> Option<&mut D> {
if self.is::<D>() {
unsafe {
Some(&mut *(self as *mut dyn NamedBusDevice<T> as *mut D))
}
} else {
None
}
}
}
pub trait BusDevice: Debug {
type Timestamp: Sized;
type NextDevice: BusDevice<Timestamp=Self::Timestamp>;
fn next_device_mut(&mut self) -> &mut Self::NextDevice;
fn next_device_ref(&self) -> &Self::NextDevice;
fn into_next_device(self) -> Self::NextDevice;
#[inline(always)]
fn reset(&mut self, timestamp: Self::Timestamp) {
self.next_device_mut().reset(timestamp)
}
#[inline(always)]
fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
self.next_device_mut().update_timestamp(timestamp)
}
#[inline(always)]
fn next_frame(&mut self, eof_timestamp: Self::Timestamp) {
self.next_device_mut().next_frame(eof_timestamp)
}
#[inline(always)]
fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
self.next_device_mut().read_io(port, timestamp)
}
#[inline(always)]
fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
self.next_device_mut().write_io(port, data, timestamp)
}
fn type_id(&self) -> TypeId where Self: 'static {
TypeId::of::<Self>()
}
}
impl<D: BusDevice> BusDevice for Box<D> {
type Timestamp = D::Timestamp;
type NextDevice = D::NextDevice;
#[inline(always)]
fn next_device_mut(&mut self) -> &mut Self::NextDevice {
(**self).next_device_mut()
}
#[inline(always)]
fn next_device_ref(&self) -> &Self::NextDevice {
(**self).next_device_ref()
}
#[inline]
fn into_next_device(self) -> Self::NextDevice {
(*self).into_next_device()
}
#[inline]
fn reset(&mut self, timestamp: Self::Timestamp) {
(**self).reset(timestamp)
}
#[inline]
fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
(**self).update_timestamp(timestamp)
}
#[inline]
fn next_frame(&mut self, eof_timestamp: Self::Timestamp) {
(**self).next_frame(eof_timestamp)
}
#[inline]
fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
(**self).read_io(port, timestamp)
}
#[inline]
fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
(**self).write_io(port, data, timestamp)
}
}
pub trait PortAddress: Debug {
const ADDRESS_MASK: u16;
const ADDRESS_BITS: u16;
#[inline]
fn match_port(address: u16) -> bool {
address & Self::ADDRESS_MASK == Self::ADDRESS_BITS & Self::ADDRESS_MASK
}
}
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
pub struct NullDevice<T>(PhantomData<T>);
pub type VFNullDevice<V> = NullDevice<VFrameTs<V>>;
impl<T> Default for NullDevice<T> {
#[inline(always)]
fn default() -> Self {
NullDevice(PhantomData)
}
}
impl<T> BusDevice for NullDevice<T> {
type Timestamp = T;
type NextDevice = Self;
#[inline(always)]
fn next_device_mut(&mut self) -> &mut Self::NextDevice {
self
}
#[inline(always)]
fn next_device_ref(&self) -> &Self::NextDevice {
self
}
#[inline(always)]
fn into_next_device(self) -> Self::NextDevice {
self
}
#[inline(always)]
fn reset(&mut self, _timestamp: Self::Timestamp) {}
#[inline(always)]
fn update_timestamp(&mut self, _timestamp: Self::Timestamp) {}
#[inline(always)]
fn next_frame(&mut self, _timestamp: Self::Timestamp) {}
#[inline(always)]
fn read_io(&mut self, _port: u16, _timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
None
}
#[inline(always)]
fn write_io(&mut self, _port: u16, _data: u8, _timestamp: Self::Timestamp) -> Option<u16> {
None
}
}
impl<T> fmt::Debug for NullDevice<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NullDevice").finish()
}
}
impl<T> fmt::Display for NullDevice<T> {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
Ok(())
}
}
#[derive(Clone, Default, Debug)]
#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "snapshot", serde(rename_all = "camelCase"))]
pub struct OptionalBusDevice<D, N> {
#[cfg_attr(feature = "snapshot", serde(default))]
pub device: Option<D>,
#[cfg_attr(feature = "snapshot", serde(default))]
pub next_device: N
}
impl<D, N> OptionalBusDevice<D, N>
where D: BusDevice, N: BusDevice
{
pub fn new(device: Option<D>, next_device: N) -> Self {
OptionalBusDevice { device, next_device }
}
}
impl<D, N> Deref for OptionalBusDevice<D, N> {
type Target = Option<D>;
fn deref(&self) -> &Self::Target {
&self.device
}
}
impl<D, N> DerefMut for OptionalBusDevice<D, N> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.device
}
}
impl<D, N> BusDevice for OptionalBusDevice<D, N>
where D: BusDevice,
N: BusDevice<Timestamp=D::Timestamp>,
D::Timestamp: Copy
{
type Timestamp = D::Timestamp;
type NextDevice = N;
#[inline]
fn next_device_mut(&mut self) -> &mut Self::NextDevice {
&mut self.next_device
}
#[inline]
fn next_device_ref(&self) -> &Self::NextDevice {
&self.next_device
}
#[inline]
fn into_next_device(self) -> Self::NextDevice {
self.next_device
}
#[inline]
fn reset(&mut self, timestamp: Self::Timestamp) {
if let Some(device) = &mut self.device {
device.reset(timestamp);
}
self.next_device.reset(timestamp);
}
#[inline]
fn update_timestamp(&mut self, timestamp: Self::Timestamp) {
if let Some(device) = &mut self.device {
device.update_timestamp(timestamp);
}
self.next_device.update_timestamp(timestamp);
}
#[inline]
fn next_frame(&mut self, timestamp: Self::Timestamp) {
if let Some(device) = &mut self.device {
device.next_frame(timestamp);
}
self.next_device.next_frame(timestamp);
}
#[inline]
fn read_io(&mut self, port: u16, timestamp: Self::Timestamp) -> Option<(u8, Option<NonZeroU16>)> {
let dev_data = if let Some((data, ws)) = self.device
.as_mut()
.and_then(|dev| dev.read_io(port, timestamp)) {
if ws.is_some() {
return Some((data, ws))
}
Some(data)
}
else {
None
};
if let Some((bus_data, ws)) = self.next_device.read_io(port, timestamp) {
let data = bus_data & dev_data.unwrap_or(!0);
return Some((data, ws))
}
dev_data.map(|data| (data, None))
}
#[inline]
fn write_io(&mut self, port: u16, data: u8, timestamp: Self::Timestamp) -> Option<u16> {
if let Some(device) = &mut self.device {
if let Some(ws) = device.write_io(port, data, timestamp) {
return Some(ws)
}
}
self.next_device.write_io(port, data, timestamp)
}
}
impl<D, N> fmt::Display for OptionalBusDevice<D, N>
where D: fmt::Display
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(ref device) = self.device {
device.fmt(f)
}
else {
Ok(())
}
}
}