Skip to content

Commit

Permalink
Refactor pc
Browse files Browse the repository at this point in the history
  • Loading branch information
Clo91eaf committed Mar 11, 2024
1 parent ea5329d commit dac08cd
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 942 deletions.
67 changes: 28 additions & 39 deletions src/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use ansi_term::Colour::{Green, Red};
use csr::*;
use instruction::BranchType as B;
use instruction::ImmediateType as I;
use instruction::Instruction as Insn;
use instruction::Inst;
use instruction::Instruction as Insn;
use instruction::JumpType as J;
use instruction::RegisterType as R;
use instruction::StoreType as S;
Expand All @@ -22,7 +22,7 @@ use memory::{read_data, read_inst, write_data};
use utils::{bits, sext};

#[derive(PartialEq, Debug)]
pub enum CpuState {
pub enum State {
Running,
// Stopped,
Ended,
Expand All @@ -45,10 +45,8 @@ pub struct Cpu {
pub gpr: [u64; 32],
pub csr: Csr,
pub pc: u64,
snpc: u64,
dnpc: u64,
inst: Inst,
pub state: CpuState,
pub state: State,
pub halt: Halt,
statistic: statistic::Statistic,
diff: Option<BufReader<std::fs::File>>,
Expand All @@ -65,34 +63,30 @@ impl Cpu {
gpr: [0; 32],
csr: Csr::new(),
pc: 0x80000000,
snpc: 0x80000000,
dnpc: 0x80000000,
inst: Inst::new(),
state: CpuState::Running,
state: State::Running,
halt: Halt::new(),
statistic: statistic::Statistic::new(),
diff,
}
}

fn hemu_trap(&mut self) {
self.state = CpuState::Ended;
self.state = State::Ended;
self.halt.pc = self.pc as u32;
self.halt.ret = self.gpr[10] as u32;

log::info!("hemu trap, pc = {:x}, ret = {}", self.pc, self.gpr[10]);
}

pub fn fetch(&mut self) {
let bits = read_inst(self.snpc) as u32;
let bits = read_inst(self.pc) as u32;
self.inst.set_bits(bits);
self.snpc += 4;
}

#[rustfmt::skip]
pub fn execute(&mut self) {
let (rd, rs1, rs2, imm) = (self.inst.rd, self.inst.rs1, self.inst.rs2, self.inst.imm);
self.dnpc = self.snpc;
let csr = bits(self.inst.bits, 20, 31) as u16;
match self.inst.typ {
Insn::Register(R::ADD) => {self.gpr[rd] = (self.gpr[rs1] as i64).wrapping_add(self.gpr[rs2] as i64) as u64;}
Expand Down Expand Up @@ -138,15 +132,15 @@ impl Cpu {
Insn::Store(S::SW) => {write_data((self.gpr[rs1] as i64).wrapping_add(imm) as u64, 4, self.gpr[rs2]);}
Insn::Store(S::SD) => {write_data((self.gpr[rs1] as i64).wrapping_add(imm) as u64, 8, self.gpr[rs2]);}

Insn::Branch(B::BEQ) => {if self.gpr[rs1] == self.gpr[rs2] {self.dnpc = (self.pc as i64).wrapping_add(imm) as u64;}}
Insn::Branch(B::BNE) => {if self.gpr[rs1] != self.gpr[rs2] {self.dnpc = (self.pc as i64).wrapping_add(imm) as u64;}}
Insn::Branch(B::BLT) => {if (self.gpr[rs1] as i64) < (self.gpr[rs2] as i64) {self.dnpc = (self.pc as i64).wrapping_add(imm) as u64;}}
Insn::Branch(B::BGE) => {if (self.gpr[rs1] as i64) >= (self.gpr[rs2] as i64) {self.dnpc = (self.pc as i64).wrapping_add(imm) as u64;}}
Insn::Branch(B::BLTU) => {if self.gpr[rs1] < self.gpr[rs2] {self.dnpc = (self.pc as i64).wrapping_add(imm) as u64;}}
Insn::Branch(B::BGEU) => {if self.gpr[rs1] >= self.gpr[rs2] {self.dnpc = (self.pc as i64).wrapping_add(imm) as u64;}}
Insn::Branch(B::BEQ) => {if self.gpr[rs1] == self.gpr[rs2] {self.pc = (self.pc as i64).wrapping_add(imm).wrapping_sub(4) as u64;}}
Insn::Branch(B::BNE) => {if self.gpr[rs1] != self.gpr[rs2] {self.pc = (self.pc as i64).wrapping_add(imm).wrapping_sub(4) as u64;}}
Insn::Branch(B::BLT) => {if (self.gpr[rs1] as i64) < (self.gpr[rs2] as i64) {self.pc = (self.pc as i64).wrapping_add(imm).wrapping_sub(4) as u64;}}
Insn::Branch(B::BGE) => {if (self.gpr[rs1] as i64) >= (self.gpr[rs2] as i64) {self.pc = (self.pc as i64).wrapping_add(imm).wrapping_sub(4) as u64;}}
Insn::Branch(B::BLTU) => {if self.gpr[rs1] < self.gpr[rs2] {self.pc = (self.pc as i64).wrapping_add(imm).wrapping_sub(4) as u64;}}
Insn::Branch(B::BGEU) => {if self.gpr[rs1] >= self.gpr[rs2] {self.pc = (self.pc as i64).wrapping_add(imm).wrapping_sub(4) as u64;}}

Insn::Jump(J::JAL) => {self.gpr[rd] = self.pc + 4; self.dnpc = (self.pc as i64).wrapping_add(imm) as u64;}
Insn::Immediate(I::JALR) => {self.gpr[rd] = self.pc + 4; self.dnpc = (self.gpr[rs1] as i64).wrapping_add(imm) as u64;}
Insn::Jump(J::JAL) => {self.gpr[rd] = self.pc + 4; self.pc = (self.pc as i64).wrapping_add(imm).wrapping_sub(4) as u64;}
Insn::Immediate(I::JALR) => {self.gpr[rd] = self.pc + 4; self.pc = (self.gpr[rs1] as i64).wrapping_add(imm).wrapping_sub(4) as u64;}

Insn::Upper(U::LUI) => {self.gpr[rd] = imm as u64;}
Insn::Upper(U::AUIPC) => {self.gpr[rd] = (self.pc as i64).wrapping_add(imm) as u64;}
Expand All @@ -165,7 +159,7 @@ impl Cpu {
Insn::Register(R::REMUW) => {self.gpr[rd] = sext((self.gpr[rs1] as u32 % self.gpr[rs2] as u32) as usize, 64);}
Insn::Register(R::REMW) => {self.gpr[rd] = sext((self.gpr[rs1] as i32 % self.gpr[rs2] as i32) as usize, 32);}

Insn::Register(R::MRET) => {self.dnpc = self.csr.read(MEPC).wrapping_add(4);}
Insn::Register(R::MRET) => {self.pc = self.csr.read(MEPC);}

Insn::Immediate(I::ECALL) => {todo!();}
Insn::Immediate(I::EBREAK) => {self.hemu_trap();}
Expand All @@ -184,29 +178,24 @@ impl Cpu {
}

fn exec_once(&mut self) {
// pipeline start
self.snpc = self.pc;
// fetch stage
self.fetch();
//disassemble
log::info!("{:08x}: {:08x}\t{}", self.pc, &self.inst.bits, self.inst.disassemble(self.pc));
let pc = self.pc;
// execute stage (including memory stage and write back stage)
self.execute();
// print disassemble
log::info!(
"{:08x}: {:08x}\t{}",
self.pc,
&self.inst.bits,
self.inst.disassemble(self.pc)
);
self.difftest().unwrap();
self.difftest(pc).unwrap();
// update pc
self.pc = self.dnpc;
self.pc += 4;
}

fn exec_ntimes(&mut self, n: usize) {
for _ in 0..n {
self.exec_once();
self.statistic.inc_count();
if self.state != CpuState::Running {
if self.state != State::Running {
break;
}
}
Expand All @@ -229,7 +218,7 @@ impl Cpu {
self.statistic.stop_timer(start_time);

match self.state {
CpuState::Ended => {
State::Ended => {
if self.halt.ret == 0 {
println!("{}", Green.bold().paint("HIT GOOD TRAP"));
self.statistic();
Expand All @@ -239,8 +228,8 @@ impl Cpu {
-1
}
}
CpuState::Running => 0,
CpuState::Quit => {
State::Running => 0,
State::Quit => {
self.statistic();
0
}
Expand All @@ -266,7 +255,7 @@ impl Cpu {
todo!("watch points not implemented!");
}

fn difftest(&mut self) -> anyhow::Result<()> {
fn difftest(&mut self, pc: u64) -> anyhow::Result<()> {
// get numbers from diff file
let mut line = String::new();

Expand All @@ -287,12 +276,12 @@ impl Cpu {
}

// difftest check
if numbers[0] != self.pc {
panic!("pc = {:x}, ref = {:x}", self.pc, numbers[0]);
if numbers[0] != pc {
panic!("pc = {:x}, ref = {:x}", pc, numbers[0]);
}
(0..32).for_each(|i| {
if numbers[i + 1] != self.gpr[i] {
panic!("x{:02} = {:x}, ref = {:x}", i, self.gpr[i], numbers[i + 1]);
panic!("pc = {:x}, x{:02} = {:x}, ref = {:x}", pc, i, self.gpr[i], numbers[i + 1]);
}
});

Expand Down
105 changes: 96 additions & 9 deletions src/cpu/instruction.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::cpu::utils;

use super::utils::{bits, sext};
use std::fmt;

#[derive(Copy, Clone, Debug)]
pub enum Instruction {
Expand Down Expand Up @@ -149,7 +146,7 @@ impl Inst {
rd: 0,
rs1: 0,
rs2: 0,
imm: 0
imm: 0,
}
}

Expand Down Expand Up @@ -179,7 +176,7 @@ impl Inst {
}

pub fn disassemble(&self, pc: u64) -> String {
utils::disassemble(self, pc)
disassemble(self, pc)
}

fn match_inst(&self, pattern: &str) -> bool {
Expand Down Expand Up @@ -217,10 +214,6 @@ impl InstPattern {
}
}

pub struct InstPatternTable {
pub patterns: Vec<InstPattern>,
}

#[rustfmt::skip]
pub fn new_ipt() -> Vec<InstPattern> {
vec![
Expand Down Expand Up @@ -321,3 +314,97 @@ pub fn new_ipt() -> Vec<InstPattern> {
InstPattern::new("??????? ????? ????? ??? ????? 01101 11", Instruction::Upper(UpperType::LUI)),
InstPattern::new("??????? ????? ????? ??? ????? 00101 11", Instruction::Upper(UpperType::AUIPC)),]
}

#[rustfmt::skip]
/// Decode operands from instruction
pub fn disassemble(inst: &Inst, pc: u64) -> String {
let (rd, rs1, rs2, imm) = (inst.rd, inst.rs1, inst.rs2, inst.imm);
let gpr = vec!["zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"];
match inst.typ {
Instruction::Register(RegisterType::ADD) => format!("add {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::ADDW) => format!("addw {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::SUB) => format!("sub {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::SUBW) => format!("subw {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::XOR) => format!("xor {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::OR) => format!("or {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::AND) => format!("and {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::SLL) => format!("sll {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::SLLW) => format!("sllw {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::SRL) => format!("srl {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::SRA) => format!("sra {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::SRLW) => format!("srlw {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::SRAW) => format!("sraw {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::SLT) => format!("slt {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::SLTU) => format!("sltu {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),

Instruction::Immediate(ImmediateType::ADDI) => format!("addi {}, {}, {}", gpr[rd], gpr[rs1], imm),
Instruction::Immediate(ImmediateType::ADDIW) => format!("addiw {}, {}, {}", gpr[rd], gpr[rs1], imm),
Instruction::Immediate(ImmediateType::XORI) => format!("xori {}, {}, {}", gpr[rd], gpr[rs1], imm),
Instruction::Immediate(ImmediateType::ORI) => format!("ori {}, {}, {}", gpr[rd], gpr[rs1], imm),
Instruction::Immediate(ImmediateType::ANDI) => format!("andi {}, {}, {}", gpr[rd], gpr[rs1], imm),
Instruction::Immediate(ImmediateType::SLLI) => format!("slli {}, {}, {}", gpr[rd], gpr[rs1], imm),
Instruction::Immediate(ImmediateType::SLLIW) => format!("slliw {}, {}, {}", gpr[rd], gpr[rs1], imm),
Instruction::Immediate(ImmediateType::SRLI) => format!("srli {}, {}, {}", gpr[rd], gpr[rs1], imm),
Instruction::Immediate(ImmediateType::SRLIW) => format!("srliw {}, {}, {}", gpr[rd], gpr[rs1], imm),
Instruction::Immediate(ImmediateType::SRAI) => format!("srai {}, {}, {}", gpr[rd], gpr[rs1], imm),
Instruction::Immediate(ImmediateType::SRAIW) => format!("sraiw {}, {}, {}", gpr[rd], gpr[rs1], imm),
Instruction::Immediate(ImmediateType::SLTI) => format!("slti {}, {}, {}", gpr[rd], gpr[rs1], imm),
Instruction::Immediate(ImmediateType::SLTIU) => format!("sltiu {}, {}, {}", gpr[rd], gpr[rs1], imm),

Instruction::Immediate(ImmediateType::LB) => format!("lb {}, {:x}({})", gpr[rd], imm, gpr[rs1]),
Instruction::Immediate(ImmediateType::LBU) => format!("lbu {}, {:x}({})", gpr[rd], imm, gpr[rs1]),
Instruction::Immediate(ImmediateType::LH) => format!("lh {}, {:x}({})", gpr[rd], imm, gpr[rs1]),
Instruction::Immediate(ImmediateType::LHU) => format!("lhu {}, {:x}({})", gpr[rd], imm, gpr[rs1]),
Instruction::Immediate(ImmediateType::LW) => format!("lw {}, {:x}({})", gpr[rd], imm, gpr[rs1]),
Instruction::Immediate(ImmediateType::LWU) => format!("lwu {}, {:x}({})", gpr[rd], imm, gpr[rs1]),
Instruction::Immediate(ImmediateType::LD) => format!("ld {}, {:x}({})", gpr[rd], imm, gpr[rs1]),

Instruction::Store(StoreType::SB) => format!("sb {}, {}({})", gpr[rs2], imm, gpr[rs1]),
Instruction::Store(StoreType::SH) => format!("sh {}, {}({})", gpr[rs2], imm, gpr[rs1]),
Instruction::Store(StoreType::SW) => format!("sw {}, {}({})", gpr[rs2], imm, gpr[rs1]),
Instruction::Store(StoreType::SD) => format!("sd {}, {}({})", gpr[rs2], imm, gpr[rs1]),

Instruction::Branch(BranchType::BEQ) => format!("beq {}, {}, {:x}", gpr[rs1], gpr[rs2], (pc as i64).wrapping_add(imm)),
Instruction::Branch(BranchType::BNE) => format!("bne {}, {}, {:x}", gpr[rs1], gpr[rs2], (pc as i64).wrapping_add(imm)),
Instruction::Branch(BranchType::BLT) => format!("blt {}, {}, {:x}", gpr[rs1], gpr[rs2], (pc as i64).wrapping_add(imm)),
Instruction::Branch(BranchType::BGE) => format!("bge {}, {}, {:x}", gpr[rs1], gpr[rs2], (pc as i64).wrapping_add(imm)),
Instruction::Branch(BranchType::BLTU) => format!("bltu {}, {}, {:x}", gpr[rs1], gpr[rs2], (pc as i64).wrapping_add(imm)),
Instruction::Branch(BranchType::BGEU) => format!("bgeu {}, {}, {:x}", gpr[rs1], gpr[rs2], (pc as i64).wrapping_add(imm)),

Instruction::Jump(JumpType::JAL) => format!("jal {}, {:x}", gpr[rd], (imm as u64).wrapping_add(pc)),
Instruction::Immediate(ImmediateType::JALR) => format!("jalr {}, {}, {:x}", gpr[rd], gpr[rs1], imm),

Instruction::Upper(UpperType::LUI) => format!("lui {}, {:x}", gpr[rd], imm),
Instruction::Upper(UpperType::AUIPC) => format!("auipc {}, {:x}", gpr[rd], (pc as i64).wrapping_add(imm)),

Instruction::Register(RegisterType::MUL) => format!("mul {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::MULH) => format!("mulh {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::MULHU) => format!("mulhu {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::MULHSU) => format!("mulhsu {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::MULW) => format!("mulw {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::DIV) => format!("div {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::DIVU) => format!("divu {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::DIVUW) => format!("divuw {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::DIVW) => format!("divw {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::REM) => format!("rem {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::REMU) => format!("remu {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::REMUW) => format!("remuw {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),
Instruction::Register(RegisterType::REMW) => format!("remw {}, {}, {}", gpr[rd], gpr[rs1], gpr[rs2]),

Instruction::Register(RegisterType::MRET) => format!("mret"),

Instruction::Immediate(ImmediateType::ECALL) => format!("ecall"),
Instruction::Immediate(ImmediateType::EBREAK) => format!("ebreak"),

Instruction::Immediate(ImmediateType::FENCE) => format!("fence"),

Instruction::Immediate(ImmediateType::CSRRW) => format!("csrrw {}, {}", gpr[rd], gpr[rs1]),
Instruction::Immediate(ImmediateType::CSRRS) => format!("csrrs {}, {}", gpr[rd], gpr[rs1]),
Instruction::Immediate(ImmediateType::CSRRC) => format!("csrrc {}, {}", gpr[rd], gpr[rs1]),
Instruction::Immediate(ImmediateType::CSRRWI) => format!("csrrwi {}, 0x{:x}, {}", gpr[rd], imm, rs1),
Instruction::Immediate(ImmediateType::CSRRSI) => format!("csrrsi {}, 0x{:x}, {}", gpr[rd], imm, rs1),
Instruction::Immediate(ImmediateType::CSRRCI) => format!("csrrci {}, 0x{:x}, {}", gpr[rd], imm, rs1),

_ => format!("Unknown instruction")
}
}
Loading

0 comments on commit dac08cd

Please sign in to comment.