forked from libre-chip/cpu
rename_execute_retire: add reference counting for L2 registers
This commit is contained in:
parent
fdf1e97e10
commit
e0dc5d486b
8 changed files with 23681 additions and 79 deletions
|
|
@ -10,14 +10,14 @@ use crate::{
|
|||
CpuConfigUnitCount, PhantomConstCpuConfig, TwiceCpuConfigFetchWidth,
|
||||
},
|
||||
instruction::{
|
||||
COMMON_MOP_SRC_LEN, L2RegNum, L2RegisterFileMOp, MOp, MOpDestReg, MOpRegNum, MOpTrait,
|
||||
PRegNum, ReadL2RegMOp, UnitNum, UnitOutRegNum, WriteL2RegMOp,
|
||||
COMMON_MOP_SRC_LEN, L2RegNum, MOp, MOpDestReg, MOpRegNum, MOpTrait, PRegNum, ReadL2RegMOp,
|
||||
UnitNum, UnitOutRegNum, WriteL2RegMOp,
|
||||
},
|
||||
next_pc::{CallStackOp, SimValueDefault},
|
||||
register::PRegValue,
|
||||
rename_execute_retire::{
|
||||
rename_table::{RenameTable, RenameTableDebugState, RenameTableEntry, RenameTableUpdate},
|
||||
reorder_buffer::{ReorderBuffer, ReorderBufferDebugState, RobEntries, RobEntry},
|
||||
reorder_buffer::{ReorderBuffer, ReorderBufferDebugState, RobEntry},
|
||||
to_unit_interfaces::ExecuteToUnitInterfaces,
|
||||
},
|
||||
unit::{UnitKind, UnitMOp},
|
||||
|
|
@ -257,6 +257,10 @@ impl<C: PhantomConstCpuConfig> SimValueDefault for RenameExecuteRetireDebugState
|
|||
}
|
||||
}
|
||||
|
||||
/// make arrays dynamically-sized to avoid putting large types on the stack
|
||||
#[hdl(get(|_| L2RegNum.l2_reg_count()))]
|
||||
type L2RegFileLen<C: PhantomConstGet<CpuConfig>> = DynSize;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, Default)]
|
||||
enum MOpInUnitState {
|
||||
#[default]
|
||||
|
|
@ -748,31 +752,14 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
|||
}
|
||||
#[hdl]
|
||||
fn find_free_l2_reg(&self) -> Option<usize> {
|
||||
// TODO: replace searching through instructions and rename tables with tracking when regs are free
|
||||
let mut allocated_regs = vec![false; L2RegNum.l2_reg_count()];
|
||||
for renamed in self.rob.renamed() {
|
||||
#[hdl(sim)]
|
||||
if let RenamedMOp::<_>::TransformedMove(l2_register_file_op) = renamed.mop.mop.inner() {
|
||||
let l2_reg = #[hdl(sim)]
|
||||
match l2_register_file_op {
|
||||
L2RegisterFileMOp::<_, _>::ReadL2Reg(v) => &v.common.imm,
|
||||
L2RegisterFileMOp::<_, _>::WriteL2Reg(v) => &v.common.imm,
|
||||
};
|
||||
allocated_regs[L2RegNum::value_sim(l2_reg)] = true;
|
||||
}
|
||||
}
|
||||
for entry in self
|
||||
.rename_table
|
||||
.entries()
|
||||
let rob_l2_reg_ref_counts = self.rob.l2_reg_ref_counts();
|
||||
let rename_table_l2_ref_counts = self.rename_table.l2_ref_counts();
|
||||
let retire_rename_table_l2_ref_counts = self.retire_rename_table.l2_ref_counts();
|
||||
rob_l2_reg_ref_counts
|
||||
.iter()
|
||||
.chain(self.retire_rename_table.entries().iter())
|
||||
{
|
||||
#[hdl(sim)]
|
||||
if let HdlSome(l2) = &entry.inner().l2 {
|
||||
allocated_regs[L2RegNum::value_sim(l2)] = true;
|
||||
}
|
||||
}
|
||||
allocated_regs.iter().position(|v| !v)
|
||||
.zip(rename_table_l2_ref_counts)
|
||||
.zip(retire_rename_table_l2_ref_counts)
|
||||
.position(|((a, b), c)| *a == 0 && *b == 0 && *c == 0)
|
||||
}
|
||||
fn add_renamed_with_new_id(
|
||||
&mut self,
|
||||
|
|
@ -838,7 +825,7 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
|||
println!("moving from {src_reg:?} renamed: {renamed_reg:?}");
|
||||
let unrenamed_dest_regs =
|
||||
MOpDestReg::regs_sim(MOpTrait::dest_reg_sim_ref(move_reg_mop));
|
||||
assert!(self.rob.incomplete_back_entry.is_none());
|
||||
assert!(!self.rob.has_incomplete_back_entry());
|
||||
for unrenamed_reg_num in unrenamed_dest_regs {
|
||||
self.update_rename_table(
|
||||
&insn,
|
||||
|
|
@ -981,7 +968,7 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
|||
src: reg_to_free.clone(),
|
||||
},
|
||||
);
|
||||
let l2_store_id = self.add_renamed_with_new_id(
|
||||
self.add_renamed_with_new_id(
|
||||
&insn,
|
||||
RobEntry::new(
|
||||
#[hdl(sim)]
|
||||
|
|
@ -1456,7 +1443,7 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
|||
fn peek_retiring_insns(&self) -> Vec<SimValue<NextPcPredictorOp<C>>> {
|
||||
let mut retval = Vec::new();
|
||||
for retire_group in self.rob.retire_groups() {
|
||||
for renamed_entry in retire_group.clone().flat_map(|v| &v.renamed_entries) {
|
||||
for renamed_entry in retire_group.clone().flatten() {
|
||||
if let RobEntry {
|
||||
is_register_fence: _,
|
||||
done_waiting_for_register_fences: _,
|
||||
|
|
@ -1479,12 +1466,7 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
|||
return retval;
|
||||
}
|
||||
}
|
||||
for RobEntries {
|
||||
unrenamed: _,
|
||||
rename_table_updates: _,
|
||||
renamed_entries,
|
||||
} in retire_group
|
||||
{
|
||||
for renamed_entries in retire_group {
|
||||
let caused_cancel = renamed_entries.iter().any(|v| v.caused_cancel.is_some());
|
||||
let caused_cancel_after_retire =
|
||||
renamed_entries
|
||||
|
|
@ -1581,12 +1563,7 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
|||
cond_br_taken: _,
|
||||
config: _,
|
||||
} = retire;
|
||||
let Some(RobEntries {
|
||||
unrenamed: _,
|
||||
rename_table_updates,
|
||||
renamed_entries,
|
||||
}) = self.rob.entries.pop_front()
|
||||
else {
|
||||
let Some((rename_table_updates, renamed_entries)) = self.rob.entries_pop_front() else {
|
||||
unreachable!();
|
||||
};
|
||||
rename_table_updates
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@
|
|||
use crate::{
|
||||
config::{CpuConfig, PhantomConstCpuConfig},
|
||||
instruction::{L2RegNum, MOpRegNum, PRegNum, UnitNum, UnitOutRegNum},
|
||||
rename_execute_retire::L2RegFileLen,
|
||||
};
|
||||
use fayalite::prelude::*;
|
||||
use fayalite::{int::UIntInRangeInclusiveType, prelude::*};
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[hdl(no_static)]
|
||||
|
|
@ -34,12 +35,15 @@ type MOpRegCount<C: PhantomConstGet<CpuConfig>> = DynSize;
|
|||
#[hdl(no_static)]
|
||||
pub(crate) struct RenameTableDebugState<C: PhantomConstGet<CpuConfig>> {
|
||||
entries: ArrayType<TraceAsString<RenameTableEntry<C>>, MOpRegCount<C>>,
|
||||
l2_ref_counts:
|
||||
ArrayType<UIntInRangeInclusiveType<ConstUsize<0>, MOpRegCount<C>>, L2RegFileLen<C>>,
|
||||
config: C,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct RenameTable<C: PhantomConstCpuConfig> {
|
||||
entries: Box<[SimValue<TraceAsString<RenameTableEntry<C>>>; 1 << MOpRegNum::WIDTH]>,
|
||||
l2_ref_counts: Box<[usize]>,
|
||||
config: C,
|
||||
}
|
||||
|
||||
|
|
@ -48,11 +52,17 @@ impl<C: PhantomConstCpuConfig> Clone for RenameTable<C> {
|
|||
Self {
|
||||
entries: self.entries.clone(),
|
||||
config: self.config.clone(),
|
||||
l2_ref_counts: self.l2_ref_counts.clone(),
|
||||
}
|
||||
}
|
||||
fn clone_from(&mut self, source: &Self) {
|
||||
let Self { entries, config } = self;
|
||||
let Self {
|
||||
entries,
|
||||
l2_ref_counts,
|
||||
config,
|
||||
} = self;
|
||||
entries.clone_from(&source.entries);
|
||||
l2_ref_counts.clone_from(&source.l2_ref_counts);
|
||||
*config = source.config;
|
||||
}
|
||||
}
|
||||
|
|
@ -83,7 +93,11 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
|||
]
|
||||
.try_into()
|
||||
.expect("size is known to match");
|
||||
Self { entries, config }
|
||||
Self {
|
||||
entries,
|
||||
l2_ref_counts: vec![0; L2RegFileLen[config]].into_boxed_slice(),
|
||||
config,
|
||||
}
|
||||
}
|
||||
pub(crate) fn entries(
|
||||
&self,
|
||||
|
|
@ -92,16 +106,60 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
|||
}
|
||||
#[hdl]
|
||||
pub(crate) fn to_debug_state(&self) -> SimValue<RenameTableDebugState<C>> {
|
||||
let Self { entries, config } = self;
|
||||
let Self {
|
||||
entries,
|
||||
l2_ref_counts,
|
||||
config,
|
||||
} = self;
|
||||
let ty = RenameTableDebugState[*config];
|
||||
#[hdl(sim)]
|
||||
RenameTableDebugState::<_> {
|
||||
entries: entries.to_sim_value_with_type(ty.entries),
|
||||
l2_ref_counts: l2_ref_counts.to_sim_value_with_type(ty.l2_ref_counts),
|
||||
config,
|
||||
}
|
||||
}
|
||||
#[hdl]
|
||||
pub(crate) fn update(&mut self, update: &RenameTableUpdate<C>, rename_table_name: &str) {
|
||||
pub(crate) fn l2_ref_counts(&self) -> &[usize] {
|
||||
let mut expected = vec![0usize; L2RegNum.l2_reg_count()];
|
||||
for entry in self.entries.iter() {
|
||||
#[hdl(sim)]
|
||||
let RenameTableEntry::<_> { l1: _, l2 } = entry.inner();
|
||||
#[hdl(sim)]
|
||||
if let HdlSome(l2) = l2 {
|
||||
expected[L2RegNum::value_sim(l2)] += 1
|
||||
}
|
||||
}
|
||||
assert_eq!(*expected, *self.l2_ref_counts);
|
||||
&self.l2_ref_counts
|
||||
}
|
||||
#[hdl]
|
||||
pub(crate) fn update<'a>(&mut self, update: &RenameTableUpdate<C>, rename_table_name: &str) {
|
||||
let mut update_entry =
|
||||
|entry: &mut SimValue<TraceAsString<RenameTableEntry<C>>>,
|
||||
new: SimValue<TraceAsString<RenameTableEntry<C>>>| {
|
||||
#[hdl(sim)]
|
||||
let RenameTableEntry::<_> { l1: _, l2 } = entry.inner();
|
||||
#[hdl(sim)]
|
||||
if let HdlSome(l2) = l2 {
|
||||
let ref_count = &mut self.l2_ref_counts[L2RegNum::value_sim(l2)];
|
||||
*ref_count = ref_count.checked_sub(1).unwrap_or_else(|| {
|
||||
unreachable!("{rename_table_name}: l2 ref count went negative: {l2:?}")
|
||||
});
|
||||
}
|
||||
#[hdl(sim)]
|
||||
let RenameTableEntry::<_> { l1: _, l2 } = new.inner();
|
||||
#[hdl(sim)]
|
||||
if let HdlSome(l2) = l2 {
|
||||
let ref_count = &mut self.l2_ref_counts[L2RegNum::value_sim(l2)];
|
||||
*ref_count += 1;
|
||||
assert!(
|
||||
*ref_count <= L2RegNum.l2_reg_count(),
|
||||
"{rename_table_name}: l2 ref count overflowed: {l2:?}",
|
||||
)
|
||||
}
|
||||
*entry = new;
|
||||
};
|
||||
match update {
|
||||
RenameTableUpdate::Write {
|
||||
unrenamed_reg_num,
|
||||
|
|
@ -112,7 +170,7 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
|||
return;
|
||||
}
|
||||
println!("{rename_table_name}: Write: {unrenamed_reg_num:#x} <- {new:?}");
|
||||
self.entries[*unrenamed_reg_num as usize] = new.clone();
|
||||
update_entry(&mut self.entries[*unrenamed_reg_num as usize], new.clone());
|
||||
}
|
||||
RenameTableUpdate::UpdateForReadL2Reg { dest, src } => {
|
||||
let new = #[hdl(sim)]
|
||||
|
|
@ -134,7 +192,7 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
|||
if let HdlSome(_) = &entry.inner().l1 {
|
||||
unreachable!("l1 should be HdlNone: {entry:?}");
|
||||
}
|
||||
*entry = new.to_trace_as_string();
|
||||
update_entry(entry, new.to_trace_as_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -159,7 +217,7 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
|||
if let HdlSome(_) = &entry.inner().l2 {
|
||||
unreachable!("l2 should be HdlNone: {entry:?}");
|
||||
}
|
||||
*entry = new.to_trace_as_string();
|
||||
update_entry(entry, new.to_trace_as_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -177,7 +235,7 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
|||
"{rename_table_name}: DropAllL2RegFileOutputs: {unrenamed_reg_num:#x} \
|
||||
updating from {entry:?} to {new:?}",
|
||||
);
|
||||
*entry = new.to_trace_as_string();
|
||||
update_entry(entry, new.to_trace_as_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,19 @@
|
|||
|
||||
use crate::{
|
||||
config::{CpuConfig, CpuConfigRobSize, CpuConfigUnitCount, PhantomConstCpuConfig},
|
||||
instruction::{MOp, MOpTrait, PRegNum, UnitNum, UnitOutRegNum},
|
||||
instruction::{L2RegNum, L2RegisterFileMOp, MOp, MOpTrait, PRegNum, UnitNum, UnitOutRegNum},
|
||||
next_pc::SimValueDefault,
|
||||
rename_execute_retire::{
|
||||
MOpId, MOpInUnitState, MOpInstance, NextPcPredictorOp, RenamedMOp, UnitCausedCancel,
|
||||
rename_table::RenameTableUpdate, zeroed,
|
||||
L2RegFileLen, MOpId, MOpInUnitState, MOpInstance, NextPcPredictorOp, RenamedMOp,
|
||||
UnitCausedCancel, rename_table::RenameTableUpdate, zeroed,
|
||||
},
|
||||
util::array_vec::ArrayVec,
|
||||
};
|
||||
use fayalite::{int::UIntInRangeType, prelude::*, ty::StaticType};
|
||||
use fayalite::{
|
||||
int::{UIntInRangeInclusiveType, UIntInRangeType},
|
||||
prelude::*,
|
||||
ty::StaticType,
|
||||
};
|
||||
use std::{collections::VecDeque, mem};
|
||||
|
||||
#[hdl]
|
||||
|
|
@ -136,6 +140,33 @@ impl<C: PhantomConstCpuConfig> RobEntry<C> {
|
|||
caused_cancel: caused_cancel.into_sim_value_with_type(ret_ty.caused_cancel),
|
||||
}
|
||||
}
|
||||
#[hdl]
|
||||
fn for_each_reg<S>(
|
||||
&self,
|
||||
mut shared_state: S,
|
||||
mut l1_reg: impl FnMut(&mut S, &SimValue<PRegNum<C>>),
|
||||
mut l2_reg: impl FnMut(&mut S, &SimValue<L2RegNum>),
|
||||
) {
|
||||
l1_reg(
|
||||
&mut shared_state,
|
||||
MOpTrait::dest_reg_sim_ref(self.mop.mop.inner()),
|
||||
);
|
||||
MOpTrait::for_each_src_reg_sim_ref(self.mop.mop.inner(), &mut |l1, _| {
|
||||
l1_reg(&mut shared_state, l1);
|
||||
});
|
||||
#[hdl(sim)]
|
||||
if let RenamedMOp::<_>::TransformedMove(mop) = self.mop.mop.inner() {
|
||||
#[hdl(sim)]
|
||||
match mop {
|
||||
L2RegisterFileMOp::<_, _>::ReadL2Reg(v) => {
|
||||
l2_reg(&mut shared_state, &v.common.imm);
|
||||
}
|
||||
L2RegisterFileMOp::<_, _>::WriteL2Reg(v) => {
|
||||
l2_reg(&mut shared_state, &v.common.imm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
|
|
@ -161,10 +192,10 @@ impl SimValueDefault for RobEntriesDebugState {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct RobEntries<C: PhantomConstCpuConfig> {
|
||||
pub(crate) unrenamed: SimValue<MOpInstance<MOp>>,
|
||||
pub(crate) rename_table_updates: Vec<RenameTableUpdate<C>>,
|
||||
pub(crate) renamed_entries: VecDeque<RobEntry<C>>,
|
||||
struct RobEntries<C: PhantomConstCpuConfig> {
|
||||
unrenamed: SimValue<MOpInstance<MOp>>,
|
||||
rename_table_updates: Vec<RenameTableUpdate<C>>,
|
||||
renamed_entries: VecDeque<RobEntry<C>>,
|
||||
}
|
||||
|
||||
impl<C: PhantomConstCpuConfig> RobEntries<C> {
|
||||
|
|
@ -190,6 +221,8 @@ pub(crate) struct ReorderBufferDebugState<C: PhantomConstGet<CpuConfig>> {
|
|||
entries: ArrayVec<RobEntriesDebugState, CpuConfigRobSize<C>>,
|
||||
incomplete_back_entry: HdlOption<RobEntriesDebugState>,
|
||||
renamed: ArrayVec<RobEntryDebugState<C>, CpuConfigRobSize<C>>,
|
||||
l2_reg_ref_counts:
|
||||
ArrayType<UIntInRangeInclusiveType<ConstUsize<0>, CpuConfigRobSize<C>>, L2RegFileLen<C>>,
|
||||
config: C,
|
||||
}
|
||||
|
||||
|
|
@ -201,6 +234,7 @@ impl<C: PhantomConstCpuConfig> SimValueDefault for ReorderBufferDebugState<C> {
|
|||
entries,
|
||||
incomplete_back_entry,
|
||||
renamed,
|
||||
l2_reg_ref_counts,
|
||||
config,
|
||||
} = self;
|
||||
#[hdl(sim)]
|
||||
|
|
@ -209,6 +243,7 @@ impl<C: PhantomConstCpuConfig> SimValueDefault for ReorderBufferDebugState<C> {
|
|||
entries: entries.sim_value_default(),
|
||||
incomplete_back_entry: incomplete_back_entry.sim_value_default(),
|
||||
renamed: renamed.sim_value_default(),
|
||||
l2_reg_ref_counts: zeroed(l2_reg_ref_counts),
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
|
@ -217,8 +252,9 @@ impl<C: PhantomConstCpuConfig> SimValueDefault for ReorderBufferDebugState<C> {
|
|||
#[derive(Debug)]
|
||||
pub(crate) struct ReorderBuffer<C: PhantomConstCpuConfig> {
|
||||
next_renamed_mop_id: SimValue<MOpId>,
|
||||
pub(crate) entries: VecDeque<RobEntries<C>>,
|
||||
pub(crate) incomplete_back_entry: Option<RobEntries<C>>,
|
||||
entries: VecDeque<RobEntries<C>>,
|
||||
incomplete_back_entry: Option<RobEntries<C>>,
|
||||
l2_reg_ref_counts: Box<[usize]>,
|
||||
config: C,
|
||||
}
|
||||
|
||||
|
|
@ -228,15 +264,34 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
|||
next_renamed_mop_id: MOpId.zero().into_sim_value(),
|
||||
entries: VecDeque::new(),
|
||||
incomplete_back_entry: None,
|
||||
l2_reg_ref_counts: vec![0; L2RegNum.l2_reg_count()].into_boxed_slice(),
|
||||
config,
|
||||
}
|
||||
}
|
||||
#[hdl]
|
||||
pub(crate) fn l2_reg_ref_counts(&self) -> &[usize] {
|
||||
let mut expected = vec![0usize; L2RegNum.l2_reg_count()];
|
||||
for entry in self.renamed() {
|
||||
#[hdl(sim)]
|
||||
if let RenamedMOp::<_>::TransformedMove(mop) = entry.mop.mop.inner() {
|
||||
let l2_reg = #[hdl(sim)]
|
||||
match mop {
|
||||
L2RegisterFileMOp::<_, _>::ReadL2Reg(v) => &v.common.imm,
|
||||
L2RegisterFileMOp::<_, _>::WriteL2Reg(v) => &v.common.imm,
|
||||
};
|
||||
expected[L2RegNum::value_sim(l2_reg)] += 1;
|
||||
}
|
||||
}
|
||||
assert_eq!(*expected, *self.l2_reg_ref_counts);
|
||||
&self.l2_reg_ref_counts
|
||||
}
|
||||
#[hdl]
|
||||
pub(crate) fn debug_state(&self) -> SimValue<ReorderBufferDebugState<C>> {
|
||||
let Self {
|
||||
next_renamed_mop_id,
|
||||
entries,
|
||||
incomplete_back_entry,
|
||||
l2_reg_ref_counts,
|
||||
config,
|
||||
} = self;
|
||||
let ty = ReorderBufferDebugState[*config];
|
||||
|
|
@ -259,6 +314,7 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
|||
)
|
||||
.ok()
|
||||
.expect("known to fit"),
|
||||
l2_reg_ref_counts: l2_reg_ref_counts.to_sim_value_with_type(ty.l2_reg_ref_counts),
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
|
@ -270,11 +326,6 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
|||
) -> impl DoubleEndedIterator<Item = &SimValue<MOpInstance<MOp>>> + Clone {
|
||||
self.entries.iter().map(|v| &v.unrenamed)
|
||||
}
|
||||
fn unrenamed_mut(
|
||||
&mut self,
|
||||
) -> impl DoubleEndedIterator<Item = &mut SimValue<MOpInstance<MOp>>> {
|
||||
self.entries.iter_mut().map(|v| &mut v.unrenamed)
|
||||
}
|
||||
fn retire_groups_unrenamed_ranges(
|
||||
&self,
|
||||
) -> impl Clone + Iterator<Item = std::ops::Range<usize>> {
|
||||
|
|
@ -294,15 +345,20 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
|||
}
|
||||
pub(crate) fn retire_groups(
|
||||
&self,
|
||||
) -> impl Clone + Iterator<Item: DoubleEndedIterator<Item = &RobEntries<C>> + Clone> {
|
||||
self.retire_groups_unrenamed_ranges()
|
||||
.map(|range| self.entries.range(range))
|
||||
) -> impl Clone + Iterator<Item: DoubleEndedIterator<Item = &VecDeque<RobEntry<C>>> + Clone>
|
||||
{
|
||||
self.retire_groups_unrenamed_ranges().map(|range| {
|
||||
self.entries
|
||||
.range(range)
|
||||
.map(|entries| &entries.renamed_entries)
|
||||
})
|
||||
}
|
||||
pub(crate) fn renamed_len(&self) -> usize {
|
||||
let Self {
|
||||
next_renamed_mop_id: _,
|
||||
entries,
|
||||
incomplete_back_entry,
|
||||
l2_reg_ref_counts: _,
|
||||
config: _,
|
||||
} = self;
|
||||
entries
|
||||
|
|
@ -316,6 +372,7 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
|||
next_renamed_mop_id: _,
|
||||
entries,
|
||||
incomplete_back_entry,
|
||||
l2_reg_ref_counts: _,
|
||||
config: _,
|
||||
} = self;
|
||||
entries
|
||||
|
|
@ -328,6 +385,7 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
|||
next_renamed_mop_id: _,
|
||||
entries,
|
||||
incomplete_back_entry,
|
||||
l2_reg_ref_counts: _,
|
||||
config: _,
|
||||
} = self;
|
||||
entries
|
||||
|
|
@ -335,19 +393,9 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
|||
.chain(incomplete_back_entry)
|
||||
.flat_map(|entries| &mut entries.renamed_entries)
|
||||
}
|
||||
fn try_renamed_by_id(&self, id: &SimValue<MOpId>) -> Option<&RobEntry<C>> {
|
||||
self.renamed().find(|v| v.mop.id == *id)
|
||||
}
|
||||
fn try_renamed_by_id_mut(&mut self, id: &SimValue<MOpId>) -> Option<&mut RobEntry<C>> {
|
||||
self.renamed_mut().find(|v| v.mop.id == *id)
|
||||
}
|
||||
#[track_caller]
|
||||
fn renamed_by_id(&self, id: &SimValue<MOpId>) -> &RobEntry<C> {
|
||||
match self.try_renamed_by_id(id) {
|
||||
Some(v) => v,
|
||||
None => panic!("MOpId not found: {id:?}"),
|
||||
}
|
||||
}
|
||||
pub(crate) fn renamed_by_id_mut(&mut self, id: &SimValue<MOpId>) -> &mut RobEntry<C> {
|
||||
match self.try_renamed_by_id_mut(id) {
|
||||
Some(v) => v,
|
||||
|
|
@ -366,6 +414,11 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
|||
.into_sim_value();
|
||||
renamed.mop.id = mem::replace(&mut self.next_renamed_mop_id, replacement_id);
|
||||
println!("renamed_push_back_with_new_id: {:?}", renamed.mop);
|
||||
renamed.for_each_reg(
|
||||
(),
|
||||
|(), _l1| {},
|
||||
|(), l2| self.l2_reg_ref_counts[L2RegNum::value_sim(l2)] += 1,
|
||||
);
|
||||
let renamed_entries = &mut self
|
||||
.incomplete_back_entry
|
||||
.get_or_insert_with(|| RobEntries {
|
||||
|
|
@ -377,6 +430,9 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
|||
renamed_entries.push_back(renamed);
|
||||
&renamed_entries.back().expect("just pushed").mop.id
|
||||
}
|
||||
pub(crate) fn has_incomplete_back_entry(&self) -> bool {
|
||||
self.incomplete_back_entry.is_some()
|
||||
}
|
||||
pub(crate) fn finished_unrenamed_push_back(&mut self, unrenamed: &SimValue<MOpInstance<MOp>>) {
|
||||
let entry = self
|
||||
.incomplete_back_entry
|
||||
|
|
@ -393,9 +449,11 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
|||
next_renamed_mop_id: _,
|
||||
entries,
|
||||
incomplete_back_entry,
|
||||
l2_reg_ref_counts,
|
||||
config: _,
|
||||
} = self;
|
||||
entries.clear();
|
||||
l2_reg_ref_counts.fill(0);
|
||||
*incomplete_back_entry = None;
|
||||
}
|
||||
pub(crate) fn unrenamed_back_append_rename_table_update(
|
||||
|
|
@ -418,4 +476,26 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
|||
&& entry.mop_in_unit_state.is_finished_and_or_caused_cancel()
|
||||
})
|
||||
}
|
||||
pub(crate) fn entries_pop_front(
|
||||
&mut self,
|
||||
) -> Option<(Vec<RenameTableUpdate<C>>, VecDeque<RobEntry<C>>)> {
|
||||
let RobEntries {
|
||||
unrenamed: _,
|
||||
rename_table_updates,
|
||||
renamed_entries,
|
||||
} = self.entries.pop_front()?;
|
||||
for entry in &renamed_entries {
|
||||
entry.for_each_reg(
|
||||
(),
|
||||
|(), _l1| {},
|
||||
|(), l2| {
|
||||
let ref_count = &mut self.l2_reg_ref_counts[L2RegNum::value_sim(l2)];
|
||||
*ref_count = ref_count.checked_sub(1).unwrap_or_else(|| {
|
||||
unreachable!("ReorderBuffer: l2 ref count went negative: {l2:?}")
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
Some((rename_table_updates, renamed_entries))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
4614
crates/cpu/tests/expected/rename_execute_retire_head_n1.vcd
generated
4614
crates/cpu/tests/expected/rename_execute_retire_head_n1.vcd
generated
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue