Skip to content

Commit

Permalink
Merge pull request #4 from howjmay/basic
Browse files Browse the repository at this point in the history
refactor: Refactor architecture
  • Loading branch information
howjmay committed Feb 15, 2024
2 parents c340474 + 4ad2bc4 commit b066371
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 111 deletions.
65 changes: 33 additions & 32 deletions src/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::registers;
pub struct CPU {
// integer registers
pub xregs: registers::XREGS,
pub pc: u64,
pub pc: u32,

pub bus: memory::BUS,
}
Expand Down Expand Up @@ -114,22 +114,23 @@ impl CPU {
// RV32I
// see page 64 at https://riscv.org/wp-content/uploads/2016/06/riscv-spec-v2.1.pdf
pub fn exec_lui(cpu: &mut CPU, instr: u32) {
let imm = (imm_U(instr) as i32) as u64;
let imm = (imm_u(instr) as i32) as u32;
cpu.xregs.regs[rd(instr) as usize] = imm;
}
pub fn exec_auipc(cpu: &mut CPU, instr: u32) {
let imm = (imm_U(instr) as i32) as i64;
cpu.xregs.regs[rd(instr) as usize] = (cpu.pc as i64 + imm) as u64;
let imm = imm_u(instr) as i32;
cpu.xregs.regs[rd(instr) as usize] = (cpu.pc as i32).wrapping_add(imm) as u32;
}
pub fn exec_jal(cpu: &mut CPU, instr: u32) {
let imm = (imm_J(instr) as i32) as i64;
let imm = imm_j(instr) as i32;
cpu.xregs.regs[rd(instr) as usize] = cpu.pc + 4;
cpu.pc = (cpu.pc as i64 + imm) as u64;
cpu.pc = (cpu.pc as i32 + imm) as u32;
}
pub fn exec_jalr(cpu: &mut CPU, instr: u32) {
let imm = (imm_J(instr) as i32) as i64;
let imm = imm_i(instr) as i32;
cpu.xregs.regs[rd(instr) as usize] = cpu.pc + 4;
cpu.pc = (cpu.pc as i64 + imm) as u64;
// ignore the last 1 bit with 0xfffffffe
cpu.pc = (cpu.xregs.regs[rs1(instr) as usize] as i32).wrapping_add(imm) as u32 & 0xfffffffe;
}
pub fn exec_beq(cpu: &mut CPU, instr: u32) {}
pub fn exec_bne(cpu: &mut CPU, instr: u32) {}
Expand All @@ -149,51 +150,51 @@ pub fn exec_sh(cpu: &mut CPU, instr: u32) {}
pub fn exec_sw(cpu: &mut CPU, instr: u32) {}
pub fn exec_sd(cpu: &mut CPU, instr: u32) {}
pub fn exec_addi(cpu: &mut CPU, instr: u32) {
let imm = imm_I(instr);
cpu.xregs.regs[rd(instr) as usize] = cpu.xregs.regs[rs1(instr) as usize] + imm as u64;
let imm = imm_i(instr);
cpu.xregs.regs[rd(instr) as usize] = cpu.xregs.regs[rs1(instr) as usize] + imm as u32;
}
pub fn exec_slti(cpu: &mut CPU, instr: u32) {
let imm = imm_I(instr);
let imm = imm_i(instr);
cpu.xregs.regs[rd(instr) as usize] =
((cpu.xregs.regs[rs1(instr) as usize] as i64) < (imm as i64)) as u64;
((cpu.xregs.regs[rs1(instr) as usize] as i32) < (imm as i32)) as u32;
}
pub fn exec_sltiu(cpu: &mut CPU, instr: u32) {
let imm = imm_I(instr);
cpu.xregs.regs[rd(instr) as usize] = (cpu.xregs.regs[rs1(instr) as usize] < imm as u64) as u64;
let imm = imm_i(instr);
cpu.xregs.regs[rd(instr) as usize] = (cpu.xregs.regs[rs1(instr) as usize] < imm as u32) as u32;
}
pub fn exec_xori(cpu: &mut CPU, instr: u32) {
let imm = imm_I(instr);
cpu.xregs.regs[rd(instr) as usize] = cpu.xregs.regs[rs1(instr) as usize] ^ imm as u64;
let imm = imm_i(instr);
cpu.xregs.regs[rd(instr) as usize] = cpu.xregs.regs[rs1(instr) as usize] ^ imm as u32;
}
pub fn exec_ori(cpu: &mut CPU, instr: u32) {
let imm = imm_I(instr);
cpu.xregs.regs[rd(instr) as usize] = cpu.xregs.regs[rs1(instr) as usize] | imm as u64;
let imm = imm_i(instr);
cpu.xregs.regs[rd(instr) as usize] = cpu.xregs.regs[rs1(instr) as usize] | imm as u32;
}
pub fn exec_andi(cpu: &mut CPU, instr: u32) {
let imm = imm_I(instr);
cpu.xregs.regs[rd(instr) as usize] = cpu.xregs.regs[rs1(instr) as usize] & imm as u64;
let imm = imm_i(instr);
cpu.xregs.regs[rd(instr) as usize] = cpu.xregs.regs[rs1(instr) as usize] & imm as u32;
}
pub fn exec_slli(cpu: &mut CPU, instr: u32) {
let imm = imm_I(instr);
cpu.xregs.regs[rd(instr) as usize] = cpu.xregs.regs[rs1(instr) as usize] << imm as u64;
let imm = imm_i(instr);
cpu.xregs.regs[rd(instr) as usize] = cpu.xregs.regs[rs1(instr) as usize] << imm as u32;
}
pub fn exec_srli(cpu: &mut CPU, instr: u32) {
let imm = imm_I(instr);
cpu.xregs.regs[rd(instr) as usize] = cpu.xregs.regs[rs1(instr) as usize] >> imm as u64;
let imm = imm_i(instr);
cpu.xregs.regs[rd(instr) as usize] = cpu.xregs.regs[rs1(instr) as usize] >> imm as u32;
}
pub fn exec_srai(cpu: &mut CPU, instr: u32) {
let imm = imm_I(instr);
cpu.xregs.regs[rd(instr) as usize] = (cpu.xregs.regs[rs1(instr) as usize] as i64 >> imm) as u64;
let imm = imm_i(instr);
cpu.xregs.regs[rd(instr) as usize] = (cpu.xregs.regs[rs1(instr) as usize] as i32 >> imm) as u32;
}
pub fn exec_add(cpu: &mut CPU, instr: u32) {
cpu.xregs.regs[rd(instr) as usize] = (cpu.xregs.regs[rs1(instr) as usize] as i64
+ cpu.xregs.regs[rs2(instr) as usize] as i64)
as u64;
cpu.xregs.regs[rd(instr) as usize] = (cpu.xregs.regs[rs1(instr) as usize] as i32
+ cpu.xregs.regs[rs2(instr) as usize] as i32)
as u32;
}
pub fn exec_sub(cpu: &mut CPU, instr: u32) {
cpu.xregs.regs[rd(instr) as usize] = (cpu.xregs.regs[rs1(instr) as usize] as i64
- cpu.xregs.regs[rs2(instr) as usize] as i64)
as u64;
cpu.xregs.regs[rd(instr) as usize] = (cpu.xregs.regs[rs1(instr) as usize] as i32
- cpu.xregs.regs[rs2(instr) as usize] as i32)
as u32;
}
pub fn exec_sll(cpu: &mut CPU, instr: u32) {}
pub fn exec_slt(cpu: &mut CPU, instr: u32) {}
Expand Down
96 changes: 48 additions & 48 deletions src/memory.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// pub mod memory;

pub const MEM_BASE: u64 = 0x80000000; // defined in QEMU
pub const MEM_SIZE: u64 = 1024;
pub const MEM_BASE: u32 = 0x80000000; // defined in QEMU
pub const MEM_SIZE: u32 = 1024;

#[derive(Debug)]
pub struct BUS {
Expand All @@ -12,10 +12,10 @@ impl BUS {
pub fn new() -> Self {
BUS { mem: MEMORY::new() }
}
pub fn load(self, addr: u64, size: u64) -> u32 {
pub fn load(self, addr: u32, size: u32) -> u32 {
return self.mem.load(addr, size) as u32;
}
pub fn store(&mut self, addr: u64, size: u64, value: u64) {
pub fn store(&mut self, addr: u32, size: u32, value: u32) {
self.mem.store(addr, size, value);
}
}
Expand All @@ -32,78 +32,78 @@ impl MEMORY {
}
}

fn load(self, addr: u64, size: u64) -> u64 {
fn load(self, addr: u32, size: u32) -> u32 {
match size {
8 => return self.load8(addr),
16 => return self.load16(addr),
32 => return self.load32(addr),
64 => return self.load64(addr),
// 64 => return self.load64(addr),
_ => panic!("wrong load size"),
}
}
fn store(&mut self, addr: u64, size: u64, value: u64) {
fn store(&mut self, addr: u32, size: u32, value: u32) {
match size {
8 => self.store8(addr, value),
16 => self.store16(addr, value),
32 => self.store32(addr, value),
64 => self.store64(addr, value),
// 64 => self.store64(addr, value),
_ => panic!("wrong store size"),
}
}

// load funcs
fn load8(self, addr: u64) -> u64 {
fn load8(self, addr: u32) -> u32 {
let index = (addr - MEM_BASE) as usize;
return self.mem[index] as u64;
return self.mem[index] as u32;
}
fn load16(self, addr: u64) -> u64 {
fn load16(self, addr: u32) -> u32 {
let index = (addr - MEM_BASE) as usize;
return self.mem[index] as u64 | ((self.mem[index + 1] as u64) << 8);
return self.mem[index] as u32 | ((self.mem[index + 1] as u32) << 8);
}
fn load32(self, addr: u64) -> u64 {
fn load32(self, addr: u32) -> u32 {
let index = (addr - MEM_BASE) as usize;
return self.mem[index] as u64
| ((self.mem[index + 1] as u64) << 8)
| ((self.mem[index + 2] as u64) << 16)
| ((self.mem[index + 3] as u64) << 24);
}
fn load64(self, addr: u64) -> u64 {
let index = (addr - MEM_BASE) as usize;
return self.mem[index] as u64
| ((self.mem[index + 1] as u64) << 8)
| ((self.mem[index + 2] as u64) << 16)
| ((self.mem[index + 3] as u64) << 24)
| ((self.mem[index + 4] as u64) << 32)
| ((self.mem[index + 5] as u64) << 40)
| ((self.mem[index + 6] as u64) << 48)
| ((self.mem[index + 7] as u64) << 56);
return self.mem[index] as u32
| ((self.mem[index + 1] as u32) << 8)
| ((self.mem[index + 2] as u32) << 16)
| ((self.mem[index + 3] as u32) << 24);
}
// fn load64(self, addr: u32) -> u32 {
// let index = (addr - MEM_BASE) as usize;
// return self.mem[index] as u32
// | ((self.mem[index + 1] as u32) << 8)
// | ((self.mem[index + 2] as u32) << 16)
// | ((self.mem[index + 3] as u32) << 24)
// | ((self.mem[index + 4] as u32) << 32)
// | ((self.mem[index + 5] as u32) << 40)
// | ((self.mem[index + 6] as u32) << 48)
// | ((self.mem[index + 7] as u32) << 56);
// }

// store funcs
fn store8(&mut self, addr: u64, value: u64) {
let index = (addr - MEM_BASE) as usize;
self.mem[index] = (value & (std::u8::MAX as u64)) as u8;
}
fn store16(&mut self, addr: u64, value: u64) {
fn store8(&mut self, addr: u32, value: u32) {
let index = (addr - MEM_BASE) as usize;
self.mem[index] = (value & (std::u8::MAX as u64)) as u8;
self.mem[index + 1] = ((value >> 8) & (std::u8::MAX as u64)) as u8;
self.mem[index] = (value & (std::u8::MAX as u32)) as u8;
}
fn store32(&mut self, addr: u64, value: u64) {
fn store16(&mut self, addr: u32, value: u32) {
let index = (addr - MEM_BASE) as usize;
self.mem[index] = (value & (std::u8::MAX as u64)) as u8;
self.mem[index + 1] = ((value >> 8) & (std::u8::MAX as u64)) as u8;
self.mem[index + 2] = ((value >> 16) & (std::u8::MAX as u64)) as u8;
self.mem[index] = (value & (std::u8::MAX as u32)) as u8;
self.mem[index + 1] = ((value >> 8) & (std::u8::MAX as u32)) as u8;
}
fn store64(&mut self, addr: u64, value: u64) {
fn store32(&mut self, addr: u32, value: u32) {
let index = (addr - MEM_BASE) as usize;
self.mem[index] = (value & (std::u8::MAX as u64)) as u8;
self.mem[index + 1] = ((value >> 8) & (std::u8::MAX as u64)) as u8;
self.mem[index + 2] = ((value >> 16) & (std::u8::MAX as u64)) as u8;
self.mem[index + 3] = ((value >> 24) & (std::u8::MAX as u64)) as u8;
self.mem[index + 4] = ((value >> 32) & (std::u8::MAX as u64)) as u8;
self.mem[index + 5] = ((value >> 40) & (std::u8::MAX as u64)) as u8;
self.mem[index + 6] = ((value >> 48) & (std::u8::MAX as u64)) as u8;
self.mem[index + 7] = ((value >> 56) & (std::u8::MAX as u64)) as u8;
self.mem[index] = (value & (std::u8::MAX as u32)) as u8;
self.mem[index + 1] = ((value >> 8) & (std::u8::MAX as u32)) as u8;
self.mem[index + 2] = ((value >> 16) & (std::u8::MAX as u32)) as u8;
}
// fn store64(&mut self, addr: u32, value: u32) {
// let index = (addr - MEM_BASE) as usize;
// self.mem[index] = (value & (std::u8::MAX as u32)) as u8;
// self.mem[index + 1] = ((value >> 8) & (std::u8::MAX as u32)) as u8;
// self.mem[index + 2] = ((value >> 16) & (std::u8::MAX as u32)) as u8;
// self.mem[index + 3] = ((value >> 24) & (std::u8::MAX as u32)) as u8;
// self.mem[index + 4] = ((value >> 32) & (std::u8::MAX as u32)) as u8;
// self.mem[index + 5] = ((value >> 40) & (std::u8::MAX as u32)) as u8;
// self.mem[index + 6] = ((value >> 48) & (std::u8::MAX as u32)) as u8;
// self.mem[index + 7] = ((value >> 56) & (std::u8::MAX as u32)) as u8;
// }
}
36 changes: 18 additions & 18 deletions src/opcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,41 +100,41 @@ pub fn rs2(instr: u32) -> u32 {

pub fn shamt(instr: u32) -> u32 {
// shamt[4:5] = imm[5:0]
return (imm_I(instr) & 0x1f) as u32;
return (imm_i(instr) & 0x1f) as u32;
}

pub fn csr(instr: u32) -> u64 {
pub fn csr(instr: u32) -> u32 {
// csr[11:0] = inst[31:20]
return ((instr & 0xfff00000) >> 20) as u64;
return ((instr & 0xfff00000) >> 20) as u32;
}

pub fn imm_B(instr: u32) -> u64 {
pub fn imm_b(instr: u32) -> u32 {
// imm[12|10:5|4:1|11] = inst[31|30:25|11:8|7]
return ((instr & 0x80000000) >> 19) as u64
| ((instr & 0x80) << 4) as u64 // imm[11]
| ((instr >> 20) & 0x7e0) as u64 // imm[10:5]
| ((instr >> 7) & 0x1e) as u64; // imm[4:1]
return ((instr & 0x80000000) >> 19) as u32
| ((instr & 0x80) << 4) as u32 // imm[11]
| ((instr >> 20) & 0x7e0) as u32 // imm[10:5]
| ((instr >> 7) & 0x1e) as u32; // imm[4:1]
}

pub fn imm_S(instr: u32) -> u64 {
pub fn imm_s(instr: u32) -> u32 {
// imm[11:5] = inst[31:25], imm[4:0] = inst[11:7]
return ((instr & 0xfe000000) >> 20) as u64 | ((instr >> 7) & 0x1f) as u64;
return ((instr & 0xfe000000) >> 20) as u32 | ((instr >> 7) & 0x1f) as u32;
}

pub fn imm_I(instr: u32) -> i32 {
pub fn imm_i(instr: u32) -> i32 {
// imm[11:0] = inst[31:20]
return (instr & 0xfff00000) as i32 >> 20;
}

pub fn imm_U(instr: u32) -> u64 {
pub fn imm_u(instr: u32) -> u32 {
// imm[31:12] = inst[31:12]
return (instr & 0xfffff000) as u64;
return (instr & 0xfffff000) as u32;
}

pub fn imm_J(instr: u32) -> u64 {
pub fn imm_j(instr: u32) -> u32 {
// imm[20|10:1|11|19:12] = inst[31|30:21|20|19:12]
return (((instr & 0x80000000) as i32 as i64 >> 11) as u64)// imm[20]
| ((instr & 0x3ff00000) >> 20) as u64 // imm[10:1]
| ((instr & 0x80000) >> 9) as u64 // imm[11]
| (instr & 0xff000) as u64; // imm[19:12]
return (((instr & 0x80000000) as i32 >> 11) as u32)// imm[20]
| ((instr & 0x3ff00000) >> 20) as u32 // imm[10:1]
| ((instr & 0x80000) >> 9) as u32 // imm[11]
| (instr & 0xff000) as u32; // imm[19:12]
}
4 changes: 2 additions & 2 deletions src/registers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use core::fmt;

pub struct XREGS {
pub regs: [u64; 32],
pub regs: [u32; 32],
}

impl XREGS {
Expand All @@ -29,7 +29,7 @@ mod tests {
fn xregs_debug() {
let mut xregs = XREGS::new();
for i in 0..32 {
xregs.regs[i] = (i * 11) as u64;
xregs.regs[i] = (i * 11) as u32;
}
println!("{xregs:#?}")
}
Expand Down
Loading

0 comments on commit b066371

Please sign in to comment.