2021-09-28 23:09:38 +00:00
|
|
|
|
|
|
|
use std::fs;
|
2021-10-27 04:32:25 +00:00
|
|
|
use std::rc::Rc;
|
|
|
|
use std::cell::RefCell;
|
2021-09-28 23:09:38 +00:00
|
|
|
|
|
|
|
use crate::error::Error;
|
2021-11-13 19:39:20 +00:00
|
|
|
use crate::devices::{Address, Addressable, Transmutable, TransmutableBox};
|
2021-09-28 23:09:38 +00:00
|
|
|
|
|
|
|
|
2021-09-30 06:21:11 +00:00
|
|
|
pub struct MemoryBlock {
|
2021-11-03 22:33:22 +00:00
|
|
|
pub read_only: bool,
|
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 {
|
2021-11-03 22:33:22 +00:00
|
|
|
read_only: false,
|
2021-09-30 06:21:11 +00:00
|
|
|
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
|
|
|
|
2021-11-09 19:03:57 +00:00
|
|
|
pub fn load_at(&mut self, addr: Address, filename: &str) -> Result<(), Error> {
|
2021-10-03 16:55:20 +00:00
|
|
|
match fs::read(filename) {
|
|
|
|
Ok(contents) => {
|
2021-11-09 19:03:57 +00:00
|
|
|
for i in 0..contents.len() {
|
|
|
|
self.contents[(addr as usize) + i] = contents[i];
|
2021-10-03 16:55:20 +00:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
},
|
|
|
|
Err(_) => Err(Error::new(&format!("Error reading contents of {}", filename))),
|
|
|
|
}
|
|
|
|
}
|
2021-11-03 22:33:22 +00:00
|
|
|
|
|
|
|
pub fn read_only(&mut self) {
|
|
|
|
self.read_only = true;
|
|
|
|
}
|
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-27 00:33:23 +00:00
|
|
|
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
|
|
|
|
for i in 0..data.len() {
|
2021-10-16 17:58:27 +00:00
|
|
|
data[i] = self.contents[(addr as usize) + i];
|
|
|
|
}
|
2021-10-27 00:33:23 +00:00
|
|
|
Ok(())
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
2021-11-09 19:03:57 +00:00
|
|
|
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
|
2021-11-03 22:33:22 +00:00
|
|
|
if self.read_only {
|
|
|
|
return Err(Error::breakpoint(&format!("Attempt to write to read-only memory at {:x} with data {:?}", addr, data)));
|
|
|
|
}
|
|
|
|
|
2021-11-09 19:03:57 +00:00
|
|
|
for i in 0..data.len() {
|
|
|
|
self.contents[(addr as usize) + i] = data[i];
|
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-17 17:39:43 +00:00
|
|
|
impl Transmutable for MemoryBlock {
|
|
|
|
fn as_addressable(&mut self) -> Option<&mut dyn Addressable> {
|
|
|
|
Some(self)
|
2021-10-06 23:14:56 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-28 23:09:38 +00:00
|
|
|
|
|
|
|
|
2021-12-02 23:04:41 +00:00
|
|
|
pub struct AddressAdapter {
|
2021-11-13 19:39:20 +00:00
|
|
|
pub subdevice: TransmutableBox,
|
|
|
|
pub shift: u8,
|
|
|
|
}
|
|
|
|
|
2021-12-02 23:04:41 +00:00
|
|
|
impl AddressAdapter {
|
2021-11-13 19:39:20 +00:00
|
|
|
pub fn new(subdevice: TransmutableBox, shift: u8) -> Self {
|
|
|
|
Self {
|
|
|
|
subdevice,
|
|
|
|
shift,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-02 23:04:41 +00:00
|
|
|
impl Addressable for AddressAdapter {
|
2021-11-13 19:39:20 +00:00
|
|
|
fn len(&self) -> usize {
|
|
|
|
let len = self.subdevice.borrow_mut().as_addressable().unwrap().len();
|
|
|
|
len << self.shift
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
|
|
|
|
self.subdevice.borrow_mut().as_addressable().unwrap().read(addr >> self.shift, data)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
|
|
|
|
self.subdevice.borrow_mut().as_addressable().unwrap().write(addr >> self.shift, data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-02 23:04:41 +00:00
|
|
|
impl Transmutable for AddressAdapter {
|
2021-11-13 19:39:20 +00:00
|
|
|
fn as_addressable(&mut self) -> Option<&mut dyn Addressable> {
|
|
|
|
Some(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-17 17:39:43 +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-17 17:39:43 +00:00
|
|
|
pub dev: TransmutableBox,
|
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-17 17:39:43 +00:00
|
|
|
pub fn insert(&mut self, base: Address, length: usize, dev: TransmutableBox) {
|
2021-10-06 23:14:56 +00:00
|
|
|
let block = Block { base, length, dev };
|
2021-11-23 19:45:11 +00:00
|
|
|
let i = self.blocks.iter().position(|cur| cur.base > block.base).unwrap_or(self.blocks.len());
|
2021-11-18 16:46:41 +00:00
|
|
|
self.blocks.insert(i, block);
|
2021-09-28 23:09:38 +00:00
|
|
|
}
|
|
|
|
|
2021-10-17 17:39:43 +00:00
|
|
|
pub fn get_device_at(&self, addr: Address, count: usize) -> Result<(TransmutableBox, Address), Error> {
|
2021-10-06 23:14:56 +00:00
|
|
|
for block in &self.blocks {
|
2021-11-09 19:03:57 +00:00
|
|
|
if addr >= block.base && addr < (block.base + block.length as Address) {
|
2021-10-06 23:14:56 +00:00
|
|
|
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-11-23 19:45:11 +00:00
|
|
|
return Err(Error::new(&format!("No segment found at {:#010x}", 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
|
|
|
|
}
|
|
|
|
|
2021-10-27 00:33:23 +00:00
|
|
|
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
|
|
|
|
let (dev, relative_addr) = self.get_device_at(addr, data.len())?;
|
|
|
|
let result = dev.borrow_mut().as_addressable().unwrap().read(relative_addr, data);
|
2021-10-07 16:41:01 +00:00
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
|
|
|
|
let (dev, relative_addr) = self.get_device_at(addr, data.len())?;
|
2021-10-17 17:39:43 +00:00
|
|
|
let result = dev.borrow_mut().as_addressable().unwrap().write(relative_addr, data);
|
2021-10-07 16:41:01 +00:00
|
|
|
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-10-27 04:32:25 +00:00
|
|
|
pub struct BusPort {
|
|
|
|
pub offset: Address,
|
|
|
|
pub address_mask: Address,
|
|
|
|
pub data_width: u8,
|
|
|
|
pub subdevice: Rc<RefCell<Bus>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BusPort {
|
|
|
|
pub fn new(offset: Address, address_bits: u8, data_bits: u8, bus: Rc<RefCell<Bus>>) -> Self {
|
|
|
|
let mut address_mask = 0;
|
|
|
|
for _ in 0..address_bits {
|
|
|
|
address_mask = (address_mask << 1) | 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
Self {
|
|
|
|
offset,
|
|
|
|
address_mask,
|
|
|
|
data_width: data_bits / 8,
|
|
|
|
subdevice: bus,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-09 19:03:57 +00:00
|
|
|
pub fn dump_memory(&mut self, addr: Address, count: Address) {
|
2021-11-03 22:33:22 +00:00
|
|
|
self.subdevice.borrow_mut().dump_memory(self.offset + (addr & self.address_mask), count)
|
2021-10-27 04:32:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Addressable for BusPort {
|
|
|
|
fn len(&self) -> usize {
|
|
|
|
self.subdevice.borrow().len()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
|
|
|
|
let addr = self.offset + (addr & self.address_mask);
|
|
|
|
let mut subdevice = self.subdevice.borrow_mut();
|
|
|
|
for i in (0..data.len()).step_by(self.data_width as usize) {
|
|
|
|
let end = std::cmp::min(i + self.data_width as usize, data.len());
|
|
|
|
subdevice.read(addr + i as Address, &mut data[i..end])?;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
|
|
|
|
let addr = self.offset + (addr & self.address_mask);
|
|
|
|
let mut subdevice = self.subdevice.borrow_mut();
|
|
|
|
for i in (0..data.len()).step_by(self.data_width as usize) {
|
|
|
|
let end = std::cmp::min(i + self.data_width as usize, data.len());
|
|
|
|
subdevice.write(addr + i as Address, &data[i..end])?;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|