rename_execute_retire: add reference counting for L2 registers

This commit is contained in:
Jacob Lifshay 2026-05-21 20:54:04 -07:00
parent fdf1e97e10
commit e0dc5d486b
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
8 changed files with 23681 additions and 79 deletions

View file

@ -10,14 +10,14 @@ use crate::{
CpuConfigUnitCount, PhantomConstCpuConfig, TwiceCpuConfigFetchWidth, CpuConfigUnitCount, PhantomConstCpuConfig, TwiceCpuConfigFetchWidth,
}, },
instruction::{ instruction::{
COMMON_MOP_SRC_LEN, L2RegNum, L2RegisterFileMOp, MOp, MOpDestReg, MOpRegNum, MOpTrait, COMMON_MOP_SRC_LEN, L2RegNum, MOp, MOpDestReg, MOpRegNum, MOpTrait, PRegNum, ReadL2RegMOp,
PRegNum, ReadL2RegMOp, UnitNum, UnitOutRegNum, WriteL2RegMOp, UnitNum, UnitOutRegNum, WriteL2RegMOp,
}, },
next_pc::{CallStackOp, SimValueDefault}, next_pc::{CallStackOp, SimValueDefault},
register::PRegValue, register::PRegValue,
rename_execute_retire::{ rename_execute_retire::{
rename_table::{RenameTable, RenameTableDebugState, RenameTableEntry, RenameTableUpdate}, rename_table::{RenameTable, RenameTableDebugState, RenameTableEntry, RenameTableUpdate},
reorder_buffer::{ReorderBuffer, ReorderBufferDebugState, RobEntries, RobEntry}, reorder_buffer::{ReorderBuffer, ReorderBufferDebugState, RobEntry},
to_unit_interfaces::ExecuteToUnitInterfaces, to_unit_interfaces::ExecuteToUnitInterfaces,
}, },
unit::{UnitKind, UnitMOp}, 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)] #[derive(Copy, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, Default)]
enum MOpInUnitState { enum MOpInUnitState {
#[default] #[default]
@ -748,31 +752,14 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
} }
#[hdl] #[hdl]
fn find_free_l2_reg(&self) -> Option<usize> { fn find_free_l2_reg(&self) -> Option<usize> {
// TODO: replace searching through instructions and rename tables with tracking when regs are free let rob_l2_reg_ref_counts = self.rob.l2_reg_ref_counts();
let mut allocated_regs = vec![false; L2RegNum.l2_reg_count()]; let rename_table_l2_ref_counts = self.rename_table.l2_ref_counts();
for renamed in self.rob.renamed() { let retire_rename_table_l2_ref_counts = self.retire_rename_table.l2_ref_counts();
#[hdl(sim)] rob_l2_reg_ref_counts
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()
.iter() .iter()
.chain(self.retire_rename_table.entries().iter()) .zip(rename_table_l2_ref_counts)
{ .zip(retire_rename_table_l2_ref_counts)
#[hdl(sim)] .position(|((a, b), c)| *a == 0 && *b == 0 && *c == 0)
if let HdlSome(l2) = &entry.inner().l2 {
allocated_regs[L2RegNum::value_sim(l2)] = true;
}
}
allocated_regs.iter().position(|v| !v)
} }
fn add_renamed_with_new_id( fn add_renamed_with_new_id(
&mut self, &mut self,
@ -838,7 +825,7 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
println!("moving from {src_reg:?} renamed: {renamed_reg:?}"); println!("moving from {src_reg:?} renamed: {renamed_reg:?}");
let unrenamed_dest_regs = let unrenamed_dest_regs =
MOpDestReg::regs_sim(MOpTrait::dest_reg_sim_ref(move_reg_mop)); 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 { for unrenamed_reg_num in unrenamed_dest_regs {
self.update_rename_table( self.update_rename_table(
&insn, &insn,
@ -981,7 +968,7 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
src: reg_to_free.clone(), src: reg_to_free.clone(),
}, },
); );
let l2_store_id = self.add_renamed_with_new_id( self.add_renamed_with_new_id(
&insn, &insn,
RobEntry::new( RobEntry::new(
#[hdl(sim)] #[hdl(sim)]
@ -1456,7 +1443,7 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
fn peek_retiring_insns(&self) -> Vec<SimValue<NextPcPredictorOp<C>>> { fn peek_retiring_insns(&self) -> Vec<SimValue<NextPcPredictorOp<C>>> {
let mut retval = Vec::new(); let mut retval = Vec::new();
for retire_group in self.rob.retire_groups() { 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 { if let RobEntry {
is_register_fence: _, is_register_fence: _,
done_waiting_for_register_fences: _, done_waiting_for_register_fences: _,
@ -1479,12 +1466,7 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
return retval; return retval;
} }
} }
for RobEntries { for renamed_entries in retire_group {
unrenamed: _,
rename_table_updates: _,
renamed_entries,
} in retire_group
{
let caused_cancel = renamed_entries.iter().any(|v| v.caused_cancel.is_some()); let caused_cancel = renamed_entries.iter().any(|v| v.caused_cancel.is_some());
let caused_cancel_after_retire = let caused_cancel_after_retire =
renamed_entries renamed_entries
@ -1581,12 +1563,7 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
cond_br_taken: _, cond_br_taken: _,
config: _, config: _,
} = retire; } = retire;
let Some(RobEntries { let Some((rename_table_updates, renamed_entries)) = self.rob.entries_pop_front() else {
unrenamed: _,
rename_table_updates,
renamed_entries,
}) = self.rob.entries.pop_front()
else {
unreachable!(); unreachable!();
}; };
rename_table_updates rename_table_updates

View file

@ -4,8 +4,9 @@
use crate::{ use crate::{
config::{CpuConfig, PhantomConstCpuConfig}, config::{CpuConfig, PhantomConstCpuConfig},
instruction::{L2RegNum, MOpRegNum, PRegNum, UnitNum, UnitOutRegNum}, instruction::{L2RegNum, MOpRegNum, PRegNum, UnitNum, UnitOutRegNum},
rename_execute_retire::L2RegFileLen,
}; };
use fayalite::prelude::*; use fayalite::{int::UIntInRangeInclusiveType, prelude::*};
use std::collections::BTreeSet; use std::collections::BTreeSet;
#[hdl(no_static)] #[hdl(no_static)]
@ -34,12 +35,15 @@ type MOpRegCount<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(no_static)] #[hdl(no_static)]
pub(crate) struct RenameTableDebugState<C: PhantomConstGet<CpuConfig>> { pub(crate) struct RenameTableDebugState<C: PhantomConstGet<CpuConfig>> {
entries: ArrayType<TraceAsString<RenameTableEntry<C>>, MOpRegCount<C>>, entries: ArrayType<TraceAsString<RenameTableEntry<C>>, MOpRegCount<C>>,
l2_ref_counts:
ArrayType<UIntInRangeInclusiveType<ConstUsize<0>, MOpRegCount<C>>, L2RegFileLen<C>>,
config: C, config: C,
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct RenameTable<C: PhantomConstCpuConfig> { pub(crate) struct RenameTable<C: PhantomConstCpuConfig> {
entries: Box<[SimValue<TraceAsString<RenameTableEntry<C>>>; 1 << MOpRegNum::WIDTH]>, entries: Box<[SimValue<TraceAsString<RenameTableEntry<C>>>; 1 << MOpRegNum::WIDTH]>,
l2_ref_counts: Box<[usize]>,
config: C, config: C,
} }
@ -48,11 +52,17 @@ impl<C: PhantomConstCpuConfig> Clone for RenameTable<C> {
Self { Self {
entries: self.entries.clone(), entries: self.entries.clone(),
config: self.config.clone(), config: self.config.clone(),
l2_ref_counts: self.l2_ref_counts.clone(),
} }
} }
fn clone_from(&mut self, source: &Self) { 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); entries.clone_from(&source.entries);
l2_ref_counts.clone_from(&source.l2_ref_counts);
*config = source.config; *config = source.config;
} }
} }
@ -83,7 +93,11 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
] ]
.try_into() .try_into()
.expect("size is known to match"); .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( pub(crate) fn entries(
&self, &self,
@ -92,16 +106,60 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
} }
#[hdl] #[hdl]
pub(crate) fn to_debug_state(&self) -> SimValue<RenameTableDebugState<C>> { 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]; let ty = RenameTableDebugState[*config];
#[hdl(sim)] #[hdl(sim)]
RenameTableDebugState::<_> { RenameTableDebugState::<_> {
entries: entries.to_sim_value_with_type(ty.entries), 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, config,
} }
} }
#[hdl] #[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 { match update {
RenameTableUpdate::Write { RenameTableUpdate::Write {
unrenamed_reg_num, unrenamed_reg_num,
@ -112,7 +170,7 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
return; return;
} }
println!("{rename_table_name}: Write: {unrenamed_reg_num:#x} <- {new:?}"); 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 } => { RenameTableUpdate::UpdateForReadL2Reg { dest, src } => {
let new = #[hdl(sim)] let new = #[hdl(sim)]
@ -134,7 +192,7 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
if let HdlSome(_) = &entry.inner().l1 { if let HdlSome(_) = &entry.inner().l1 {
unreachable!("l1 should be HdlNone: {entry:?}"); 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 { if let HdlSome(_) = &entry.inner().l2 {
unreachable!("l2 should be HdlNone: {entry:?}"); 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} \ "{rename_table_name}: DropAllL2RegFileOutputs: {unrenamed_reg_num:#x} \
updating from {entry:?} to {new:?}", updating from {entry:?} to {new:?}",
); );
*entry = new.to_trace_as_string(); update_entry(entry, new.to_trace_as_string());
} }
} }
} }

View file

@ -3,15 +3,19 @@
use crate::{ use crate::{
config::{CpuConfig, CpuConfigRobSize, CpuConfigUnitCount, PhantomConstCpuConfig}, config::{CpuConfig, CpuConfigRobSize, CpuConfigUnitCount, PhantomConstCpuConfig},
instruction::{MOp, MOpTrait, PRegNum, UnitNum, UnitOutRegNum}, instruction::{L2RegNum, L2RegisterFileMOp, MOp, MOpTrait, PRegNum, UnitNum, UnitOutRegNum},
next_pc::SimValueDefault, next_pc::SimValueDefault,
rename_execute_retire::{ rename_execute_retire::{
MOpId, MOpInUnitState, MOpInstance, NextPcPredictorOp, RenamedMOp, UnitCausedCancel, L2RegFileLen, MOpId, MOpInUnitState, MOpInstance, NextPcPredictorOp, RenamedMOp,
rename_table::RenameTableUpdate, zeroed, UnitCausedCancel, rename_table::RenameTableUpdate, zeroed,
}, },
util::array_vec::ArrayVec, util::array_vec::ArrayVec,
}; };
use fayalite::{int::UIntInRangeType, prelude::*, ty::StaticType}; use fayalite::{
int::{UIntInRangeInclusiveType, UIntInRangeType},
prelude::*,
ty::StaticType,
};
use std::{collections::VecDeque, mem}; use std::{collections::VecDeque, mem};
#[hdl] #[hdl]
@ -136,6 +140,33 @@ impl<C: PhantomConstCpuConfig> RobEntry<C> {
caused_cancel: caused_cancel.into_sim_value_with_type(ret_ty.caused_cancel), 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] #[hdl]
@ -161,10 +192,10 @@ impl SimValueDefault for RobEntriesDebugState {
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct RobEntries<C: PhantomConstCpuConfig> { struct RobEntries<C: PhantomConstCpuConfig> {
pub(crate) unrenamed: SimValue<MOpInstance<MOp>>, unrenamed: SimValue<MOpInstance<MOp>>,
pub(crate) rename_table_updates: Vec<RenameTableUpdate<C>>, rename_table_updates: Vec<RenameTableUpdate<C>>,
pub(crate) renamed_entries: VecDeque<RobEntry<C>>, renamed_entries: VecDeque<RobEntry<C>>,
} }
impl<C: PhantomConstCpuConfig> RobEntries<C> { impl<C: PhantomConstCpuConfig> RobEntries<C> {
@ -190,6 +221,8 @@ pub(crate) struct ReorderBufferDebugState<C: PhantomConstGet<CpuConfig>> {
entries: ArrayVec<RobEntriesDebugState, CpuConfigRobSize<C>>, entries: ArrayVec<RobEntriesDebugState, CpuConfigRobSize<C>>,
incomplete_back_entry: HdlOption<RobEntriesDebugState>, incomplete_back_entry: HdlOption<RobEntriesDebugState>,
renamed: ArrayVec<RobEntryDebugState<C>, CpuConfigRobSize<C>>, renamed: ArrayVec<RobEntryDebugState<C>, CpuConfigRobSize<C>>,
l2_reg_ref_counts:
ArrayType<UIntInRangeInclusiveType<ConstUsize<0>, CpuConfigRobSize<C>>, L2RegFileLen<C>>,
config: C, config: C,
} }
@ -201,6 +234,7 @@ impl<C: PhantomConstCpuConfig> SimValueDefault for ReorderBufferDebugState<C> {
entries, entries,
incomplete_back_entry, incomplete_back_entry,
renamed, renamed,
l2_reg_ref_counts,
config, config,
} = self; } = self;
#[hdl(sim)] #[hdl(sim)]
@ -209,6 +243,7 @@ impl<C: PhantomConstCpuConfig> SimValueDefault for ReorderBufferDebugState<C> {
entries: entries.sim_value_default(), entries: entries.sim_value_default(),
incomplete_back_entry: incomplete_back_entry.sim_value_default(), incomplete_back_entry: incomplete_back_entry.sim_value_default(),
renamed: renamed.sim_value_default(), renamed: renamed.sim_value_default(),
l2_reg_ref_counts: zeroed(l2_reg_ref_counts),
config, config,
} }
} }
@ -217,8 +252,9 @@ impl<C: PhantomConstCpuConfig> SimValueDefault for ReorderBufferDebugState<C> {
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct ReorderBuffer<C: PhantomConstCpuConfig> { pub(crate) struct ReorderBuffer<C: PhantomConstCpuConfig> {
next_renamed_mop_id: SimValue<MOpId>, next_renamed_mop_id: SimValue<MOpId>,
pub(crate) entries: VecDeque<RobEntries<C>>, entries: VecDeque<RobEntries<C>>,
pub(crate) incomplete_back_entry: Option<RobEntries<C>>, incomplete_back_entry: Option<RobEntries<C>>,
l2_reg_ref_counts: Box<[usize]>,
config: C, config: C,
} }
@ -228,15 +264,34 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
next_renamed_mop_id: MOpId.zero().into_sim_value(), next_renamed_mop_id: MOpId.zero().into_sim_value(),
entries: VecDeque::new(), entries: VecDeque::new(),
incomplete_back_entry: None, incomplete_back_entry: None,
l2_reg_ref_counts: vec![0; L2RegNum.l2_reg_count()].into_boxed_slice(),
config, config,
} }
} }
#[hdl] #[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>> { pub(crate) fn debug_state(&self) -> SimValue<ReorderBufferDebugState<C>> {
let Self { let Self {
next_renamed_mop_id, next_renamed_mop_id,
entries, entries,
incomplete_back_entry, incomplete_back_entry,
l2_reg_ref_counts,
config, config,
} = self; } = self;
let ty = ReorderBufferDebugState[*config]; let ty = ReorderBufferDebugState[*config];
@ -259,6 +314,7 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
) )
.ok() .ok()
.expect("known to fit"), .expect("known to fit"),
l2_reg_ref_counts: l2_reg_ref_counts.to_sim_value_with_type(ty.l2_reg_ref_counts),
config, config,
} }
} }
@ -270,11 +326,6 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
) -> impl DoubleEndedIterator<Item = &SimValue<MOpInstance<MOp>>> + Clone { ) -> impl DoubleEndedIterator<Item = &SimValue<MOpInstance<MOp>>> + Clone {
self.entries.iter().map(|v| &v.unrenamed) 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( fn retire_groups_unrenamed_ranges(
&self, &self,
) -> impl Clone + Iterator<Item = std::ops::Range<usize>> { ) -> impl Clone + Iterator<Item = std::ops::Range<usize>> {
@ -294,15 +345,20 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
} }
pub(crate) fn retire_groups( pub(crate) fn retire_groups(
&self, &self,
) -> impl Clone + Iterator<Item: DoubleEndedIterator<Item = &RobEntries<C>> + Clone> { ) -> impl Clone + Iterator<Item: DoubleEndedIterator<Item = &VecDeque<RobEntry<C>>> + Clone>
self.retire_groups_unrenamed_ranges() {
.map(|range| self.entries.range(range)) self.retire_groups_unrenamed_ranges().map(|range| {
self.entries
.range(range)
.map(|entries| &entries.renamed_entries)
})
} }
pub(crate) fn renamed_len(&self) -> usize { pub(crate) fn renamed_len(&self) -> usize {
let Self { let Self {
next_renamed_mop_id: _, next_renamed_mop_id: _,
entries, entries,
incomplete_back_entry, incomplete_back_entry,
l2_reg_ref_counts: _,
config: _, config: _,
} = self; } = self;
entries entries
@ -316,6 +372,7 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
next_renamed_mop_id: _, next_renamed_mop_id: _,
entries, entries,
incomplete_back_entry, incomplete_back_entry,
l2_reg_ref_counts: _,
config: _, config: _,
} = self; } = self;
entries entries
@ -328,6 +385,7 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
next_renamed_mop_id: _, next_renamed_mop_id: _,
entries, entries,
incomplete_back_entry, incomplete_back_entry,
l2_reg_ref_counts: _,
config: _, config: _,
} = self; } = self;
entries entries
@ -335,19 +393,9 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
.chain(incomplete_back_entry) .chain(incomplete_back_entry)
.flat_map(|entries| &mut entries.renamed_entries) .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>> { fn try_renamed_by_id_mut(&mut self, id: &SimValue<MOpId>) -> Option<&mut RobEntry<C>> {
self.renamed_mut().find(|v| v.mop.id == *id) 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> { pub(crate) fn renamed_by_id_mut(&mut self, id: &SimValue<MOpId>) -> &mut RobEntry<C> {
match self.try_renamed_by_id_mut(id) { match self.try_renamed_by_id_mut(id) {
Some(v) => v, Some(v) => v,
@ -366,6 +414,11 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
.into_sim_value(); .into_sim_value();
renamed.mop.id = mem::replace(&mut self.next_renamed_mop_id, replacement_id); renamed.mop.id = mem::replace(&mut self.next_renamed_mop_id, replacement_id);
println!("renamed_push_back_with_new_id: {:?}", renamed.mop); 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 let renamed_entries = &mut self
.incomplete_back_entry .incomplete_back_entry
.get_or_insert_with(|| RobEntries { .get_or_insert_with(|| RobEntries {
@ -377,6 +430,9 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
renamed_entries.push_back(renamed); renamed_entries.push_back(renamed);
&renamed_entries.back().expect("just pushed").mop.id &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>>) { pub(crate) fn finished_unrenamed_push_back(&mut self, unrenamed: &SimValue<MOpInstance<MOp>>) {
let entry = self let entry = self
.incomplete_back_entry .incomplete_back_entry
@ -393,9 +449,11 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
next_renamed_mop_id: _, next_renamed_mop_id: _,
entries, entries,
incomplete_back_entry, incomplete_back_entry,
l2_reg_ref_counts,
config: _, config: _,
} = self; } = self;
entries.clear(); entries.clear();
l2_reg_ref_counts.fill(0);
*incomplete_back_entry = None; *incomplete_back_entry = None;
} }
pub(crate) fn unrenamed_back_append_rename_table_update( 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() && 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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff