pull cpu into its own crate

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2023-12-29 23:09:32 +08:00
parent 9ae18afa67
commit 2e6ae9fc5d
9 changed files with 103 additions and 33 deletions

7
Cargo.lock generated
View File

@ -2,6 +2,13 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "riscv-cpu"
version = "0.1.0"
[[package]] [[package]]
name = "rouns" name = "rouns"
version = "0.1.0" version = "0.1.0"
dependencies = [
"riscv-cpu",
]

View File

@ -1,3 +1,5 @@
workspace = { members = ["crates/riscv-cpu"] }
[package] [package]
name = "rouns" name = "rouns"
version = "0.1.0" version = "0.1.0"
@ -6,3 +8,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
riscv-cpu = { path = "crates/riscv-cpu" }

View File

@ -0,0 +1,8 @@
[package]
name = "riscv-cpu"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@ -1,10 +1,6 @@
// extern crate fnv;
// use self::fnv::FnvHashMap;
use std::collections::HashMap; use std::collections::HashMap;
use crate::riscv::mmu::{AddressingMode, Mmu}; use crate::mmu::{AddressingMode, Mmu};
// use terminal::Terminal;
const CSR_CAPACITY: usize = 4096; const CSR_CAPACITY: usize = 4096;
@ -213,13 +209,39 @@ fn get_trap_cause(trap: &Trap, xlen: &Xlen) -> u64 {
} }
} }
impl Cpu { pub struct CpuBuilder {
/// Creates a new `Cpu`. xlen: Xlen,
/// memory_size: u64,
/// # Arguments }
/// * `Terminal`
impl CpuBuilder {
pub fn new() -> Self { pub fn new() -> Self {
let mut cpu = Cpu { CpuBuilder {
xlen: Xlen::Bit64,
memory_size: 0,
}
}
pub fn xlen(mut self, xlen: Xlen) -> Self {
self.xlen = xlen;
self
}
pub fn memory_size(mut self, memory_size: u64) -> Self {
self.memory_size = memory_size;
self
}
pub fn build(self) -> Cpu {
let mut cpu = Cpu::new();
cpu.update_xlen(self.xlen.clone());
cpu
}
}
impl Default for Cpu {
fn default() -> Self {
Cpu {
clock: 0, clock: 0,
xlen: Xlen::Bit64, xlen: Xlen::Bit64,
privilege_mode: PrivilegeMode::Machine, privilege_mode: PrivilegeMode::Machine,
@ -234,10 +256,21 @@ impl Cpu {
_dump_flag: false, _dump_flag: false,
decode_cache: DecodeCache::new(), decode_cache: DecodeCache::new(),
unsigned_data_mask: 0xffffffffffffffff, unsigned_data_mask: 0xffffffffffffffff,
}; }
cpu.x[0xb] = 0x1020; // I don't know why but Linux boot seems to require this initialization }
cpu.write_csr_raw(CSR_MISA_ADDRESS, 0x800000008014312f); }
cpu
impl Cpu {
/// Creates a new `Cpu`.
///
/// # Arguments
/// * `Terminal`
pub fn new() -> Self {
Default::default()
// let mut cpu = ;
// cpu.x[0xb] = 0x1020; // I don't know why but Linux boot seems to require this initialization
// cpu.write_csr_raw(CSR_MISA_ADDRESS, 0x800000008014312f);
// cpu
} }
/// Updates Program Counter content /// Updates Program Counter content
@ -324,7 +357,7 @@ impl Cpu {
Ok(inst) => { Ok(inst) => {
let result = (inst.operation)(self, word, instruction_address); let result = (inst.operation)(self, word, instruction_address);
self.x[0] = 0; // hardwired zero self.x[0] = 0; // hardwired zero
return result; result
} }
Err(()) => { Err(()) => {
panic!( panic!(
@ -332,7 +365,7 @@ impl Cpu {
instruction_address, original_word instruction_address, original_word
); );
} }
}; }
} }
/// Decodes a word instruction data and returns a reference to /// Decodes a word instruction data and returns a reference to
@ -341,7 +374,7 @@ impl Cpu {
/// The result will be stored to cache. /// The result will be stored to cache.
fn decode(&mut self, word: u32) -> Result<&Instruction, ()> { fn decode(&mut self, word: u32) -> Result<&Instruction, ()> {
match self.decode_cache.get(word) { match self.decode_cache.get(word) {
Some(index) => return Ok(&INSTRUCTIONS[index]), Some(index) => Ok(&INSTRUCTIONS[index]),
None => match self.decode_and_get_instruction_index(word) { None => match self.decode_and_get_instruction_index(word) {
Ok(index) => { Ok(index) => {
self.decode_cache.insert(word, index); self.decode_cache.insert(word, index);
@ -382,14 +415,16 @@ impl Cpu {
// @TODO: Optimize // @TODO: Optimize
let minterrupt = self.read_csr_raw(CSR_MIP_ADDRESS) & self.read_csr_raw(CSR_MIE_ADDRESS); let minterrupt = self.read_csr_raw(CSR_MIP_ADDRESS) & self.read_csr_raw(CSR_MIE_ADDRESS);
if (minterrupt & MIP_MEIP) != 0 && self.handle_trap( if (minterrupt & MIP_MEIP) != 0
&& self.handle_trap(
Trap { Trap {
trap_type: TrapType::MachineExternalInterrupt, trap_type: TrapType::MachineExternalInterrupt,
value: self.pc, // dummy value: self.pc, // dummy
}, },
instruction_address, instruction_address,
true, true,
) { )
{
// Who should clear mip bit? // Who should clear mip bit?
self.write_csr_raw( self.write_csr_raw(
CSR_MIP_ADDRESS, CSR_MIP_ADDRESS,
@ -398,14 +433,16 @@ impl Cpu {
self.wfi = false; self.wfi = false;
return; return;
} }
if (minterrupt & MIP_MSIP) != 0 && self.handle_trap( if (minterrupt & MIP_MSIP) != 0
&& self.handle_trap(
Trap { Trap {
trap_type: TrapType::MachineSoftwareInterrupt, trap_type: TrapType::MachineSoftwareInterrupt,
value: self.pc, // dummy value: self.pc, // dummy
}, },
instruction_address, instruction_address,
true, true,
) { )
{
self.write_csr_raw( self.write_csr_raw(
CSR_MIP_ADDRESS, CSR_MIP_ADDRESS,
self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_MSIP, self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_MSIP,
@ -413,14 +450,16 @@ impl Cpu {
self.wfi = false; self.wfi = false;
return; return;
} }
if (minterrupt & MIP_MTIP) != 0 && self.handle_trap( if (minterrupt & MIP_MTIP) != 0
&& self.handle_trap(
Trap { Trap {
trap_type: TrapType::MachineTimerInterrupt, trap_type: TrapType::MachineTimerInterrupt,
value: self.pc, // dummy value: self.pc, // dummy
}, },
instruction_address, instruction_address,
true, true,
) { )
{
self.write_csr_raw( self.write_csr_raw(
CSR_MIP_ADDRESS, CSR_MIP_ADDRESS,
self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_MTIP, self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_MTIP,
@ -428,14 +467,16 @@ impl Cpu {
self.wfi = false; self.wfi = false;
return; return;
} }
if (minterrupt & MIP_SEIP) != 0 && self.handle_trap( if (minterrupt & MIP_SEIP) != 0
&& self.handle_trap(
Trap { Trap {
trap_type: TrapType::SupervisorExternalInterrupt, trap_type: TrapType::SupervisorExternalInterrupt,
value: self.pc, // dummy value: self.pc, // dummy
}, },
instruction_address, instruction_address,
true, true,
) { )
{
self.write_csr_raw( self.write_csr_raw(
CSR_MIP_ADDRESS, CSR_MIP_ADDRESS,
self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_SEIP, self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_SEIP,
@ -443,14 +484,16 @@ impl Cpu {
self.wfi = false; self.wfi = false;
return; return;
} }
if (minterrupt & MIP_SSIP) != 0 && self.handle_trap( if (minterrupt & MIP_SSIP) != 0
&& self.handle_trap(
Trap { Trap {
trap_type: TrapType::SupervisorSoftwareInterrupt, trap_type: TrapType::SupervisorSoftwareInterrupt,
value: self.pc, // dummy value: self.pc, // dummy
}, },
instruction_address, instruction_address,
true, true,
) { )
{
self.write_csr_raw( self.write_csr_raw(
CSR_MIP_ADDRESS, CSR_MIP_ADDRESS,
self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_SSIP, self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_SSIP,
@ -458,14 +501,16 @@ impl Cpu {
self.wfi = false; self.wfi = false;
return; return;
} }
if (minterrupt & MIP_STIP) != 0 && self.handle_trap( if (minterrupt & MIP_STIP) != 0
&& self.handle_trap(
Trap { Trap {
trap_type: TrapType::SupervisorTimerInterrupt, trap_type: TrapType::SupervisorTimerInterrupt,
value: self.pc, // dummy value: self.pc, // dummy
}, },
instruction_address, instruction_address,
true, true,
) { )
{
self.write_csr_raw( self.write_csr_raw(
CSR_MIP_ADDRESS, CSR_MIP_ADDRESS,
self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_STIP, self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_STIP,

View File

@ -0,0 +1,5 @@
pub mod cpu;
pub mod memory;
pub mod mmu;
pub use cpu::{Cpu, CpuBuilder, Xlen};

View File

@ -4,7 +4,7 @@ pub const DRAM_BASE: u64 = 0x80000000;
use std::collections::HashMap; use std::collections::HashMap;
use crate::riscv::{ use crate::{
cpu::{get_privilege_mode, PrivilegeMode, Trap, TrapType, Xlen}, cpu::{get_privilege_mode, PrivilegeMode, Trap, TrapType, Xlen},
memory::Memory, memory::Memory,
}; };

View File

@ -1,5 +1,7 @@
mod riscv;
fn main() { fn main() {
let mut cpu = riscv_cpu::CpuBuilder::new()
.memory_size(64 * 1024 * 1024)
.xlen(riscv_cpu::Xlen::Bit32)
.build();
println!("Hello, world!"); println!("Hello, world!");
} }