diff --git a/Cargo.lock b/Cargo.lock index 8d83466..6b92449 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", +] diff --git a/Cargo.toml b/Cargo.toml index 4a52e92..648c20a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" } diff --git a/crates/riscv-cpu/Cargo.toml b/crates/riscv-cpu/Cargo.toml new file mode 100644 index 0000000..3af4735 --- /dev/null +++ b/crates/riscv-cpu/Cargo.toml @@ -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] diff --git a/src/riscv/cpu.rs b/crates/riscv-cpu/src/cpu.rs similarity index 98% rename from src/riscv/cpu.rs rename to crates/riscv-cpu/src/cpu.rs index ab3ac45..fe6d413 100644 --- a/src/riscv/cpu.rs +++ b/crates/riscv-cpu/src/cpu.rs @@ -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, diff --git a/crates/riscv-cpu/src/lib.rs b/crates/riscv-cpu/src/lib.rs new file mode 100644 index 0000000..e886bff --- /dev/null +++ b/crates/riscv-cpu/src/lib.rs @@ -0,0 +1,5 @@ +pub mod cpu; +pub mod memory; +pub mod mmu; + +pub use cpu::{Cpu, CpuBuilder, Xlen}; diff --git a/src/riscv/memory.rs b/crates/riscv-cpu/src/memory.rs similarity index 100% rename from src/riscv/memory.rs rename to crates/riscv-cpu/src/memory.rs diff --git a/src/riscv/mmu.rs b/crates/riscv-cpu/src/mmu.rs similarity index 99% rename from src/riscv/mmu.rs rename to crates/riscv-cpu/src/mmu.rs index aae8952..018e9cf 100644 --- a/src/riscv/mmu.rs +++ b/crates/riscv-cpu/src/mmu.rs @@ -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, }; diff --git a/src/riscv/mod.rs b/crates/riscv-cpu/src/mod.rs similarity index 100% rename from src/riscv/mod.rs rename to crates/riscv-cpu/src/mod.rs diff --git a/src/main.rs b/src/main.rs index 149a9cc..01e37eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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!"); }