Bus mastering

This commit is contained in:
Benjamin Kyd
2023-05-25 18:37:21 +01:00
parent 0b2b39d308
commit a0046bd58d
4 changed files with 125 additions and 36 deletions

View File

@@ -1,5 +1,6 @@
pub const DRAM_BASE: u32 = 0x80000000;
use crate::rv32;
use crate::ram;
pub struct Bus {
@@ -10,4 +11,52 @@ impl Bus {
pub fn new() -> Bus {
Bus { memory: ram::RAM::new() }
}
pub fn load_8(&mut self, address: rv32::XLen) -> rv32::Byte {
match address {
DRAM_BASE.. => {
self.memory.read_8(address)
}
_ => {
println!("VM > BUS > Peripheral at 0x{:08x} does not exist", address);
rv32::Byte::default()
},
}
}
pub fn load_16(&mut self, address: rv32::XLen) -> rv32::HalfWord {
match address {
DRAM_BASE.. => {
self.memory.read_16(address)
}
_ => {
println!("VM > BUS > Peripheral at 0x{:08x} does not exist", address);
rv32::HalfWord::default()
},
}
}
pub fn load_32(&mut self, address: rv32::XLen) -> rv32::Word {
match address {
DRAM_BASE.. => {
self.memory.read_32(address)
}
_ => {
println!("VM > BUS > Peripheral at 0x{:08x} does not exist", address);
rv32::Word::default()
},
}
}
pub fn load_64(&mut self, address: rv32::XLen) -> rv32::DoubleWord {
match address {
DRAM_BASE.. => {
self.memory.read_64(address)
}
_ => {
println!("VM > BUS > Peripheral at 0x{:08x} does not exist", address);
rv32::DoubleWord::default()
},
}
}
}

View File

@@ -47,7 +47,7 @@ impl VMRV32I {
}
fn dump_prog(&mut self) {
println!("VM > Dumping program");
println!("VM > Dumping program (virtual addresses)");
for i in 0..12 {
println!("VM > 0x{:08x}: 0x{:02x}", i, self.bus.memory.0[i]);
}
@@ -69,8 +69,17 @@ impl VMRV32I {
}
fn exec(&mut self) {
let val: u8 = self.bus.memory.read::<rv32::Byte>(0x80000000)
println!("VM > WORD at 0x80000000: 0x{:08x}", val);
let val: u8 = self.bus.memory.read_8(0x80000000);
println!("VM > BYTE at 0x80000000: 0x{:02x}", val);
let val = self.bus.memory.read_16(0x80000000);
println!("VM > HWORD at 0x80000000: 0x{:04x}", val);
let val = self.bus.memory.read_32(0x80000000);
println!("VM > WORD at 0x80000000: 0x{:08x}", val);
let val = self.bus.memory.read_64(0x80000000);
println!("VM > DWORD at 0x80000000: 0x{:016x}", val);
let val = self.bus.load_8(0x7FFFFFFF);
println!("VM > BYTE at 0x80000000: 0x{:02x}", val);
while self.pc > self.bus.memory.len() as u32 {
let inst = self.fetch();

View File

@@ -14,30 +14,68 @@ impl RAM {
self.0.len()
}
pub fn read<T>(&mut self, address: rv32::XLen) -> T
where
T: num::Num
+ num::ToPrimitive
+ Default
+ std::fmt::LowerHex
+ std::ops::Shl<T, Output = T>
+ std::ops::BitOr<T, Output = T>
+ num::cast::NumCast,
{
let address: usize = (address - bus::DRAM_BASE) as usize;
pub fn read_8(&mut self, address: rv32::XLen) -> rv32::Byte {
let memory = &self.0;
(address..)
.take(core::mem::size_of::<T>())
.enumerate()
.fold(T::default(), |mut acc, (i, x)| {
println!("VM > Reading from 0x{:08x} to 0x{:08x}", x, acc);
println!("VM > Memory: 0x{:02x}", memory[x]);
println!("VM > Now Shift: {}", i * 8);
acc << u32::from(i as u32 * 8) | memory[x].from()
})
let address = (address - bus::DRAM_BASE) as usize;
memory[address]
}
pub fn write<T>(&mut self, address: rv32::XLen, data: T) {}
pub fn read_16(&mut self, address: rv32::XLen) -> rv32::HalfWord {
let memory = &self.0;
let address = (address - bus::DRAM_BASE) as usize;
let ret: rv32::HalfWord =
memory[address] as rv32::HalfWord | (memory[address + 1] as rv32::HalfWord) << 8;
ret
}
pub fn read_32(&mut self, address: rv32::XLen) -> rv32::Word {
let memory = &self.0;
let address = (address - bus::DRAM_BASE) as usize;
let ret: rv32::Word = memory[address] as rv32::Word
| (memory[address + 1] as rv32::Word) << 8
| (memory[address + 2] as rv32::Word) << 16
| (memory[address + 3] as rv32::Word) << 24;
ret
}
pub fn read_64(&mut self, address: rv32::XLen) -> rv32::DoubleWord {
let memory = &self.0;
let address = (address - bus::DRAM_BASE) as usize;
let ret: rv32::DoubleWord = memory[address] as rv32::DoubleWord
| (memory[address + 1] as rv32::DoubleWord) << 8
| (memory[address + 2] as rv32::DoubleWord) << 16
| (memory[address + 3] as rv32::DoubleWord) << 24
| (memory[address + 4] as rv32::DoubleWord) << 32
| (memory[address + 5] as rv32::DoubleWord) << 40
| (memory[address + 6] as rv32::DoubleWord) << 48
| (memory[address + 7] as rv32::DoubleWord) << 56;
ret
}
//pub fn read<T>(&mut self, address: rv32::XLen) -> T
//where
//T: num::Num
//+ num::ToPrimitive
//+ Default
//+ std::fmt::LowerHex
//+ std::ops::Shl<T, Output = T>
//+ std::ops::BitOr<T, Output = T>
//+ num::cast::NumCast,
//{
//let address: usize = (address - bus::DRAM_BASE) as usize;
//let memory = &self.0;
//(address..)
//.take(core::mem::size_of::<T>())
//.enumerate()
//.fold(T::default(), |mut acc, (i, x)| {
//println!("VM > Reading from 0x{:08x} to 0x{:08x}", x, acc);
//println!("VM > Memory: 0x{:02x}", memory[x]);
//println!("VM > Now Shift: {}", i * 8);
//acc << u32::from(i as u32 * 8) | memory[x].from()
//})
//}
//pub fn write<T>(&mut self, address: rv32::XLen, data: T) {}
}

View File

@@ -1,22 +1,15 @@
pub const XLEN: usize = 32;
pub type XLen = u32;
enum Data {
QuadWord(u128),
DoubleWord(u64),
Word(u32),
HalfWord(u16),
Byte(u8),
}
// define words as byte fraction
//pub const QUADWORD: usize = 16;
pub const QUADWORD: usize = 16;
pub const DOUBLEWORD: usize = 8;
pub const WORD: usize = 4;
pub const HALFWORD: usize = 2;
pub const BYTE: usize = 1;
//pub type DoubleWord = u64;
pub type QuadWord = u128;
pub type DoubleWord = u64;
pub type Word = u32;
pub type HalfWord = u16;
pub type Byte = u8;