diff options
Diffstat (limited to 'src/simulator.rs')
-rw-r--r-- | src/simulator.rs | 444 |
1 files changed, 221 insertions, 223 deletions
diff --git a/src/simulator.rs b/src/simulator.rs index be47764..27e543a 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -18,8 +18,7 @@ use std::cell::RefCell; use std::rc::Rc; use isa; -use binary::{Binary}; -use memory::{MemoryInterface, Memory, MemoryError}; +use memory::{MemoryInterface, MemoryError}; struct RegisterFile { registers: [isa::Word; 32], @@ -76,260 +75,254 @@ impl RegisterFile { } impl<'a> Core<'a> { + // TODO: take Rc<RefCell<>> to Memory as well? pub fn new(cache: Rc<RefCell<Box<MemoryInterface + 'a>>>) -> Core<'a> { Core { - pc: 0, // TODO: hardcoded: fix later + pc: 0x1002c, // TODO: hardcoded: fix later registers: RegisterFile::new(), running: true, cache: cache, } } - fn step(&mut self, inst: Option<isa::Instruction>) { + fn step(&mut self, inst: isa::Instruction) { let pc = self.pc; - if let Some(inst) = inst { - match inst.opcode() { - isa::opcodes::JALR => { - // TODO: assert funct3 is 0 - let base = self.registers.read_word(inst.rs1()) - as isa::SignedWord; - let target = (base + inst.i_imm()) as isa::Address; - let retval = (pc + 4) as isa::Word; - if target == 0x0 { - // ret - self.running = false; - } - else { - self.registers.write_word(inst.rd(), retval); - self.pc = target; - return; + match inst.opcode() { + isa::opcodes::JALR => { + // TODO: assert funct3 is 0 + let base = self.registers.read_word(inst.rs1()) + as isa::SignedWord; + let target = (base + inst.i_imm()) as isa::Address; + let retval = (pc + 4) as isa::Word; + if target == 0x0 { + // ret + self.running = false; + } + else { + self.registers.write_word(inst.rd(), retval); + self.pc = target; + return; + } + }, + isa::opcodes::JAL => { + let target = ((pc as isa::SignedWord) + inst.uj_imm()) as isa::Address; + self.registers.write_word(inst.rd(), (pc + 4) as isa::Word); + self.pc = target; + // panic!("JAL to {:X} 0x{:X}", pc, target); + return; + } + isa::opcodes::BRANCH => { + let target = ((pc as isa::SignedWord) + inst.sb_imm()) as isa::Address; + let rs1 = self.registers.read_word(inst.rs1()); + let rs2 = self.registers.read_word(inst.rs2()); + if match inst.funct3() { + isa::funct3::BEQ => rs1 == rs2, + isa::funct3::BNE => rs1 != rs2, + isa::funct3::BLT => (rs1 as isa::SignedWord) < (rs2 as isa::SignedWord), + isa::funct3::BGE => (rs1 as isa::SignedWord) > (rs2 as isa::SignedWord), + isa::funct3::BLTU => rs1 < rs2, + isa::funct3::BGEU => rs1 > rs2, + _ => { + self.trap(Trap::IllegalInstruction { + address: pc, + instruction: inst, + }); + false } - }, - isa::opcodes::JAL => { - let target = ((pc as isa::SignedWord) + inst.uj_imm()) as isa::Address; - self.registers.write_word(inst.rd(), (pc + 4) as isa::Word); + } { self.pc = target; - // panic!("JAL to {:X} 0x{:X}", pc, target); return; } - isa::opcodes::BRANCH => { - let target = ((pc as isa::SignedWord) + inst.sb_imm()) as isa::Address; - let rs1 = self.registers.read_word(inst.rs1()); - let rs2 = self.registers.read_word(inst.rs2()); - if match inst.funct3() { - isa::funct3::BEQ => rs1 == rs2, - isa::funct3::BNE => rs1 != rs2, - isa::funct3::BLT => (rs1 as isa::SignedWord) < (rs2 as isa::SignedWord), - isa::funct3::BGE => (rs1 as isa::SignedWord) > (rs2 as isa::SignedWord), - isa::funct3::BLTU => rs1 < rs2, - isa::funct3::BGEU => rs1 > rs2, - _ => { - self.trap(Trap::IllegalInstruction { - address: pc, - instruction: inst, - }); - false + }, + isa::opcodes::INTEGER_IMMEDIATE => { + let imm = inst.i_imm(); + let src = self.registers.read_word(inst.rs1()) as isa::SignedWord; + if let Some(value) = match inst.funct3() { + isa::funct3::ADDI => { + Some(src.wrapping_add(imm) as isa::Word) + }, + isa::funct3::SLLI => { + Some((src << inst.shamt()) as isa::Word) + }, + isa::funct3::SLTI => { + if src < imm { + Some(1) } - } { - self.pc = target; - return; - } - }, - isa::opcodes::INTEGER_IMMEDIATE => { - let imm = inst.i_imm(); - let src = self.registers.read_word(inst.rs1()) as isa::SignedWord; - if let Some(value) = match inst.funct3() { - isa::funct3::ADDI => { - Some(src.wrapping_add(imm) as isa::Word) - }, - isa::funct3::SLLI => { - Some((src << inst.shamt()) as isa::Word) - }, - isa::funct3::SLTI => { - if src < imm { - Some(1) - } - else { - Some(0) - } - }, - isa::funct3::SLTIU => { - if (src as isa::Word) < (imm as isa::Word) { - Some(1) - } - else { - Some(0) - } - }, - isa::funct3::XORI => { - Some((src ^ imm) as isa::Word) - }, - isa::funct3::SRLI_SRAI => { - match inst.funct7() { - isa::funct7::SRLI => Some(((src as isa::Word) >> inst.shamt()) as isa::Word), - isa::funct7::SRAI => Some((src >> inst.shamt()) as isa::Word), - _ => { - self.trap(Trap::IllegalInstruction { - address: pc, - instruction: inst, - }); - None - } + else { + Some(0) + } + }, + isa::funct3::SLTIU => { + if (src as isa::Word) < (imm as isa::Word) { + Some(1) + } + else { + Some(0) + } + }, + isa::funct3::XORI => { + Some((src ^ imm) as isa::Word) + }, + isa::funct3::SRLI_SRAI => { + match inst.funct7() { + isa::funct7::SRLI => Some(((src as isa::Word) >> inst.shamt()) as isa::Word), + isa::funct7::SRAI => Some((src >> inst.shamt()) as isa::Word), + _ => { + self.trap(Trap::IllegalInstruction { + address: pc, + instruction: inst, + }); + None } - }, - isa::funct3::ORI => { - Some((src | imm) as isa::Word) - }, - isa::funct3::ANDI => { - Some((src & imm) as isa::Word) - }, - _ => { - self.trap(Trap::IllegalInstruction { - address: pc, - instruction: inst, - }); - None } - } { - self.registers.write_word(inst.rd(), value); + }, + isa::funct3::ORI => { + Some((src | imm) as isa::Word) + }, + isa::funct3::ANDI => { + Some((src & imm) as isa::Word) + }, + _ => { + self.trap(Trap::IllegalInstruction { + address: pc, + instruction: inst, + }); + None } - }, - isa::opcodes::INTEGER_REGISTER => { - let src1 = self.registers.read_word(inst.rs1()); - let src2 = self.registers.read_word(inst.rs2()); - let src2_shift = src2 & 0x1F; - if let Some(value) = match inst.funct3() { - isa::funct3::ADD_SUB => { - match inst.funct7() { - isa::funct7::ADD_SRL => Some(((src1 as isa::SignedWord).wrapping_add(src2 as isa::SignedWord)) as isa::Word), - isa::funct7::SUB_SRA => Some(((src1 as isa::SignedWord).wrapping_sub(src2 as isa::SignedWord)) as isa::Word), - _ => { - self.trap(Trap::IllegalInstruction { - address: pc, - instruction: inst, - }); - None - } - } - }, - isa::funct3::SLL => { - Some(src1 << src2_shift) - }, - isa::funct3::SLT => { - if (src1 as isa::SignedWord) < (src2 as isa::SignedWord) { - Some(1) - } - else { - Some(0) - } - }, - isa::funct3::SLTU => { - if src1 < src2 { - Some(1) - } - else { - Some(0) - } - }, - isa::funct3::XOR => { - Some(src1 ^ src2) - }, - isa::funct3::SRL_SRA => { - match inst.funct7() { - isa::funct7::ADD_SRL => Some(src1 >> src2_shift), - isa::funct7::SUB_SRA => Some(((src1 as isa::SignedWord) >> src2_shift) as isa::Word), - _ => { - self.trap(Trap::IllegalInstruction { - address: pc, - instruction: inst, - }); - None - } + } { + self.registers.write_word(inst.rd(), value); + } + }, + isa::opcodes::INTEGER_REGISTER => { + let src1 = self.registers.read_word(inst.rs1()); + let src2 = self.registers.read_word(inst.rs2()); + let src2_shift = src2 & 0x1F; + if let Some(value) = match inst.funct3() { + isa::funct3::ADD_SUB => { + match inst.funct7() { + isa::funct7::ADD_SRL => Some(((src1 as isa::SignedWord).wrapping_add(src2 as isa::SignedWord)) as isa::Word), + isa::funct7::SUB_SRA => Some(((src1 as isa::SignedWord).wrapping_sub(src2 as isa::SignedWord)) as isa::Word), + _ => { + self.trap(Trap::IllegalInstruction { + address: pc, + instruction: inst, + }); + None } - }, - isa::funct3::OR => { - Some(src1 | src2) - }, - isa::funct3::AND => { - Some(src1 & src2) - }, - _ => { - self.trap(Trap::IllegalInstruction { - address: pc, - instruction: inst, - }); - None } - } { - self.registers.write_word(inst.rd(), value); - } - }, - isa::opcodes::LOAD => match inst.funct3() { - isa::funct3::LW => { - let imm = inst.i_imm(); - let base = self.registers.read_word(inst.rs1()); - let address = ((base as isa::SignedWord) + imm) as isa::Address; - let result = self.cache.borrow_mut().read_word(address); - match result { - Ok(value) => - self.registers.write_word(inst.rd(), value), - Err(MemoryError::CacheMiss {..}) => return, - Err(MemoryError::InvalidAddress) => { - self.trap(Trap::IllegalRead { + }, + isa::funct3::SLL => { + Some(src1 << src2_shift) + }, + isa::funct3::SLT => { + if (src1 as isa::SignedWord) < (src2 as isa::SignedWord) { + Some(1) + } + else { + Some(0) + } + }, + isa::funct3::SLTU => { + if src1 < src2 { + Some(1) + } + else { + Some(0) + } + }, + isa::funct3::XOR => { + Some(src1 ^ src2) + }, + isa::funct3::SRL_SRA => { + match inst.funct7() { + isa::funct7::ADD_SRL => Some(src1 >> src2_shift), + isa::funct7::SUB_SRA => Some(((src1 as isa::SignedWord) >> src2_shift) as isa::Word), + _ => { + self.trap(Trap::IllegalInstruction { address: pc, instruction: inst, - memory_address: address, }); + None } } }, + isa::funct3::OR => { + Some(src1 | src2) + }, + isa::funct3::AND => { + Some(src1 & src2) + }, _ => { - panic!("Invalid load funct3code: 0x{:x}", inst.funct3()); - } - }, - isa::opcodes::STORE => match inst.funct3() { - isa::funct3::SW => { - let imm = inst.s_imm(); - let base = self.registers.read_word(inst.rs1()); - let val = self.registers.read_word(inst.rs2()); - let address = ((base as isa::SignedWord) + imm) as isa::Address; - let result = self.cache.borrow_mut().write_word(address, val); - match result { - Ok(()) => (), - Err(MemoryError::CacheMiss {..}) => return, - Err(MemoryError::InvalidAddress) => { - self.trap(Trap::IllegalWrite { - address: pc, - instruction: inst, - memory_address: address, - memory_value: val, - }) - } - } + self.trap(Trap::IllegalInstruction { + address: pc, + instruction: inst, + }); + None } - _ => { - panic!("Invalid store funct3code: 0x{:x}", inst.funct3()); + } { + self.registers.write_word(inst.rd(), value); + } + }, + isa::opcodes::LOAD => match inst.funct3() { + isa::funct3::LW => { + let imm = inst.i_imm(); + let base = self.registers.read_word(inst.rs1()); + let address = ((base as isa::SignedWord) + imm) as isa::Address; + let result = self.cache.borrow_mut().read_word(address); + match result { + Ok(value) => + self.registers.write_word(inst.rd(), value), + Err(MemoryError::CacheMiss {..}) => return, + Err(MemoryError::InvalidAddress) => { + self.trap(Trap::IllegalRead { + address: pc, + instruction: inst, + memory_address: address, + }); + } } }, - isa::opcodes::SYSTEM => match inst.i_imm() { - 0x0 => { - // System call - println!("System call {}:", self.registers.read_word(isa::Register::X10)); - let address = self.registers.read_word(isa::Register::X11); - println!("Argument {:X}: {:?}", address, self.cache.borrow_mut().read_word(address)); - } - _ => { - + _ => { + panic!("Invalid load funct3code: 0x{:x}", inst.funct3()); + } + }, + isa::opcodes::STORE => match inst.funct3() { + isa::funct3::SW => { + let imm = inst.s_imm(); + let base = self.registers.read_word(inst.rs1()); + let val = self.registers.read_word(inst.rs2()); + let address = ((base as isa::SignedWord) + imm) as isa::Address; + let result = self.cache.borrow_mut().write_word(address, val); + match result { + Ok(()) => (), + Err(MemoryError::CacheMiss {..}) => return, + Err(MemoryError::InvalidAddress) => { + self.trap(Trap::IllegalWrite { + address: pc, + instruction: inst, + memory_address: address, + memory_value: val, + }) + } } - }, + } _ => { - panic!("Invalid opcode: 0x{:02X} at PC 0x{:X}", inst.opcode(), pc); + panic!("Invalid store funct3code: 0x{:x}", inst.funct3()); + } + }, + isa::opcodes::SYSTEM => match inst.i_imm() { + 0x0 => { + // System call + println!("System call {}:", self.registers.read_word(isa::Register::X10)); } + _ => { + + } + }, + _ => { + panic!("Invalid opcode: 0x{:02X} at PC 0x{:X}", inst.opcode(), pc); } } - else { - // trap - } self.pc += 4; } @@ -363,7 +356,12 @@ impl<'a> Simulator<'a> { continue; } let inst = self.memory.borrow_mut().read_instruction(core.pc); - core.step(inst); + if let Some(inst) = inst { + core.step(inst); + } + else { + // TODO: trap + } ran = true; } if !ran { |