use crate::common::{PhysAddr, VirtAddr};
use crate::isa::reg::RegIdx;
use crate::uarch::pipeline::snapshot::LatchSnapshot;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct PipelineSnapshot {
pub width: usize,
pub fetch1_fetch2: Vec<FetchSlot>,
pub fetch2_decode: Vec<FetchedSlot>,
pub decode_rename: Vec<DecodedSlot>,
pub rename_issue: Vec<RenamedSlot>,
pub issue_queue: Vec<RenamedSlot>,
pub execute_mem1: Vec<ExecutedSlot>,
pub mem1_mem2: Vec<MemorySlot>,
pub mem2_wb: Vec<WritebackSlot>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FetchSlot {
pub pc: u64,
pub pred_taken: bool,
pub pred_target: u64,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FetchedSlot {
pub pc: u64,
pub raw: u32,
pub pred_taken: bool,
pub pred_target: u64,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct DecodedSlot {
pub pc: u64,
pub raw: u32,
pub rs1: RegIdx,
pub rs2: RegIdx,
pub rd: RegIdx,
pub imm: i64,
pub rv1: u64,
pub rv2: u64,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RenamedSlot {
pub pc: u64,
pub raw: u32,
pub rs1: RegIdx,
pub rs2: RegIdx,
pub rd: RegIdx,
pub rv1: u64,
pub rv2: u64,
pub rob_tag: u32,
pub rs1_ready: bool,
pub rs2_ready: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ExecutedSlot {
pub pc: u64,
pub raw: u32,
pub rd: RegIdx,
pub alu: u64,
pub store_data: u64,
pub rob_tag: u32,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct MemorySlot {
pub pc: u64,
pub raw: u32,
pub rd: RegIdx,
pub alu: u64,
pub vaddr: VirtAddr,
pub paddr: PhysAddr,
pub store_data: u64,
pub rob_tag: u32,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct WritebackSlot {
pub pc: u64,
pub raw: u32,
pub rd: RegIdx,
pub alu: u64,
pub load_data: u64,
pub rob_tag: u32,
}
impl From<&LatchSnapshot> for PipelineSnapshot {
fn from(latches: &LatchSnapshot) -> Self {
Self {
width: latches.width,
fetch1_fetch2: latches
.fetch1_fetch2
.iter()
.map(|e| FetchSlot {
pc: e.pc,
pred_taken: e.pred_taken,
pred_target: e.pred_target,
})
.collect(),
fetch2_decode: latches
.fetch2_decode
.iter()
.map(|e| FetchedSlot {
pc: e.pc,
raw: e.inst,
pred_taken: e.pred_taken,
pred_target: e.pred_target,
})
.collect(),
decode_rename: latches
.decode_rename
.iter()
.map(|e| DecodedSlot {
pc: e.inst.pc,
raw: e.inst.bits,
rs1: e.inst.rs1,
rs2: e.inst.rs2,
rd: e.inst.rd,
imm: e.inst.imm,
rv1: e.inst.rv1,
rv2: e.inst.rv2,
})
.collect(),
rename_issue: latches.rename_issue.iter().map(renamed_slot).collect(),
issue_queue: latches.issue_queue.iter().map(renamed_slot).collect(),
execute_mem1: latches
.execute_mem1
.iter()
.map(|e| ExecutedSlot {
pc: e.pc,
raw: e.inst,
rd: e.rd,
alu: e.alu,
store_data: e.store_data,
rob_tag: e.rob_tag.0,
})
.collect(),
mem1_mem2: latches
.mem1_mem2
.iter()
.map(|e| MemorySlot {
pc: e.pc,
raw: e.inst,
rd: e.rd,
alu: e.alu,
vaddr: e.vaddr,
paddr: e.paddr,
store_data: e.store_data,
rob_tag: e.rob_tag.0,
})
.collect(),
mem2_wb: latches
.mem2_wb
.iter()
.map(|e| WritebackSlot {
pc: e.pc,
raw: e.inst,
rd: e.rd,
alu: e.alu,
load_data: e.load_data,
rob_tag: e.rob_tag.0,
})
.collect(),
}
}
}
const fn renamed_slot(e: &crate::uarch::pipeline::latches::RenameIssueEntry) -> RenamedSlot {
RenamedSlot {
pc: e.inst.pc,
raw: e.inst.bits,
rs1: e.inst.rs1,
rs2: e.inst.rs2,
rd: e.inst.rd,
rv1: e.inst.rv1,
rv2: e.inst.rv2,
rob_tag: e.rob_tag.0,
rs1_ready: e.rs1_tag.is_none(),
rs2_ready: e.rs2_tag.is_none(),
}
}