2021-09-28 23:09:38 +00:00
|
|
|
|
|
|
|
use std::fs;
|
|
|
|
|
|
|
|
use crate::error::Error;
|
2021-10-09 06:11:52 +00:00
|
|
|
use crate::system::System;
|
|
|
|
use crate::devices::{Clock, Steppable, AddressableDeviceBox};
|
2021-09-28 23:09:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
pub type Address = u64;
|
|
|
|
|
2021-10-11 22:04:39 +00:00
|
|
|
/// A device that can be addressed to read data from or write data to the device.
|
2021-09-30 06:21:11 +00:00
|
|
|
pub trait Addressable {
|
|
|
|
fn len(&self) -> usize;
|
2021-10-06 02:58:22 +00:00
|
|
|
fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error>;
|
|
|
|
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error>;
|
|
|
|
|
|
|
|
fn read_u8(&mut self, addr: Address) -> Result<u8, Error> {
|
|
|
|
Ok(self.read(addr, 1)?[0])
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_beu16(&mut self, addr: Address) -> Result<u16, Error> {
|
|
|
|
Ok(read_beu16(&self.read(addr, 2)?))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_beu32(&mut self, addr: Address) -> Result<u32, Error> {
|
|
|
|
Ok(read_beu32(&self.read(addr, 4)?))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_u8(&mut self, addr: Address, value: u8) -> Result<(), Error> {
|
|
|
|
let data = [value];
|
|
|
|
self.write(addr, &data)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_beu16(&mut self, addr: Address, value: u16) -> Result<(), Error> {
|
|
|
|
let data = write_beu16(value);
|
|
|
|
self.write(addr, &data)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_beu32(&mut self, addr: Address, value: u32) -> Result<(), Error> {
|
|
|
|
let data = write_beu32(value);
|
|
|
|
self.write(addr, &data)
|
|
|
|
}
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-30 06:21:11 +00:00
|
|
|
pub struct MemoryBlock {
|
2021-09-28 23:09:38 +00:00
|
|
|
pub contents: Vec<u8>,
|
|
|
|
}
|
|
|
|
|
2021-09-30 06:21:11 +00:00
|
|
|
impl MemoryBlock {
|
|
|
|
pub fn new(contents: Vec<u8>) -> MemoryBlock {
|
|
|
|
MemoryBlock {
|
|
|
|
contents
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-30 06:21:11 +00:00
|
|
|
pub fn load(filename: &str) -> Result<MemoryBlock, Error> {
|
2021-09-28 23:09:38 +00:00
|
|
|
match fs::read(filename) {
|
2021-09-30 06:21:11 +00:00
|
|
|
Ok(contents) => Ok(MemoryBlock::new(contents)),
|
2021-09-28 23:09:38 +00:00
|
|
|
Err(_) => Err(Error::new(&format!("Error reading contents of {}", filename))),
|
|
|
|
}
|
|
|
|
}
|
2021-10-03 16:55:20 +00:00
|
|
|
|
|
|
|
pub fn load_at(&mut self, mut addr: Address, filename: &str) -> Result<(), Error> {
|
|
|
|
match fs::read(filename) {
|
|
|
|
Ok(contents) => {
|
|
|
|
for byte in contents {
|
|
|
|
self.contents[addr as usize] = byte;
|
|
|
|
addr += 1;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
},
|
|
|
|
Err(_) => Err(Error::new(&format!("Error reading contents of {}", filename))),
|
|
|
|
}
|
|
|
|
}
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
2021-09-30 06:21:11 +00:00
|
|
|
impl Addressable for MemoryBlock {
|
|
|
|
fn len(&self) -> usize {
|
|
|
|
self.contents.len()
|
|
|
|
}
|
|
|
|
|
2021-10-06 02:58:22 +00:00
|
|
|
fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
|
|
|
|
Ok(self.contents[(addr as usize) .. (addr as usize + count)].to_vec())
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 02:58:22 +00:00
|
|
|
fn write(&mut self, mut addr: Address, data: &[u8]) -> Result<(), Error> {
|
2021-09-28 23:09:38 +00:00
|
|
|
for byte in data {
|
2021-09-30 06:21:11 +00:00
|
|
|
self.contents[addr as usize] = *byte;
|
2021-09-30 04:52:38 +00:00
|
|
|
addr += 1;
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
2021-10-06 02:58:22 +00:00
|
|
|
Ok(())
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-07 16:41:01 +00:00
|
|
|
impl Steppable for MemoryBlock {
|
2021-10-06 23:14:56 +00:00
|
|
|
fn step(&mut self, _system: &System) -> Result<Clock, Error> {
|
|
|
|
Ok(1)
|
|
|
|
}
|
|
|
|
}
|
2021-09-28 23:09:38 +00:00
|
|
|
|
|
|
|
|
2021-10-06 23:14:56 +00:00
|
|
|
pub struct Block {
|
2021-09-30 06:21:11 +00:00
|
|
|
pub base: Address,
|
2021-10-06 23:14:56 +00:00
|
|
|
pub length: usize,
|
2021-10-07 16:41:01 +00:00
|
|
|
pub dev: AddressableDeviceBox,
|
2021-09-30 06:21:11 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 23:14:56 +00:00
|
|
|
pub struct Bus {
|
|
|
|
pub blocks: Vec<Block>,
|
2021-09-30 06:21:11 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 23:14:56 +00:00
|
|
|
impl Bus {
|
|
|
|
pub fn new() -> Bus {
|
|
|
|
Bus {
|
|
|
|
blocks: vec!(),
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-07 16:41:01 +00:00
|
|
|
pub fn insert(&mut self, base: Address, length: usize, dev: AddressableDeviceBox) {
|
2021-10-06 23:14:56 +00:00
|
|
|
let block = Block { base, length, dev };
|
|
|
|
for i in 0..self.blocks.len() {
|
|
|
|
if self.blocks[i].base > block.base {
|
|
|
|
self.blocks.insert(i, block);
|
2021-09-28 23:09:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2021-10-06 23:14:56 +00:00
|
|
|
self.blocks.insert(0, block);
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
2021-10-07 16:41:01 +00:00
|
|
|
pub fn get_device_at(&self, addr: Address, count: usize) -> Result<(AddressableDeviceBox, Address), Error> {
|
2021-10-06 23:14:56 +00:00
|
|
|
for block in &self.blocks {
|
|
|
|
if addr >= block.base && addr <= (block.base + block.length as Address) {
|
|
|
|
let relative_addr = addr - block.base;
|
|
|
|
if relative_addr as usize + count <= block.length {
|
2021-10-07 16:41:01 +00:00
|
|
|
return Ok((block.dev.clone(), relative_addr));
|
2021-10-06 23:14:56 +00:00
|
|
|
} else {
|
|
|
|
return Err(Error::new(&format!("Error reading address {:#010x}", addr)));
|
|
|
|
}
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-30 04:52:38 +00:00
|
|
|
return Err(Error::new(&format!("No segment found at {:#08x}", addr)));
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
2021-10-07 16:41:01 +00:00
|
|
|
pub fn dump_memory(&mut self, mut addr: Address, mut count: Address) {
|
|
|
|
while count > 0 {
|
|
|
|
let mut line = format!("{:#010x}: ", addr);
|
|
|
|
|
|
|
|
let to = if count < 16 { count / 2 } else { 8 };
|
|
|
|
for _ in 0..to {
|
|
|
|
let word = self.read_beu16(addr);
|
|
|
|
if word.is_err() {
|
|
|
|
println!("{}", line);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
line += &format!("{:#06x} ", word.unwrap());
|
|
|
|
addr += 2;
|
|
|
|
count -= 2;
|
|
|
|
}
|
|
|
|
println!("{}", line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Addressable for Bus {
|
|
|
|
fn len(&self) -> usize {
|
2021-10-06 23:14:56 +00:00
|
|
|
let block = &self.blocks[self.blocks.len() - 1];
|
2021-10-07 16:41:01 +00:00
|
|
|
(block.base as usize) + block.length
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
|
|
|
|
let (dev, relative_addr) = self.get_device_at(addr, count)?;
|
|
|
|
let result = dev.borrow_mut().read(relative_addr, count);
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
|
|
|
|
let (dev, relative_addr) = self.get_device_at(addr, data.len())?;
|
|
|
|
let result = dev.borrow_mut().write(relative_addr, data);
|
|
|
|
result
|
2021-09-30 19:58:11 +00:00
|
|
|
}
|
2021-10-06 02:58:22 +00:00
|
|
|
}
|
2021-09-30 19:58:11 +00:00
|
|
|
|
2021-09-28 23:09:38 +00:00
|
|
|
|
2021-10-04 04:05:10 +00:00
|
|
|
#[inline(always)]
|
2021-10-06 02:58:22 +00:00
|
|
|
pub fn read_beu16(data: &[u8]) -> u16 {
|
2021-10-04 04:05:10 +00:00
|
|
|
(data[0] as u16) << 8 |
|
|
|
|
(data[1] as u16)
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
2021-10-04 04:05:10 +00:00
|
|
|
#[inline(always)]
|
2021-10-06 02:58:22 +00:00
|
|
|
pub fn read_beu32(data: &[u8]) -> u32 {
|
2021-10-04 04:05:10 +00:00
|
|
|
(data[0] as u32) << 24 |
|
|
|
|
(data[1] as u32) << 16 |
|
|
|
|
(data[2] as u32) << 8 |
|
|
|
|
(data[3] as u32)
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
2021-10-06 02:58:22 +00:00
|
|
|
#[inline(always)]
|
|
|
|
pub fn write_beu16(value: u16) -> [u8; 2] {
|
|
|
|
[
|
|
|
|
(value >> 8) as u8,
|
|
|
|
value as u8,
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn write_beu32(value: u32) -> [u8; 4] {
|
|
|
|
[
|
|
|
|
(value >> 24) as u8,
|
|
|
|
(value >> 16) as u8,
|
|
|
|
(value >> 8) as u8,
|
|
|
|
value as u8,
|
|
|
|
]
|
|
|
|
}
|
2021-10-06 23:14:56 +00:00
|
|
|
|