From c1e8b6b7aae5549c003818b258c52b55c2926e2a Mon Sep 17 00:00:00 2001 From: Minseong Jang Date: Mon, 16 Sep 2024 15:42:04 +0900 Subject: [PATCH] Update baseline CPU --- hazardflow-designs/src/cpu/alu.rs | 5 +- hazardflow-designs/src/cpu/csr.rs | 40 ++--- hazardflow-designs/src/cpu/decode.rs | 50 +++--- hazardflow-designs/src/cpu/exe.rs | 57 ++++--- hazardflow-designs/src/cpu/mem.rs | 92 ++++------ hazardflow-designs/src/cpu/mem_interface.rs | 7 - hazardflow-designs/src/cpu/multiplier.rs | 17 +- hazardflow-designs/src/cpu/riscv32_5stage.rs | 2 +- hazardflow-designs/src/cpu/riscv_isa.rs | 167 +++++++++---------- hazardflow-designs/src/cpu/wb.rs | 8 +- 10 files changed, 189 insertions(+), 256 deletions(-) diff --git a/hazardflow-designs/src/cpu/alu.rs b/hazardflow-designs/src/cpu/alu.rs index 4074438..7236cc2 100644 --- a/hazardflow-designs/src/cpu/alu.rs +++ b/hazardflow-designs/src/cpu/alu.rs @@ -2,8 +2,7 @@ use super::*; -/// Alu Input -/// Belongs to DecodeEP, and this will be used to determine what to operate with what value. +/// ALU input. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct AluInput { /// Operator. @@ -70,7 +69,7 @@ pub enum BaseAluOp { /// Execute alu pub fn exe_alu(alu_op1: u32, alu_op2: u32, op: BaseAluOp) -> u32 { - let alu_shamt = alu_op2 & 0x1f; // TODO: Use `I<5>` instead of `u32`. + let alu_shamt = alu_op2 & 0x1f; match op { BaseAluOp::Add => alu_op1 + alu_op2, diff --git a/hazardflow-designs/src/cpu/csr.rs b/hazardflow-designs/src/cpu/csr.rs index 46aba54..196d8a7 100644 --- a/hazardflow-designs/src/cpu/csr.rs +++ b/hazardflow-designs/src/cpu/csr.rs @@ -4,6 +4,8 @@ //! //! - Constants: +#![allow(missing_docs)] + use super::*; /// Contains information that is needed to interact with CSR. @@ -22,47 +24,42 @@ pub struct CsrInfo { /// - #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum CsrCmd { - /// TODO: Documentation - R = 5, - /// TODO: Documentation + W = 1, S = 2, - /// TODO: Documentation C = 3, - /// TODO: Documentation - W = 1, - /// TODO: Documentation I = 4, + R = 5, } -/// TODO: Documentation, Add remaining fields +/// CSR request. #[derive(Debug, Clone, Copy)] pub struct CsrReq { - /// TODO: Documentation + /// CSR command. pub cmd: CsrCmd, - /// TODO: Documentation + /// Write data. pub wdata: u32, - /// TODO: Documentation + /// CSR register. pub decode: U, - /// TODO: Documentation + /// Exception happened? pub exception: bool, - /// TODO: Documentation + /// PC. pub pc: u32, } -/// TODO: Documentation +/// CSR response. #[derive(Debug, Clone, Copy)] pub struct CsrResp { - /// TODO: Documentation + /// Read data. pub rdata: u32, - /// TODO: Documentation + /// Returning from exception? pub eret: bool, - /// TODO: Documentation + /// Redirected PC when returning from exception. pub evec: u32, } @@ -255,12 +252,11 @@ pub fn csr(i: Valid) -> Valid { }) } -/// TODO: Documentation pub fn csr_wrap( - i: I, WbR)>, { Dep::Helpful }>, -) -> I, WbR)>, { Dep::Helpful }> { + i: I>, { Dep::Helpful }>, +) -> I>, { Dep::Helpful }> { let (i1, i2) = unsafe { - Interface::fsm::<(Valid, I, WbR)>, { Dep::Helpful }>), ()>( + Interface::fsm::<(Valid, I>, { Dep::Helpful }>), ()>( i, (), |ip, er, s| { @@ -275,7 +271,7 @@ pub fn csr_wrap( let e1 = i1.comb(csr); unsafe { - (e1, i2).fsm::, WbR)>, { Dep::Helpful }>, ()>( + (e1, i2).fsm::>, { Dep::Helpful }>, ()>( (), |(ip1, ip2), er, s| { let ep = ip1.zip(ip2); diff --git a/hazardflow-designs/src/cpu/decode.rs b/hazardflow-designs/src/cpu/decode.rs index 289ce4d..fac994a 100644 --- a/hazardflow-designs/src/cpu/decode.rs +++ b/hazardflow-designs/src/cpu/decode.rs @@ -5,37 +5,30 @@ use super::*; /// Payload from decode stage to execute stage. #[derive(Debug, Clone, Copy)] pub struct DecEP { - /// Writeback. + /// Writeback information. /// /// It contains the writeback address and selector. - pub wb: HOption<(U<{ clog2(REGS) }>, WbSel)>, + pub wb_info: HOption<(U<{ clog2(REGS) }>, WbSel)>, - /// Store data. - /// - /// The `SW`, `SH`, and `SB` instructions store 32-bit, 16-bit, and 8-bit values from the low bits of `rs2` to memory. - pub st_data: HOption, - - /// Branch type. - pub br_type: BranchType, - - /// Jump target. - /// - /// It contains the base address and offset. - pub jmp_target: (u32, u32), + /// Branch information. + pub br_info: HOption, /// ALU input. pub alu_input: AluInput, - /// Memory operation. - pub mem_op: MemOp, + /// Memory information. + pub mem_info: HOption, + + /// CSR information. + pub csr_info: HOption, - /// Indicates that the instruction is illegal/unsupported or not. + /// Indicates that the instruction is illegal or not. pub is_illegal: bool, /// PC. pub pc: u32, - /// Instruciton (To calculate CPI) + /// Instruction (for debugging purpose). pub debug_inst: u32, } @@ -109,21 +102,18 @@ fn gen_payload(ip: FetEP, inst: Instruction, er: ExeR) -> HOption { AluInput { op: inst.alu_op, op1_data, op2_data } }; - let jmp_target = inst.jmp_target(rs1, ip.imem_resp.addr); + let br_info = inst.br_info(rs1, ip.imem_resp.addr); Some(DecEP { - wb: inst.rd_addr.zip(inst.wb_sel), - st_data: rs2.map(|rs2| rs2.data), - br_type: inst.br_type, - jmp_target, + wb_info: inst.rd_addr.zip(inst.wb_sel), + br_info, alu_input, - mem_op: if let Some((fcn, typ)) = inst.mem_info { - MemOp::Dmem { fcn, typ } - } else if let Some(csr_info) = inst.csr_info { - MemOp::Csr(csr_info) - } else { - MemOp::None - }, + mem_info: inst.mem_info.map(|(fcn, typ)| MemInfo { + fcn, + typ, + data: rs2.map(|r| r.data).unwrap_or(unsafe { x() }), + }), + csr_info: inst.csr_info, is_illegal: inst.is_illegal, pc: ip.imem_resp.addr, debug_inst: ip.imem_resp.data, diff --git a/hazardflow-designs/src/cpu/exe.rs b/hazardflow-designs/src/cpu/exe.rs index 40e0fc8..26f5cdc 100644 --- a/hazardflow-designs/src/cpu/exe.rs +++ b/hazardflow-designs/src/cpu/exe.rs @@ -5,29 +5,27 @@ use super::*; /// Payload from execute stage to memory stage. #[derive(Debug, Clone, Copy)] pub struct ExeEP { - /// Writeback. + /// Writeback information. /// /// It contains the writeback address and selector. - pub wb: HOption<(U<{ clog2(REGS) }>, WbSel)>, + pub wb_info: HOption<(U<{ clog2(REGS) }>, WbSel)>, /// ALU output. pub alu_out: u32, - /// Memory operation. - pub mem_op: MemOp, + /// Memory information. + pub mem_info: HOption, - /// Store data. - /// - /// The `SW`, `SH`, and `SB` instructions store 32-bit, 16-bit, and 8-bit values from the low bits of `rs2` to memory. - pub st_data: HOption, + /// CSR information. + pub csr_info: HOption, - /// Indicates that exception happened or not. - pub exception: bool, + /// Indicates that the instruction is illegal or not. + pub is_illegal: bool, /// PC. pub pc: u32, - /// Instruciton (To calculate CPI) + /// Instruction (for debugging purpose). pub debug_inst: u32, } @@ -76,26 +74,23 @@ impl ExeR { /// Returns redirected PC based on the given payload. fn get_redirect(p: DecEP, alu_out: u32) -> HOption { - let target = p.jmp_target.0 + p.jmp_target.1; + let Some(br_info) = p.br_info else { + return None; + }; + let target = br_info.base + br_info.offset; let alu_true = alu_out != 0; - match p.br_type { - BranchType::N => None, - BranchType::J => { - // From J-instruction - Some(target) - } - BranchType::Eq | BranchType::Ge | BranchType::Geu => { - // From Br-instruction + match br_info.typ { + BrType::Jal | BrType::Jalr => Some(target), + BrType::Beq | BrType::Bge | BrType::Bgeu => { if !alu_true { Some(target) } else { None } } - BranchType::Ne | BranchType::Lt | BranchType::Ltu => { - // From Br-instruction + BrType::Bne | BrType::Blt | BrType::Bltu => { if alu_true { Some(target) } else { @@ -110,17 +105,21 @@ fn gen_resolver(er: (HOption<(DecEP, u32)>, MemR)) -> ExeR { let (p, memr) = er; let stall = p.and_then(|(p, _)| { - p.wb.and_then(|(addr, wb_sel)| if matches!(wb_sel, WbSel::Mem | WbSel::Csr) { Some(addr) } else { None }) + p.wb_info.and_then(|(addr, wb_sel)| if matches!(wb_sel, WbSel::Mem | WbSel::Csr) { Some(addr) } else { None }) }); let Some((p, alu_out)) = p else { return ExeR::new(memr, None, stall, None); }; + let bypass = + p.wb_info.and_then( + |(addr, wb_sel)| if matches!(wb_sel, WbSel::Alu) { Some(Register::new(addr, alu_out)) } else { None }, + ); + let redirect = get_redirect(p, alu_out); - let exer_wb = p.wb.map(|(addr, _)| Register::new(addr, alu_out)); - ExeR::new(memr, exer_wb, stall, redirect) + ExeR::new(memr, bypass, stall, redirect) } /// Generates payload from execute stage to memory stage. @@ -130,10 +129,10 @@ fn gen_payload(ip: DecEP, alu_out: u32, memr: MemR) -> HOption { } else { Some(ExeEP { alu_out, - wb: ip.wb, - mem_op: ip.mem_op, - st_data: ip.st_data, - exception: ip.is_illegal, + wb_info: ip.wb_info, + mem_info: ip.mem_info, + csr_info: ip.csr_info, + is_illegal: ip.is_illegal, pc: ip.pc, debug_inst: ip.debug_inst, }) diff --git a/hazardflow-designs/src/cpu/mem.rs b/hazardflow-designs/src/cpu/mem.rs index 99e6cf0..9f31e4a 100644 --- a/hazardflow-designs/src/cpu/mem.rs +++ b/hazardflow-designs/src/cpu/mem.rs @@ -2,55 +2,33 @@ use super::*; -/// Operation at memory stage. +/// Memory access information. #[derive(Debug, Clone, Copy)] -pub enum MemOp { - /// Access DMEM. - Dmem { - /// Function (load or store) - fcn: MemOpFcn, +pub struct MemInfo { + /// Function (load or store). + pub fcn: MemOpFcn, - /// Operand type - typ: MemOpTyp, - }, + /// Operand type. + pub typ: MemOpTyp, - /// Access CSR. - Csr(CsrInfo), - - /// Do nothing. - None, -} - -impl MemOp { - /// Returns DMEM access. - pub fn dmem(self) -> HOption<(MemOpFcn, MemOpTyp)> { - match self { - MemOp::Dmem { fcn, typ } => Some((fcn, typ)), - _ => None, - } - } - - /// Returns CSR access. - pub fn csr(self) -> HOption { - match self { - MemOp::Csr(csr_info) => Some(csr_info), - _ => None, - } - } + /// Store data. + /// + /// Used for S-type instructions (`sw`, `sh`, `sb`). + pub data: u32, } /// Payload from memory stage to writeback stage. #[derive(Debug, Clone, Copy)] pub struct MemEP { - /// Writeback. + /// Writeback information. /// /// It contains the writeback address and data. - pub wb: HOption, + pub wb_info: HOption, - /// PC (To calculate CPI) + /// PC (for debugging purpose). pub debug_pc: u32, - /// Instruciton (To calculate CPI) + /// Instruction (for debugging purpose). pub debug_inst: u32, } @@ -78,11 +56,10 @@ impl MemR { } fn get_wb(p: ExeEP, dmem_resp: HOption, csr_resp: HOption) -> HOption { - p.wb.map(|(addr, wb_sel)| { + p.wb_info.map(|(addr, wb_sel)| { let data = match wb_sel { WbSel::Alu => p.alu_out, WbSel::Mem => dmem_resp.unwrap().data, - WbSel::Pc4 => p.pc + 4, WbSel::Csr => csr_resp.unwrap().rdata, }; @@ -90,16 +67,15 @@ fn get_wb(p: ExeEP, dmem_resp: HOption, csr_resp: HOption, (HOption<(CsrResp, ExeEP)>, WbR), HOption)) -> MemR { +fn gen_resolver(er: (HOption<(MemRespWithAddr, ExeEP)>, HOption<(CsrResp, ExeEP)>, (HOption, WbR))) -> MemR { // Extracts resolver from each branch. - let (er_dmem, er_csr, er_none) = er; + let (er_dmem, er_csr, (er_none, wbr)) = er; let dmem_resp = er_dmem.map(|(r, _)| r); - let csr_resp = er_csr.0.map(|(r, _)| r); - let exep = er_dmem.map(|(_, r)| r).or(er_csr.0.map(|(_, r)| r)).or(er_none); - let wbr = er_csr.1; + let csr_resp = er_csr.map(|(r, _)| r); + let exep = er_dmem.map(|(_, r)| r).or(er_csr.map(|(_, r)| r)).or(er_none); - let exception = exep.is_some_and(|p| p.exception); + let exception = exep.is_some_and(|p| p.is_illegal); let bypass = exep.and_then(|p| get_wb(p, dmem_resp, csr_resp)); let redirect = csr_resp.and_then(|r| if r.eret || exception { Some(r.evec) } else { None }); @@ -114,21 +90,18 @@ pub fn mem( ) -> I, { Dep::Demanding }> { let exep = i .reg_fwd(true) - .map_resolver_inner::<(HOption<(MemRespWithAddr, ExeEP)>, (HOption<(CsrResp, ExeEP)>, WbR), HOption)>( + .map_resolver_inner::<(HOption<(MemRespWithAddr, ExeEP)>, HOption<(CsrResp, ExeEP)>, (HOption, WbR))>( gen_resolver, ); let (dmem_req, csr_req, exep) = exep .map(|p| { - let sel = if p.exception { - // If exception happens, it should go to the CSR. + let sel = if p.mem_info.is_some() { + 0.into_u() + } else if p.csr_info.is_some() || p.is_illegal { 1.into_u() } else { - match p.mem_op { - MemOp::Dmem { .. } => 0.into_u(), - MemOp::Csr(_) => 1.into_u(), - MemOp::None => 2.into_u(), - } + 2.into_u() }; (p, BoundedU::new(sel)) @@ -137,11 +110,11 @@ pub fn mem( let dmem_resp = dmem_req .map(|ip| { - let MemOp::Dmem { fcn, typ } = ip.mem_op else { unsafe { x() } }; + let Some(MemInfo { fcn, typ, data }) = ip.mem_info else { unsafe { x() } }; let mem_req = match fcn { MemOpFcn::Load => MemReq::load(ip.alu_out, typ), - MemOpFcn::Store => MemReq::store(ip.alu_out, ip.st_data.unwrap(), typ), + MemOpFcn::Store => MemReq::store(ip.alu_out, data, typ), }; (mem_req, ip) @@ -152,24 +125,23 @@ pub fn mem( let csr_resp = csr_req .map(|ip| { - let MemOp::Csr(csr) = ip.mem_op else { unsafe { x() } }; + let Some(CsrInfo { cmd, addr }) = ip.csr_info else { unsafe { x() } }; - let csr_req = - CsrReq { cmd: csr.cmd, wdata: ip.alu_out, decode: csr.addr, exception: ip.exception, pc: ip.pc }; + let csr_req = CsrReq { cmd, wdata: ip.alu_out, decode: addr, exception: ip.is_illegal, pc: ip.pc }; (csr_req, ip) }) .comb(csr_wrap) - .map_resolver_with_p::(|ip, er| (ip, er.inner)) + .map_resolver_with_p::(|ip, _| ip) .map(|ip| (None, Some(ip), None)); - let exep = exep.map_resolver_with_p::(|ip, _| ip).map(|ip| (None, None, Some(ip))); + let exep = exep.map_resolver_with_p::(|ip, er| (ip, er.inner)).map(|ip| (None, None, Some(ip))); [dmem_resp, csr_resp, exep].merge().map(|(mem_resp, csr_resp, exep)| { let exep = mem_resp.map(|(_, p)| p).or(csr_resp.map(|(_, p)| p)).or(exep).unwrap(); let mem_resp = mem_resp.map(|(p, _)| p); let csr_resp = csr_resp.map(|(p, _)| p); - MemEP { wb: get_wb(exep, mem_resp, csr_resp), debug_inst: exep.debug_inst, debug_pc: exep.pc } + MemEP { wb_info: get_wb(exep, mem_resp, csr_resp), debug_inst: exep.debug_inst, debug_pc: exep.pc } }) } diff --git a/hazardflow-designs/src/cpu/mem_interface.rs b/hazardflow-designs/src/cpu/mem_interface.rs index cec2143..d01677f 100644 --- a/hazardflow-designs/src/cpu/mem_interface.rs +++ b/hazardflow-designs/src/cpu/mem_interface.rs @@ -74,10 +74,3 @@ pub struct MemRespWithAddr { /// address pub addr: u32, } - -/// Memory Response. -#[derive(Debug, Clone, Copy)] -pub struct MemResp { - /// data - pub data: u32, -} diff --git a/hazardflow-designs/src/cpu/multiplier.rs b/hazardflow-designs/src/cpu/multiplier.rs index 7025a0b..116aa64 100644 --- a/hazardflow-designs/src/cpu/multiplier.rs +++ b/hazardflow-designs/src/cpu/multiplier.rs @@ -5,21 +5,21 @@ use super::*; /// Multiplier function. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum MulOp { - /// TODO: Documentation + /// MUL operation. Mul, - /// TODO: Documentation + /// MULH operation. Mulh, - /// TODO: Documentation + /// MULHU operation. Mulhu, - /// TODO: Documentation + /// MULHSU operation. Mulhsu, - /// TODO: Documentation + /// DIV operation. Div, - /// TODO: Documentation + /// REM operation. Rem, - /// TODO: Documentation + /// DIVU operation. Divu, - /// TODO: Documentation + /// REMU operation. Remu, } @@ -48,7 +48,6 @@ pub struct MulReq { pub in2: U<32>, } -/// TODO: Documentation #[derive(Debug, Default, Clone, Copy)] enum Status { #[default] diff --git a/hazardflow-designs/src/cpu/riscv32_5stage.rs b/hazardflow-designs/src/cpu/riscv32_5stage.rs index 292a4cb..bea05b5 100644 --- a/hazardflow-designs/src/cpu/riscv32_5stage.rs +++ b/hazardflow-designs/src/cpu/riscv32_5stage.rs @@ -10,5 +10,5 @@ pub fn core( imem: impl FnOnce(Vr) -> Vr, dmem: impl FnOnce(Vr) -> Vr, ) { - fetch::(imem).comb(decode).comb(exe).comb(move |ingress| mem(ingress, dmem)).comb(wb) + fetch::(imem).comb(decode).comb(exe).comb(move |i| mem(i, dmem)).comb(wb) } diff --git a/hazardflow-designs/src/cpu/riscv_isa.rs b/hazardflow-designs/src/cpu/riscv_isa.rs index 0776be3..48e7b0a 100644 --- a/hazardflow-designs/src/cpu/riscv_isa.rs +++ b/hazardflow-designs/src/cpu/riscv_isa.rs @@ -17,7 +17,7 @@ pub const LEN_CSR_ADDR: usize = 12; /// Number of registers. pub const REGS: usize = 32; -/// Op1 data selector. +/// ALU first operand data selector. #[derive(Debug, Clone, Copy)] pub enum Op1Sel { Rs1, @@ -25,7 +25,7 @@ pub enum Op1Sel { Imm, } -/// Op2 data selector. +/// ALU second operand data selector. #[derive(Debug, Clone, Copy)] pub enum Op2Sel { Four, @@ -33,19 +33,13 @@ pub enum Op2Sel { Rs2, } -/// Jmp target selector. -#[derive(Debug, Clone, Copy)] -pub enum JmpTargetSel { - BType, - JType, - Jalr, -} - -/// Instruction2. +/// Decoded instruction. +/// +/// It does not contain the resolved register values. #[derive(Debug, Clone, Copy)] pub struct Instruction { pub is_illegal: bool, - pub br_type: BranchType, + pub br_type: HOption, pub rs1_addr: HOption>, pub rs2_addr: HOption>, pub rd_addr: HOption>, @@ -54,7 +48,6 @@ pub struct Instruction { pub wb_sel: HOption, pub csr_info: HOption, pub mem_info: HOption<(MemOpFcn, MemOpTyp)>, - jmp_target_sel: HOption, op1_sel: HOption, op2_sel: HOption, } @@ -103,14 +96,12 @@ impl Instruction { .unwrap_or(0) } - pub fn jmp_target(self, rs1: HOption, pc: u32) -> (u32, u32) { - self.jmp_target_sel - .map(|sel| match sel { - JmpTargetSel::BType => (pc, self.imm), - JmpTargetSel::JType => (self.imm, pc), - JmpTargetSel::Jalr => (rs1.unwrap().data, self.imm), - }) - .unwrap_or((0, 0)) + pub fn br_info(self, rs1: HOption, pc: u32) -> HOption { + self.br_type.map(|typ| BrInfo { + typ, + base: if matches!(typ, BrType::Jalr) { rs1.unwrap().data } else { pc }, + offset: self.imm, + }) } } @@ -199,21 +190,23 @@ impl From for Instruction { let is_csri = is_csrrwi || is_csrrsi || is_csrrci; let br_type = if is_beq { - BranchType::Eq + Some(BrType::Beq) } else if is_bne { - BranchType::Ne + Some(BrType::Bne) } else if is_bge { - BranchType::Ge + Some(BrType::Bge) } else if is_bgeu { - BranchType::Geu + Some(BrType::Bgeu) } else if is_blt { - BranchType::Lt + Some(BrType::Blt) } else if is_bltu { - BranchType::Ltu - } else if is_jtype || is_jalr { - BranchType::J + Some(BrType::Bltu) + } else if is_jtype { + Some(BrType::Jal) + } else if is_jalr { + Some(BrType::Jalr) } else { - BranchType::N + None }; let value = U::<32>::from(value); @@ -236,24 +229,22 @@ impl From for Instruction { let imm_itype = value.clip_const::<11>(20).append(value[31].repeat::<21>()); let imm_stype = value.clip_const::<5>(7).append(value.clip_const::<6>(25)).append(value[31].repeat::<21>()); - let imm = if is_lui || is_auipc { - imm_utype - } else if is_jal { - imm_jtype(value) - } else if is_jalr { - imm_itype + let imm = if is_itype { + if is_slli || is_srli || is_srai { + value.clip_const::<5>(20).append(U::<27>::from(0u32)) + } else { + imm_itype + } + } else if is_stype { + imm_stype } else if is_btype { imm_btype(value) - } else if is_lb || is_lh || is_lw || is_lbu || is_lhu { - imm_itype - } else if is_sb || is_sh || is_sw { - imm_stype - } else if is_addi || is_slti || is_sltiu || is_xori || is_ori || is_andi { - imm_itype - } else if is_slli || is_srli || is_srai { - value.clip_const::<5>(20).append(U::<27>::from(0u32)) + } else if is_utype { + imm_utype + } else if is_jtype { + imm_jtype(value) } else if is_csri { - value.clip_const::<5>(15).append(0.into_u()) + value.clip_const::<5>(15).append(false.repeat::<27>()) } else { U::from(0) }; @@ -303,15 +294,11 @@ impl From for Instruction { } else if is_itype { if is_lw || is_lh || is_lhu || is_lb || is_lbu { Some(WbSel::Mem) - } else if is_jalr { - Some(WbSel::Pc4) } else { Some(WbSel::Alu) } - } else if is_utype { + } else if is_utype || is_jtype { Some(WbSel::Alu) - } else if is_jtype { - Some(WbSel::Pc4) } else if is_stype || is_btype { None } else if is_csr || is_csri { @@ -353,7 +340,7 @@ impl From for Instruction { None }; - let op1_sel = if is_auipc || is_jtype { + let op1_sel = if is_auipc || is_jtype || is_jalr { Some(Op1Sel::Pc) } else if is_csri { Some(Op1Sel::Imm) @@ -365,7 +352,7 @@ impl From for Instruction { let op2_sel = if is_rtype || is_btype { Some(Op2Sel::Rs2) - } else if is_jtype { + } else if is_jtype || is_jalr { Some(Op2Sel::Four) } else if is_itype || is_stype || is_utype { Some(Op2Sel::Imm) @@ -373,18 +360,6 @@ impl From for Instruction { None }; - let jmp_target_sel = if is_btype { - Some(JmpTargetSel::BType) - } else if is_jtype { - // JAL: Jump to `imm`. - Some(JmpTargetSel::JType) - } else if is_jalr { - // JALR: Jump to `rs1` + `imm`. - Some(JmpTargetSel::Jalr) - } else { - None - }; - Self { is_illegal, br_type, @@ -396,54 +371,64 @@ impl From for Instruction { wb_sel, csr_info, mem_info, - jmp_target_sel, op1_sel, op2_sel, } } } -/// Branch Type -// NOTE: We ordered variants for comb logic optimization +/// Branch information. #[derive(Debug, Clone, Copy)] -pub enum BranchType { - /// Next - N, +pub struct BrInfo { + /// Branch type. + pub typ: BrType, - /// Jump - J, + /// Base address. + pub base: u32, - /// Branch on Equal - Eq, + /// Offset. + pub offset: u32, +} - /// Branch on NotEqual - Ne, +/// Branch type. +#[derive(Debug, Clone, Copy)] +pub enum BrType { + /// JAL. + Jal, - /// Branch on Greater/Equal - Ge, + /// JALR. + Jalr, - /// Branch on Less Than - Lt, + /// Branch on equal. + Beq, - /// Branch on Greater/Equal Unsigned - Geu, + /// Branch on not equal. + Bne, - /// Branch on Less Than Unsigned - Ltu, + /// Branch on greater or equal. + Bge, + + /// Branch on less. + Blt, + + /// Branch on greater or equal (unsigned). + Bgeu, + + /// Branch on less (unsigned). + Bltu, } -/// Writeback Select Signal +/// Writeback selector. +/// +/// Indicates which value should be writeback to the regfile. #[derive(Debug, Clone, Copy)] pub enum WbSel { - /// ALU + /// Writeback ALU output (e.g., `add`, `sub`, ...). Alu, - /// Memory + /// Writeback DMEM response (e.g., `lb`, `lh`, ...). Mem, - /// PC + 4 - Pc4, - - /// CSR + /// Writeback CSR response (e.g., `csrr`, `csrw`, ...). Csr, } diff --git a/hazardflow-designs/src/cpu/wb.rs b/hazardflow-designs/src/cpu/wb.rs index c3ee3a8..076f544 100644 --- a/hazardflow-designs/src/cpu/wb.rs +++ b/hazardflow-designs/src/cpu/wb.rs @@ -41,17 +41,17 @@ impl WbR { /// Writeback stage. pub fn wb(i: I, { Dep::Demanding }>) { - i.map_resolver_inner::<(HOption, Regfile)>(|(wb, rf)| WbR::new(wb.and_then(|p| p.wb), rf)) + i.map_resolver_inner::<(HOption, Regfile)>(|(p, rf)| WbR::new(p.and_then(|p| p.wb_info), rf)) .reg_fwd(true) - .sink_fsm_map(0.repeat(), |ip, rf| { + .sink_fsm_map(Regfile::default(), |ip, rf| { let ir = Ready::valid((ip, rf)); let rf_next = match ip { - Some(MemEP { wb: Some(r), .. }) => rf.set(r.addr, r.data), + Some(MemEP { wb_info: Some(r), .. }) => rf.set(r.addr, r.data), _ => rf, }; if let Some(p) = ip { - match p.wb { + match p.wb_info { Some(r) => { display!( "retire=[1] pc=[%x] inst=[%x] write=[r%d=%x]",