2021-10-09 06:11:52 +00:00
|
|
|
use std::rc::Rc;
|
2023-06-08 03:44:14 +00:00
|
|
|
use std::cell::{RefCell, RefMut, BorrowMutError};
|
|
|
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
2024-02-24 21:02:09 +00:00
|
|
|
use femtos::{Duration, Instant};
|
2021-10-09 06:11:52 +00:00
|
|
|
|
2024-02-24 21:02:09 +00:00
|
|
|
use crate::{Error, System};
|
2021-10-09 06:11:52 +00:00
|
|
|
|
|
|
|
|
2021-10-24 05:22:02 +00:00
|
|
|
/// A universal memory address used by the Addressable trait
|
2021-10-17 03:30:50 +00:00
|
|
|
pub type Address = u64;
|
2021-10-09 06:11:52 +00:00
|
|
|
|
2021-10-17 17:39:43 +00:00
|
|
|
|
2021-10-11 22:04:39 +00:00
|
|
|
/// A device that can change state over time. The `step()` method will be called
|
|
|
|
/// by the containing `System` when the system clock advances. If an error occurs
|
|
|
|
/// with any device, the `on_error()` method will be called to display any state
|
|
|
|
/// information that might be helpful for debugging.
|
2021-10-09 06:11:52 +00:00
|
|
|
pub trait Steppable {
|
2024-02-24 21:02:09 +00:00
|
|
|
fn step(&mut self, system: &System) -> Result<Duration, Error>;
|
2024-03-17 18:03:52 +00:00
|
|
|
fn on_error(&mut self, _system: &System) {}
|
2021-10-09 06:11:52 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 22:04:39 +00:00
|
|
|
/// A device that can receive an interrupt. The `interrupt_state_change()` method
|
|
|
|
/// will be called whenever an interrupt signal changes goes high or low.
|
2021-10-09 06:11:52 +00:00
|
|
|
pub trait Interruptable {
|
2021-10-30 05:02:29 +00:00
|
|
|
//fn interrupt_state_change(&mut self, state: bool, priority: u8, number: u8) -> Result<(), Error>;
|
2021-10-09 06:11:52 +00:00
|
|
|
}
|
|
|
|
|
2021-10-17 03:30:50 +00:00
|
|
|
/// A device that can be addressed to read data from or write data to the device.
|
|
|
|
pub trait Addressable {
|
2023-06-08 02:56:00 +00:00
|
|
|
fn size(&self) -> usize;
|
2024-02-24 21:02:09 +00:00
|
|
|
fn read(&mut self, clock: Instant, addr: Address, data: &mut [u8]) -> Result<(), Error>;
|
|
|
|
fn write(&mut self, clock: Instant, addr: Address, data: &[u8]) -> Result<(), Error>;
|
2021-10-17 03:30:50 +00:00
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2024-02-24 21:02:09 +00:00
|
|
|
fn read_u8(&mut self, clock: Instant, addr: Address) -> Result<u8, Error> {
|
2021-10-27 00:33:23 +00:00
|
|
|
let mut data = [0; 1];
|
2023-04-24 01:49:40 +00:00
|
|
|
self.read(clock, addr, &mut data)?;
|
2021-10-27 00:33:23 +00:00
|
|
|
Ok(data[0])
|
2021-10-17 03:30:50 +00:00
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2024-02-24 21:02:09 +00:00
|
|
|
fn read_beu16(&mut self, clock: Instant, addr: Address) -> Result<u16, Error> {
|
2021-10-27 00:33:23 +00:00
|
|
|
let mut data = [0; 2];
|
2023-04-24 01:49:40 +00:00
|
|
|
self.read(clock, addr, &mut data)?;
|
2021-10-27 00:33:23 +00:00
|
|
|
Ok(read_beu16(&data))
|
2021-10-17 03:30:50 +00:00
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2024-02-24 21:02:09 +00:00
|
|
|
fn read_leu16(&mut self, clock: Instant, addr: Address) -> Result<u16, Error> {
|
2021-11-03 03:33:27 +00:00
|
|
|
let mut data = [0; 2];
|
2023-04-24 01:49:40 +00:00
|
|
|
self.read(clock, addr, &mut data)?;
|
2021-11-03 03:33:27 +00:00
|
|
|
Ok(read_leu16(&data))
|
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2024-02-24 21:02:09 +00:00
|
|
|
fn read_beu32(&mut self, clock: Instant, addr: Address) -> Result<u32, Error> {
|
2021-10-27 00:33:23 +00:00
|
|
|
let mut data = [0; 4];
|
2023-04-24 01:49:40 +00:00
|
|
|
self.read(clock, addr, &mut data)?;
|
2021-10-27 00:33:23 +00:00
|
|
|
Ok(read_beu32(&data))
|
2021-10-17 03:30:50 +00:00
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2024-02-24 21:02:09 +00:00
|
|
|
fn read_leu32(&mut self, clock: Instant, addr: Address) -> Result<u32, Error> {
|
2021-11-03 03:33:27 +00:00
|
|
|
let mut data = [0; 4];
|
2023-04-24 01:49:40 +00:00
|
|
|
self.read(clock, addr, &mut data)?;
|
2021-11-03 03:33:27 +00:00
|
|
|
Ok(read_leu32(&data))
|
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2024-02-24 21:02:09 +00:00
|
|
|
fn write_u8(&mut self, clock: Instant, addr: Address, value: u8) -> Result<(), Error> {
|
2021-10-17 03:30:50 +00:00
|
|
|
let data = [value];
|
2023-04-24 01:49:40 +00:00
|
|
|
self.write(clock, addr, &data)
|
2021-10-17 03:30:50 +00:00
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2024-02-24 21:02:09 +00:00
|
|
|
fn write_beu16(&mut self, clock: Instant, addr: Address, value: u16) -> Result<(), Error> {
|
2021-11-03 03:33:27 +00:00
|
|
|
let mut data = [0; 2];
|
|
|
|
write_beu16(&mut data, value);
|
2023-04-24 01:49:40 +00:00
|
|
|
self.write(clock, addr, &data)
|
2021-11-03 03:33:27 +00:00
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2024-02-24 21:02:09 +00:00
|
|
|
fn write_leu16(&mut self, clock: Instant, addr: Address, value: u16) -> Result<(), Error> {
|
2021-11-03 03:33:27 +00:00
|
|
|
let mut data = [0; 2];
|
|
|
|
write_leu16(&mut data, value);
|
2023-04-24 01:49:40 +00:00
|
|
|
self.write(clock, addr, &data)
|
2021-10-17 03:30:50 +00:00
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2024-02-24 21:02:09 +00:00
|
|
|
fn write_beu32(&mut self, clock: Instant, addr: Address, value: u32) -> Result<(), Error> {
|
2021-11-03 03:33:27 +00:00
|
|
|
let mut data = [0; 4];
|
|
|
|
write_beu32(&mut data, value);
|
2023-04-24 01:49:40 +00:00
|
|
|
self.write(clock, addr, &data)
|
2021-11-03 03:33:27 +00:00
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2024-02-24 21:02:09 +00:00
|
|
|
fn write_leu32(&mut self, clock: Instant, addr: Address, value: u32) -> Result<(), Error> {
|
2021-11-03 03:33:27 +00:00
|
|
|
let mut data = [0; 4];
|
|
|
|
write_leu32(&mut data, value);
|
2023-04-24 01:49:40 +00:00
|
|
|
self.write(clock, addr, &data)
|
2021-10-17 03:30:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2021-10-17 03:30:50 +00:00
|
|
|
pub fn read_beu16(data: &[u8]) -> u16 {
|
2024-03-17 18:03:52 +00:00
|
|
|
(data[0] as u16) << 8 | (data[1] as u16)
|
2021-10-17 03:30:50 +00:00
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2021-11-03 03:33:27 +00:00
|
|
|
pub fn read_leu16(data: &[u8]) -> u16 {
|
2024-03-17 18:03:52 +00:00
|
|
|
(data[1] as u16) << 8 | (data[0] as u16)
|
2021-11-03 03:33:27 +00:00
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2021-10-17 03:30:50 +00:00
|
|
|
pub fn read_beu32(data: &[u8]) -> u32 {
|
2024-03-17 18:03:52 +00:00
|
|
|
(data[0] as u32) << 24 | (data[1] as u32) << 16 | (data[2] as u32) << 8 | (data[3] as u32)
|
2021-10-17 03:30:50 +00:00
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2021-11-03 03:33:27 +00:00
|
|
|
pub fn read_leu32(data: &[u8]) -> u32 {
|
2024-03-17 18:03:52 +00:00
|
|
|
(data[3] as u32) << 24 | (data[2] as u32) << 16 | (data[1] as u32) << 8 | (data[0] as u32)
|
2021-11-03 03:33:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2021-11-03 03:33:27 +00:00
|
|
|
pub fn write_beu16(data: &mut [u8], value: u16) -> &mut [u8] {
|
|
|
|
data[0] = (value >> 8) as u8;
|
|
|
|
data[1] = value as u8;
|
|
|
|
data
|
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2021-11-03 03:33:27 +00:00
|
|
|
pub fn write_leu16(data: &mut [u8], value: u16) -> &mut [u8] {
|
|
|
|
data[0] = value as u8;
|
|
|
|
data[1] = (value >> 8) as u8;
|
|
|
|
data
|
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2021-11-03 03:33:27 +00:00
|
|
|
pub fn write_beu32(data: &mut [u8], value: u32) -> &mut [u8] {
|
|
|
|
data[0] = (value >> 24) as u8;
|
|
|
|
data[1] = (value >> 16) as u8;
|
|
|
|
data[2] = (value >> 8) as u8;
|
|
|
|
data[3] = value as u8;
|
|
|
|
data
|
2021-10-17 03:30:50 +00:00
|
|
|
}
|
|
|
|
|
2023-06-08 04:08:28 +00:00
|
|
|
#[inline]
|
2021-11-03 03:33:27 +00:00
|
|
|
pub fn write_leu32(data: &mut [u8], value: u32) -> &mut [u8] {
|
|
|
|
data[0] = value as u8;
|
|
|
|
data[1] = (value >> 8) as u8;
|
|
|
|
data[2] = (value >> 16) as u8;
|
|
|
|
data[3] = (value >> 24) as u8;
|
|
|
|
data
|
2021-10-17 03:30:50 +00:00
|
|
|
}
|
|
|
|
|
2021-10-26 19:17:59 +00:00
|
|
|
|
2021-11-29 19:11:32 +00:00
|
|
|
/// A device (cpu) that can debugged using the built-in debugger
|
|
|
|
pub trait Debuggable {
|
|
|
|
fn add_breakpoint(&mut self, addr: Address);
|
|
|
|
fn remove_breakpoint(&mut self, addr: Address);
|
|
|
|
|
|
|
|
fn print_current_step(&mut self, system: &System) -> Result<(), Error>;
|
2024-03-16 20:15:34 +00:00
|
|
|
fn print_disassembly(&mut self, system: &System, addr: Address, count: usize);
|
2023-06-10 22:28:21 +00:00
|
|
|
fn run_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error>;
|
2021-11-29 19:11:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// A device (peripheral) that can inspected using the built-in debugger
|
|
|
|
pub trait Inspectable {
|
|
|
|
fn inspect(&mut self, system: &System, args: &[&str]) -> Result<(), Error>;
|
|
|
|
}
|
|
|
|
|
2024-04-07 17:38:41 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
|
|
pub enum Signal {
|
|
|
|
Reset,
|
|
|
|
BusRequest,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait Signalable {
|
|
|
|
fn set_signal(&mut self, signal: Signal, flag: bool) -> Result<(), Error>;
|
|
|
|
fn signal(&mut self, signal: Signal) -> Option<bool>;
|
|
|
|
}
|
2021-11-29 19:11:32 +00:00
|
|
|
|
2021-10-17 17:39:43 +00:00
|
|
|
pub trait Transmutable {
|
2023-06-08 03:44:14 +00:00
|
|
|
#[inline]
|
2021-10-17 17:39:43 +00:00
|
|
|
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2023-06-08 03:44:14 +00:00
|
|
|
#[inline]
|
2021-10-17 17:39:43 +00:00
|
|
|
fn as_addressable(&mut self) -> Option<&mut dyn Addressable> {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2023-06-08 03:44:14 +00:00
|
|
|
#[inline]
|
2021-10-17 17:39:43 +00:00
|
|
|
fn as_interruptable(&mut self) -> Option<&mut dyn Interruptable> {
|
|
|
|
None
|
|
|
|
}
|
2021-10-26 19:17:59 +00:00
|
|
|
|
2023-06-08 03:44:14 +00:00
|
|
|
#[inline]
|
2021-10-26 19:17:59 +00:00
|
|
|
fn as_debuggable(&mut self) -> Option<&mut dyn Debuggable> {
|
|
|
|
None
|
|
|
|
}
|
2021-11-29 19:11:32 +00:00
|
|
|
|
2023-06-08 03:44:14 +00:00
|
|
|
#[inline]
|
2021-11-29 19:11:32 +00:00
|
|
|
fn as_inspectable(&mut self) -> Option<&mut dyn Inspectable> {
|
|
|
|
None
|
|
|
|
}
|
2024-04-07 17:38:41 +00:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn as_signalable(&mut self) -> Option<&mut dyn Signalable> {
|
|
|
|
None
|
|
|
|
}
|
2021-10-17 17:39:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub type TransmutableBox = Rc<RefCell<Box<dyn Transmutable>>>;
|
|
|
|
|
|
|
|
pub fn wrap_transmutable<T: Transmutable + 'static>(value: T) -> TransmutableBox {
|
|
|
|
Rc::new(RefCell::new(Box::new(value)))
|
|
|
|
}
|
|
|
|
|
2023-06-08 03:44:14 +00:00
|
|
|
static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
|
|
|
|
|
2023-06-10 22:28:21 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
2023-06-08 03:44:14 +00:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
}
|
2023-04-23 22:46:47 +00:00
|
|
|
|
|
|
|
#[derive(Clone)]
|
2023-06-08 03:44:14 +00:00
|
|
|
pub struct Device(DeviceId, TransmutableBox);
|
2023-04-23 22:46:47 +00:00
|
|
|
|
|
|
|
impl Device {
|
2023-06-08 03:44:14 +00:00
|
|
|
pub fn new<T>(value: T) -> Self
|
|
|
|
where
|
2024-03-17 18:03:52 +00:00
|
|
|
T: Transmutable + 'static,
|
2023-06-08 03:44:14 +00:00
|
|
|
{
|
|
|
|
Self(DeviceId::new(), wrap_transmutable(value))
|
|
|
|
}
|
|
|
|
|
2023-06-10 22:28:21 +00:00
|
|
|
pub fn id(&self) -> DeviceId {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
|
2023-06-08 03:44:14 +00:00
|
|
|
pub fn borrow_mut(&self) -> RefMut<'_, Box<dyn Transmutable>> {
|
|
|
|
self.1.borrow_mut()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn try_borrow_mut(&self) -> Result<RefMut<'_, Box<dyn Transmutable>>, BorrowMutError> {
|
|
|
|
self.1.try_borrow_mut()
|
|
|
|
}
|
2023-04-23 22:46:47 +00:00
|
|
|
}
|
|
|
|
|
2023-04-24 02:52:19 +00:00
|
|
|
|
2023-05-10 04:50:42 +00:00
|
|
|
/*
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
|
|
pub struct DeviceId(usize);
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
|
|
pub enum Interrupt {
|
|
|
|
Number(usize),
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum InterruptPriority {
|
|
|
|
NonMaskable,
|
|
|
|
Number(usize),
|
|
|
|
}
|
|
|
|
|
|
|
|
struct InterruptPort {
|
|
|
|
id: usize,
|
|
|
|
controller: TransmutableBox,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl InterruptPort {
|
|
|
|
fn check_pending(&self) -> Option<Interrupt> {
|
|
|
|
self.controller.borrow_mut().as_interrupt_controller().check_pending(self.id)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn acknowledge(&self, interrupt: Interrupt) -> Result<(), Error> {
|
|
|
|
self.controller.borrow_mut().as_interrupt_controller().acknowledge(self.id, interrupt)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//pub trait InterruptPort {
|
|
|
|
// fn check_pending(&mut self, id: DeviceId) -> Option<Interrupt>;
|
|
|
|
// fn acknowledge(&mut self, id: DeviceId, interrupt: Interrupt) -> Result<(), Error>;
|
|
|
|
//}
|
|
|
|
|
|
|
|
//pub trait Interrupter {
|
|
|
|
// fn trigger(&mut self, id: DeviceId, interrupt: Interrupt) -> Result<(), Error>;
|
|
|
|
//}
|
|
|
|
|
|
|
|
struct Interrupter {
|
|
|
|
input_id: usize,
|
|
|
|
interrupt: Interrupt,
|
|
|
|
controller: Rc<RefCell<TransmutableBox>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait InterruptController {
|
|
|
|
fn connect(&mut self, priority: InterruptPriority) -> Result<InterruptPort, Error>;
|
|
|
|
fn check_pending(&mut self, id: usize) -> Option<Interrupt>;
|
|
|
|
fn acknowledge(&mut self, id: usize, interrupt: Interrupt) -> Result<(), Error>;
|
|
|
|
}
|
|
|
|
*/
|