Skip to content

Commit

Permalink
Update baseline CPU
Browse files Browse the repository at this point in the history
  • Loading branch information
minseongg committed Sep 16, 2024
1 parent d453c37 commit c1e8b6b
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 256 deletions.
5 changes: 2 additions & 3 deletions hazardflow-designs/src/cpu/alu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down
40 changes: 18 additions & 22 deletions hazardflow-designs/src/cpu/csr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
//!
//! - Constants: <https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/rocket/CSR.scala>
#![allow(missing_docs)]

use super::*;

/// Contains information that is needed to interact with CSR.
Expand All @@ -22,47 +24,42 @@ pub struct CsrInfo {
/// - <https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/rocket/CSR.scala#L168-L178>
#[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<LEN_CSR_ADDR>,

/// 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,
}

Expand Down Expand Up @@ -255,12 +252,11 @@ pub fn csr(i: Valid<CsrReq>) -> Valid<CsrResp> {
})
}

/// TODO: Documentation
pub fn csr_wrap<P: Copy>(
i: I<VrH<(CsrReq, P), (HOption<(CsrResp, ExeEP)>, WbR)>, { Dep::Helpful }>,
) -> I<VrH<(CsrResp, P), (HOption<(CsrResp, ExeEP)>, WbR)>, { Dep::Helpful }> {
i: I<VrH<(CsrReq, P), HOption<(CsrResp, ExeEP)>>, { Dep::Helpful }>,
) -> I<VrH<(CsrResp, P), HOption<(CsrResp, ExeEP)>>, { Dep::Helpful }> {
let (i1, i2) = unsafe {
Interface::fsm::<(Valid<CsrReq>, I<VrH<P, (HOption<(CsrResp, ExeEP)>, WbR)>, { Dep::Helpful }>), ()>(
Interface::fsm::<(Valid<CsrReq>, I<VrH<P, HOption<(CsrResp, ExeEP)>>, { Dep::Helpful }>), ()>(
i,
(),
|ip, er, s| {
Expand All @@ -275,7 +271,7 @@ pub fn csr_wrap<P: Copy>(
let e1 = i1.comb(csr);

unsafe {
(e1, i2).fsm::<I<VrH<(CsrResp, P), (HOption<(CsrResp, ExeEP)>, WbR)>, { Dep::Helpful }>, ()>(
(e1, i2).fsm::<I<VrH<(CsrResp, P), HOption<(CsrResp, ExeEP)>>, { Dep::Helpful }>, ()>(
(),
|(ip1, ip2), er, s| {
let ep = ip1.zip(ip2);
Expand Down
50 changes: 20 additions & 30 deletions hazardflow-designs/src/cpu/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u32>,

/// 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<BrInfo>,

/// ALU input.
pub alu_input: AluInput,

/// Memory operation.
pub mem_op: MemOp,
/// Memory information.
pub mem_info: HOption<MemInfo>,

/// CSR information.
pub csr_info: HOption<CsrInfo>,

/// 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,
}

Expand Down Expand Up @@ -109,21 +102,18 @@ fn gen_payload(ip: FetEP, inst: Instruction, er: ExeR) -> HOption<DecEP> {
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,
Expand Down
57 changes: 28 additions & 29 deletions hazardflow-designs/src/cpu/exe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<MemInfo>,

/// 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<u32>,
/// CSR information.
pub csr_info: HOption<CsrInfo>,

/// 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,
}

Expand Down Expand Up @@ -76,26 +74,23 @@ impl ExeR {

/// Returns redirected PC based on the given payload.
fn get_redirect(p: DecEP, alu_out: u32) -> HOption<u32> {
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 {
Expand All @@ -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.
Expand All @@ -130,10 +129,10 @@ fn gen_payload(ip: DecEP, alu_out: u32, memr: MemR) -> HOption<ExeEP> {
} 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,
})
Expand Down
Loading

0 comments on commit c1e8b6b

Please sign in to comment.