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.
version = 3
[[package]]
name = "riscv-cpu"
version = "0.1.0"
[[package]]
name = "rouns"
version = "0.1.0"
dependencies = [
"riscv-cpu",
]

View File

@ -1,3 +1,5 @@
workspace = { members = ["crates/riscv-cpu"] }
[package]
name = "rouns"
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
[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 crate::riscv::mmu::{AddressingMode, Mmu};
// use terminal::Terminal;
use crate::mmu::{AddressingMode, Mmu};
const CSR_CAPACITY: usize = 4096;
@ -213,13 +209,39 @@ fn get_trap_cause(trap: &Trap, xlen: &Xlen) -> u64 {
}
}
impl Cpu {
/// Creates a new `Cpu`.
///
/// # Arguments
/// * `Terminal`
pub struct CpuBuilder {
xlen: Xlen,
memory_size: u64,
}
impl CpuBuilder {
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,
xlen: Xlen::Bit64,
privilege_mode: PrivilegeMode::Machine,
@ -234,10 +256,21 @@ impl Cpu {
_dump_flag: false,
decode_cache: DecodeCache::new(),
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
@ -324,7 +357,7 @@ impl Cpu {
Ok(inst) => {
let result = (inst.operation)(self, word, instruction_address);
self.x[0] = 0; // hardwired zero
return result;
result
}
Err(()) => {
panic!(
@ -332,7 +365,7 @@ impl Cpu {
instruction_address, original_word
);
}
};
}
}
/// Decodes a word instruction data and returns a reference to
@ -341,7 +374,7 @@ impl Cpu {
/// The result will be stored to cache.
fn decode(&mut self, word: u32) -> Result<&Instruction, ()> {
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) {
Ok(index) => {
self.decode_cache.insert(word, index);
@ -382,14 +415,16 @@ impl Cpu {
// @TODO: Optimize
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_type: TrapType::MachineExternalInterrupt,
value: self.pc, // dummy
},
instruction_address,
true,
) {
)
{
// Who should clear mip bit?
self.write_csr_raw(
CSR_MIP_ADDRESS,
@ -398,14 +433,16 @@ impl Cpu {
self.wfi = false;
return;
}
if (minterrupt & MIP_MSIP) != 0 && self.handle_trap(
if (minterrupt & MIP_MSIP) != 0
&& self.handle_trap(
Trap {
trap_type: TrapType::MachineSoftwareInterrupt,
value: self.pc, // dummy
},
instruction_address,
true,
) {
)
{
self.write_csr_raw(
CSR_MIP_ADDRESS,
self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_MSIP,
@ -413,14 +450,16 @@ impl Cpu {
self.wfi = false;
return;
}
if (minterrupt & MIP_MTIP) != 0 && self.handle_trap(
if (minterrupt & MIP_MTIP) != 0
&& self.handle_trap(
Trap {
trap_type: TrapType::MachineTimerInterrupt,
value: self.pc, // dummy
},
instruction_address,
true,
) {
)
{
self.write_csr_raw(
CSR_MIP_ADDRESS,
self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_MTIP,
@ -428,14 +467,16 @@ impl Cpu {
self.wfi = false;
return;
}
if (minterrupt & MIP_SEIP) != 0 && self.handle_trap(
if (minterrupt & MIP_SEIP) != 0
&& self.handle_trap(
Trap {
trap_type: TrapType::SupervisorExternalInterrupt,
value: self.pc, // dummy
},
instruction_address,
true,
) {
)
{
self.write_csr_raw(
CSR_MIP_ADDRESS,
self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_SEIP,
@ -443,14 +484,16 @@ impl Cpu {
self.wfi = false;
return;
}
if (minterrupt & MIP_SSIP) != 0 && self.handle_trap(
if (minterrupt & MIP_SSIP) != 0
&& self.handle_trap(
Trap {
trap_type: TrapType::SupervisorSoftwareInterrupt,
value: self.pc, // dummy
},
instruction_address,
true,
) {
)
{
self.write_csr_raw(
CSR_MIP_ADDRESS,
self.read_csr_raw(CSR_MIP_ADDRESS) & !MIP_SSIP,
@ -458,14 +501,16 @@ impl Cpu {
self.wfi = false;
return;
}
if (minterrupt & MIP_STIP) != 0 && self.handle_trap(
if (minterrupt & MIP_STIP) != 0
&& self.handle_trap(
Trap {
trap_type: TrapType::SupervisorTimerInterrupt,
value: self.pc, // dummy
},
instruction_address,
true,
) {
)
{
self.write_csr_raw(
CSR_MIP_ADDRESS,
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 crate::riscv::{
use crate::{
cpu::{get_privilege_mode, PrivilegeMode, Trap, TrapType, Xlen},
memory::Memory,
};

View File

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