forked from libre-chip/cpu
rename_execute_retire: add reference counting for L1 registers
This commit is contained in:
parent
e0dc5d486b
commit
151683fbda
8 changed files with 16153 additions and 61 deletions
|
|
@ -716,39 +716,15 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
||||||
}
|
}
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn find_free_unit_out_reg(&self, unit_index: usize) -> Option<usize> {
|
fn find_free_unit_out_reg(&self, unit_index: usize) -> Option<usize> {
|
||||||
// TODO: replace searching through instructions and rename tables with tracking when regs are free
|
let rob_l1_reg_ref_counts = &self.rob.l1_reg_ref_counts()[unit_index];
|
||||||
let mut allocated_regs = vec![false; 1 << self.config.get().out_reg_num_width];
|
let rename_table_l1_ref_counts = &self.rename_table.l1_ref_counts()[unit_index];
|
||||||
for renamed in self.rob.renamed() {
|
let retire_rename_table_l1_ref_counts =
|
||||||
if renamed.unit_index == unit_index
|
&self.retire_rename_table.l1_ref_counts()[unit_index];
|
||||||
&& let Some(unit_out_reg_index) = renamed.unit_out_reg_index()
|
rob_l1_reg_ref_counts
|
||||||
{
|
|
||||||
allocated_regs[unit_out_reg_index] = true;
|
|
||||||
}
|
|
||||||
MOpTrait::for_each_src_reg_sim_ref(renamed.mop.mop.inner(), &mut |src_reg, _index| {
|
|
||||||
#[hdl(sim)]
|
|
||||||
let PRegNum::<_> {
|
|
||||||
unit_num,
|
|
||||||
unit_out_reg,
|
|
||||||
} = src_reg;
|
|
||||||
if Some(unit_index) == UnitNum::index_sim(&unit_num) {
|
|
||||||
allocated_regs[UnitOutRegNum::value_sim(&unit_out_reg)] = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
for entry in self
|
|
||||||
.rename_table
|
|
||||||
.entries()
|
|
||||||
.iter()
|
.iter()
|
||||||
.chain(self.retire_rename_table.entries().iter())
|
.zip(rename_table_l1_ref_counts)
|
||||||
{
|
.zip(retire_rename_table_l1_ref_counts)
|
||||||
#[hdl(sim)]
|
.position(|((a, b), c)| *a == 0 && *b == 0 && *c == 0)
|
||||||
if let HdlSome(l1) = &entry.inner().l1 {
|
|
||||||
if Some(unit_index) == UnitNum::index_sim(&l1.unit_num) {
|
|
||||||
allocated_regs[UnitOutRegNum::value_sim(&l1.unit_out_reg)] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
allocated_regs.iter().position(|v| !v)
|
|
||||||
}
|
}
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn find_free_l2_reg(&self) -> Option<usize> {
|
fn find_free_l2_reg(&self) -> Option<usize> {
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,11 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{CpuConfig, PhantomConstCpuConfig},
|
config::{CpuConfig, CpuConfig2PowOutRegNumWidth, CpuConfigUnitCount, PhantomConstCpuConfig},
|
||||||
instruction::{L2RegNum, MOpRegNum, PRegNum, UnitNum, UnitOutRegNum},
|
instruction::{L2RegNum, MOpRegNum, PRegNum, UnitNum, UnitOutRegNum},
|
||||||
rename_execute_retire::L2RegFileLen,
|
rename_execute_retire::L2RegFileLen,
|
||||||
};
|
};
|
||||||
use fayalite::{int::UIntInRangeInclusiveType, prelude::*};
|
use fayalite::{int::UIntInRangeInclusiveType, prelude::*};
|
||||||
use std::collections::BTreeSet;
|
|
||||||
|
|
||||||
#[hdl(no_static)]
|
#[hdl(no_static)]
|
||||||
pub(crate) struct RenameTableEntry<C: PhantomConstGet<CpuConfig>> {
|
pub(crate) struct RenameTableEntry<C: PhantomConstGet<CpuConfig>> {
|
||||||
|
|
@ -35,6 +34,13 @@ 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>>,
|
||||||
|
l1_ref_counts: ArrayType<
|
||||||
|
ArrayType<
|
||||||
|
UIntInRangeInclusiveType<ConstUsize<0>, MOpRegCount<C>>,
|
||||||
|
CpuConfig2PowOutRegNumWidth<C>,
|
||||||
|
>,
|
||||||
|
CpuConfigUnitCount<C>,
|
||||||
|
>,
|
||||||
l2_ref_counts:
|
l2_ref_counts:
|
||||||
ArrayType<UIntInRangeInclusiveType<ConstUsize<0>, MOpRegCount<C>>, L2RegFileLen<C>>,
|
ArrayType<UIntInRangeInclusiveType<ConstUsize<0>, MOpRegCount<C>>, L2RegFileLen<C>>,
|
||||||
config: C,
|
config: C,
|
||||||
|
|
@ -43,6 +49,7 @@ pub(crate) struct RenameTableDebugState<C: PhantomConstGet<CpuConfig>> {
|
||||||
#[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]>,
|
||||||
|
l1_ref_counts: Box<[Box<[usize]>]>,
|
||||||
l2_ref_counts: Box<[usize]>,
|
l2_ref_counts: Box<[usize]>,
|
||||||
config: C,
|
config: C,
|
||||||
}
|
}
|
||||||
|
|
@ -52,16 +59,19 @@ 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(),
|
||||||
|
l1_ref_counts: self.l1_ref_counts.clone(),
|
||||||
l2_ref_counts: self.l2_ref_counts.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 {
|
let Self {
|
||||||
entries,
|
entries,
|
||||||
|
l1_ref_counts,
|
||||||
l2_ref_counts,
|
l2_ref_counts,
|
||||||
config,
|
config,
|
||||||
} = self;
|
} = self;
|
||||||
entries.clone_from(&source.entries);
|
entries.clone_from(&source.entries);
|
||||||
|
l1_ref_counts.clone_from(&source.l1_ref_counts);
|
||||||
l2_ref_counts.clone_from(&source.l2_ref_counts);
|
l2_ref_counts.clone_from(&source.l2_ref_counts);
|
||||||
*config = source.config;
|
*config = source.config;
|
||||||
}
|
}
|
||||||
|
|
@ -95,6 +105,11 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
||||||
.expect("size is known to match");
|
.expect("size is known to match");
|
||||||
Self {
|
Self {
|
||||||
entries,
|
entries,
|
||||||
|
l1_ref_counts: vec![
|
||||||
|
vec![0; CpuConfig2PowOutRegNumWidth[config]].into_boxed_slice();
|
||||||
|
CpuConfigUnitCount[config]
|
||||||
|
]
|
||||||
|
.into_boxed_slice(),
|
||||||
l2_ref_counts: vec![0; L2RegFileLen[config]].into_boxed_slice(),
|
l2_ref_counts: vec![0; L2RegFileLen[config]].into_boxed_slice(),
|
||||||
config,
|
config,
|
||||||
}
|
}
|
||||||
|
|
@ -108,6 +123,7 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
||||||
pub(crate) fn to_debug_state(&self) -> SimValue<RenameTableDebugState<C>> {
|
pub(crate) fn to_debug_state(&self) -> SimValue<RenameTableDebugState<C>> {
|
||||||
let Self {
|
let Self {
|
||||||
entries,
|
entries,
|
||||||
|
l1_ref_counts,
|
||||||
l2_ref_counts,
|
l2_ref_counts,
|
||||||
config,
|
config,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
@ -115,11 +131,32 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
RenameTableDebugState::<_> {
|
RenameTableDebugState::<_> {
|
||||||
entries: entries.to_sim_value_with_type(ty.entries),
|
entries: entries.to_sim_value_with_type(ty.entries),
|
||||||
|
l1_ref_counts: l1_ref_counts.to_sim_value_with_type(ty.l1_ref_counts),
|
||||||
l2_ref_counts: l2_ref_counts.to_sim_value_with_type(ty.l2_ref_counts),
|
l2_ref_counts: l2_ref_counts.to_sim_value_with_type(ty.l2_ref_counts),
|
||||||
config,
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
pub(crate) fn l1_ref_counts(&self) -> &[Box<[usize]>] {
|
||||||
|
let mut expected = vec![
|
||||||
|
vec![0usize; CpuConfig2PowOutRegNumWidth[self.config]]
|
||||||
|
.into_boxed_slice();
|
||||||
|
CpuConfigUnitCount[self.config]
|
||||||
|
];
|
||||||
|
for entry in self.entries.iter() {
|
||||||
|
#[hdl(sim)]
|
||||||
|
let RenameTableEntry::<_> { l1, l2: _ } = entry.inner();
|
||||||
|
#[hdl(sim)]
|
||||||
|
if let HdlSome(l1) = l1 {
|
||||||
|
if let Some(unit_index) = UnitNum::index_sim(&l1.unit_num) {
|
||||||
|
expected[unit_index][UnitOutRegNum::value_sim(&l1.unit_out_reg)] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_eq!(*expected, *self.l1_ref_counts);
|
||||||
|
&self.l1_ref_counts
|
||||||
|
}
|
||||||
|
#[hdl]
|
||||||
pub(crate) fn l2_ref_counts(&self) -> &[usize] {
|
pub(crate) fn l2_ref_counts(&self) -> &[usize] {
|
||||||
let mut expected = vec![0usize; L2RegNum.l2_reg_count()];
|
let mut expected = vec![0usize; L2RegNum.l2_reg_count()];
|
||||||
for entry in self.entries.iter() {
|
for entry in self.entries.iter() {
|
||||||
|
|
@ -139,7 +176,17 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
||||||
|entry: &mut SimValue<TraceAsString<RenameTableEntry<C>>>,
|
|entry: &mut SimValue<TraceAsString<RenameTableEntry<C>>>,
|
||||||
new: SimValue<TraceAsString<RenameTableEntry<C>>>| {
|
new: SimValue<TraceAsString<RenameTableEntry<C>>>| {
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
let RenameTableEntry::<_> { l1: _, l2 } = entry.inner();
|
let RenameTableEntry::<_> { l1, l2 } = entry.inner();
|
||||||
|
#[hdl(sim)]
|
||||||
|
if let HdlSome(l1) = l1 {
|
||||||
|
if let Some(unit_index) = UnitNum::index_sim(&l1.unit_num) {
|
||||||
|
let ref_count = &mut self.l1_ref_counts[unit_index]
|
||||||
|
[UnitOutRegNum::value_sim(&l1.unit_out_reg)];
|
||||||
|
*ref_count = ref_count.checked_sub(1).unwrap_or_else(|| {
|
||||||
|
unreachable!("{rename_table_name}: l1 ref count went negative: {l1:?}")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
if let HdlSome(l2) = l2 {
|
if let HdlSome(l2) = l2 {
|
||||||
let ref_count = &mut self.l2_ref_counts[L2RegNum::value_sim(l2)];
|
let ref_count = &mut self.l2_ref_counts[L2RegNum::value_sim(l2)];
|
||||||
|
|
@ -148,15 +195,27 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
let RenameTableEntry::<_> { l1: _, l2 } = new.inner();
|
let RenameTableEntry::<_> { l1, l2 } = new.inner();
|
||||||
|
#[hdl(sim)]
|
||||||
|
if let HdlSome(l1) = l1 {
|
||||||
|
if let Some(unit_index) = UnitNum::index_sim(&l1.unit_num) {
|
||||||
|
let ref_count = &mut self.l1_ref_counts[unit_index]
|
||||||
|
[UnitOutRegNum::value_sim(&l1.unit_out_reg)];
|
||||||
|
*ref_count += 1;
|
||||||
|
assert!(
|
||||||
|
*ref_count <= 1 << MOpRegNum::WIDTH,
|
||||||
|
"{rename_table_name}: l1 ref count overflowed: {l1:?}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
if let HdlSome(l2) = l2 {
|
if let HdlSome(l2) = l2 {
|
||||||
let ref_count = &mut self.l2_ref_counts[L2RegNum::value_sim(l2)];
|
let ref_count = &mut self.l2_ref_counts[L2RegNum::value_sim(l2)];
|
||||||
*ref_count += 1;
|
*ref_count += 1;
|
||||||
assert!(
|
assert!(
|
||||||
*ref_count <= L2RegNum.l2_reg_count(),
|
*ref_count <= 1 << MOpRegNum::WIDTH,
|
||||||
"{rename_table_name}: l2 ref count overflowed: {l2:?}",
|
"{rename_table_name}: l2 ref count overflowed: {l2:?}",
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
*entry = new;
|
*entry = new;
|
||||||
};
|
};
|
||||||
|
|
@ -244,15 +303,9 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
||||||
}
|
}
|
||||||
#[hdl]
|
#[hdl]
|
||||||
pub(crate) fn used_unit_out_reg_count(&self, unit_index: usize) -> usize {
|
pub(crate) fn used_unit_out_reg_count(&self, unit_index: usize) -> usize {
|
||||||
let mut seen = BTreeSet::new();
|
self.l1_ref_counts()[unit_index]
|
||||||
for entry in self.entries.iter() {
|
.iter()
|
||||||
#[hdl(sim)]
|
.filter(|ref_count| **ref_count != 0)
|
||||||
if let HdlSome(v) = &entry.inner().l1 {
|
.count()
|
||||||
if UnitNum::index_sim(&v.unit_num) == Some(unit_index) {
|
|
||||||
seen.insert(UnitOutRegNum::value_sim(&v.unit_out_reg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
seen.len()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,14 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{CpuConfig, CpuConfigRobSize, CpuConfigUnitCount, PhantomConstCpuConfig},
|
config::{
|
||||||
instruction::{L2RegNum, L2RegisterFileMOp, MOp, MOpTrait, PRegNum, UnitNum, UnitOutRegNum},
|
CpuConfig, CpuConfig2PowOutRegNumWidth, CpuConfigRobSize, CpuConfigUnitCount,
|
||||||
|
PhantomConstCpuConfig,
|
||||||
|
},
|
||||||
|
instruction::{
|
||||||
|
COMMON_MOP_SRC_LEN, L2RegNum, L2RegisterFileMOp, MOp, MOpTrait, PRegNum, UnitNum,
|
||||||
|
UnitOutRegNum,
|
||||||
|
},
|
||||||
next_pc::SimValueDefault,
|
next_pc::SimValueDefault,
|
||||||
rename_execute_retire::{
|
rename_execute_retire::{
|
||||||
L2RegFileLen, MOpId, MOpInUnitState, MOpInstance, NextPcPredictorOp, RenamedMOp,
|
L2RegFileLen, MOpId, MOpInUnitState, MOpInstance, NextPcPredictorOp, RenamedMOp,
|
||||||
|
|
@ -215,12 +221,22 @@ impl<C: PhantomConstCpuConfig> RobEntries<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[hdl(get(|c| c.rob_size.get() * (1 + COMMON_MOP_SRC_LEN)))]
|
||||||
|
type L1RegMaxRefCount<C: PhantomConstGet<CpuConfig>> = DynSize;
|
||||||
|
|
||||||
#[hdl(no_static)]
|
#[hdl(no_static)]
|
||||||
pub(crate) struct ReorderBufferDebugState<C: PhantomConstGet<CpuConfig>> {
|
pub(crate) struct ReorderBufferDebugState<C: PhantomConstGet<CpuConfig>> {
|
||||||
next_renamed_mop_id: MOpId,
|
next_renamed_mop_id: MOpId,
|
||||||
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>>,
|
||||||
|
l1_reg_ref_counts: ArrayType<
|
||||||
|
ArrayType<
|
||||||
|
UIntInRangeInclusiveType<ConstUsize<0>, L1RegMaxRefCount<C>>,
|
||||||
|
CpuConfig2PowOutRegNumWidth<C>,
|
||||||
|
>,
|
||||||
|
CpuConfigUnitCount<C>,
|
||||||
|
>,
|
||||||
l2_reg_ref_counts:
|
l2_reg_ref_counts:
|
||||||
ArrayType<UIntInRangeInclusiveType<ConstUsize<0>, CpuConfigRobSize<C>>, L2RegFileLen<C>>,
|
ArrayType<UIntInRangeInclusiveType<ConstUsize<0>, CpuConfigRobSize<C>>, L2RegFileLen<C>>,
|
||||||
config: C,
|
config: C,
|
||||||
|
|
@ -234,6 +250,7 @@ impl<C: PhantomConstCpuConfig> SimValueDefault for ReorderBufferDebugState<C> {
|
||||||
entries,
|
entries,
|
||||||
incomplete_back_entry,
|
incomplete_back_entry,
|
||||||
renamed,
|
renamed,
|
||||||
|
l1_reg_ref_counts,
|
||||||
l2_reg_ref_counts,
|
l2_reg_ref_counts,
|
||||||
config,
|
config,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
@ -243,6 +260,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(),
|
||||||
|
l1_reg_ref_counts: zeroed(l1_reg_ref_counts),
|
||||||
l2_reg_ref_counts: zeroed(l2_reg_ref_counts),
|
l2_reg_ref_counts: zeroed(l2_reg_ref_counts),
|
||||||
config,
|
config,
|
||||||
}
|
}
|
||||||
|
|
@ -254,6 +272,7 @@ pub(crate) struct ReorderBuffer<C: PhantomConstCpuConfig> {
|
||||||
next_renamed_mop_id: SimValue<MOpId>,
|
next_renamed_mop_id: SimValue<MOpId>,
|
||||||
entries: VecDeque<RobEntries<C>>,
|
entries: VecDeque<RobEntries<C>>,
|
||||||
incomplete_back_entry: Option<RobEntries<C>>,
|
incomplete_back_entry: Option<RobEntries<C>>,
|
||||||
|
l1_reg_ref_counts: Box<[Box<[usize]>]>,
|
||||||
l2_reg_ref_counts: Box<[usize]>,
|
l2_reg_ref_counts: Box<[usize]>,
|
||||||
config: C,
|
config: C,
|
||||||
}
|
}
|
||||||
|
|
@ -264,23 +283,45 @@ 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,
|
||||||
|
l1_reg_ref_counts: vec![
|
||||||
|
vec![0; CpuConfig2PowOutRegNumWidth[config]].into_boxed_slice();
|
||||||
|
CpuConfigUnitCount[config]
|
||||||
|
]
|
||||||
|
.into_boxed_slice(),
|
||||||
l2_reg_ref_counts: vec![0; L2RegNum.l2_reg_count()].into_boxed_slice(),
|
l2_reg_ref_counts: vec![0; L2RegNum.l2_reg_count()].into_boxed_slice(),
|
||||||
config,
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
pub(crate) fn l1_reg_ref_counts(&self) -> &[Box<[usize]>] {
|
||||||
|
let mut expected = vec![
|
||||||
|
vec![0usize; CpuConfig2PowOutRegNumWidth[self.config]]
|
||||||
|
.into_boxed_slice();
|
||||||
|
CpuConfigUnitCount[self.config]
|
||||||
|
];
|
||||||
|
for entry in self.renamed() {
|
||||||
|
entry.for_each_reg(
|
||||||
|
(),
|
||||||
|
|(), l1| {
|
||||||
|
if let Some(unit_index) = UnitNum::index_sim(&l1.unit_num) {
|
||||||
|
expected[unit_index][UnitOutRegNum::value_sim(&l1.unit_out_reg)] += 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|(), _l2| {},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
assert_eq!(*expected, *self.l1_reg_ref_counts);
|
||||||
|
&self.l1_reg_ref_counts
|
||||||
|
}
|
||||||
|
#[hdl]
|
||||||
pub(crate) fn l2_reg_ref_counts(&self) -> &[usize] {
|
pub(crate) fn l2_reg_ref_counts(&self) -> &[usize] {
|
||||||
let mut expected = vec![0usize; L2RegNum.l2_reg_count()];
|
let mut expected = vec![0usize; L2RegNum.l2_reg_count()];
|
||||||
for entry in self.renamed() {
|
for entry in self.renamed() {
|
||||||
#[hdl(sim)]
|
entry.for_each_reg(
|
||||||
if let RenamedMOp::<_>::TransformedMove(mop) = entry.mop.mop.inner() {
|
(),
|
||||||
let l2_reg = #[hdl(sim)]
|
|(), _l1| {},
|
||||||
match mop {
|
|(), l2| expected[L2RegNum::value_sim(l2)] += 1,
|
||||||
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);
|
assert_eq!(*expected, *self.l2_reg_ref_counts);
|
||||||
&self.l2_reg_ref_counts
|
&self.l2_reg_ref_counts
|
||||||
|
|
@ -291,6 +332,7 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
||||||
next_renamed_mop_id,
|
next_renamed_mop_id,
|
||||||
entries,
|
entries,
|
||||||
incomplete_back_entry,
|
incomplete_back_entry,
|
||||||
|
l1_reg_ref_counts,
|
||||||
l2_reg_ref_counts,
|
l2_reg_ref_counts,
|
||||||
config,
|
config,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
@ -314,6 +356,7 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
||||||
)
|
)
|
||||||
.ok()
|
.ok()
|
||||||
.expect("known to fit"),
|
.expect("known to fit"),
|
||||||
|
l1_reg_ref_counts: l1_reg_ref_counts.to_sim_value_with_type(ty.l1_reg_ref_counts),
|
||||||
l2_reg_ref_counts: l2_reg_ref_counts.to_sim_value_with_type(ty.l2_reg_ref_counts),
|
l2_reg_ref_counts: l2_reg_ref_counts.to_sim_value_with_type(ty.l2_reg_ref_counts),
|
||||||
config,
|
config,
|
||||||
}
|
}
|
||||||
|
|
@ -358,6 +401,7 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
||||||
next_renamed_mop_id: _,
|
next_renamed_mop_id: _,
|
||||||
entries,
|
entries,
|
||||||
incomplete_back_entry,
|
incomplete_back_entry,
|
||||||
|
l1_reg_ref_counts: _,
|
||||||
l2_reg_ref_counts: _,
|
l2_reg_ref_counts: _,
|
||||||
config: _,
|
config: _,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
@ -372,6 +416,7 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
||||||
next_renamed_mop_id: _,
|
next_renamed_mop_id: _,
|
||||||
entries,
|
entries,
|
||||||
incomplete_back_entry,
|
incomplete_back_entry,
|
||||||
|
l1_reg_ref_counts: _,
|
||||||
l2_reg_ref_counts: _,
|
l2_reg_ref_counts: _,
|
||||||
config: _,
|
config: _,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
@ -385,6 +430,7 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
||||||
next_renamed_mop_id: _,
|
next_renamed_mop_id: _,
|
||||||
entries,
|
entries,
|
||||||
incomplete_back_entry,
|
incomplete_back_entry,
|
||||||
|
l1_reg_ref_counts: _,
|
||||||
l2_reg_ref_counts: _,
|
l2_reg_ref_counts: _,
|
||||||
config: _,
|
config: _,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
@ -416,7 +462,12 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
||||||
println!("renamed_push_back_with_new_id: {:?}", renamed.mop);
|
println!("renamed_push_back_with_new_id: {:?}", renamed.mop);
|
||||||
renamed.for_each_reg(
|
renamed.for_each_reg(
|
||||||
(),
|
(),
|
||||||
|(), _l1| {},
|
|(), l1| {
|
||||||
|
if let Some(unit_index) = UnitNum::index_sim(&l1.unit_num) {
|
||||||
|
self.l1_reg_ref_counts[unit_index]
|
||||||
|
[UnitOutRegNum::value_sim(&l1.unit_out_reg)] += 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|(), l2| self.l2_reg_ref_counts[L2RegNum::value_sim(l2)] += 1,
|
|(), l2| self.l2_reg_ref_counts[L2RegNum::value_sim(l2)] += 1,
|
||||||
);
|
);
|
||||||
let renamed_entries = &mut self
|
let renamed_entries = &mut self
|
||||||
|
|
@ -449,11 +500,15 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
||||||
next_renamed_mop_id: _,
|
next_renamed_mop_id: _,
|
||||||
entries,
|
entries,
|
||||||
incomplete_back_entry,
|
incomplete_back_entry,
|
||||||
|
l1_reg_ref_counts,
|
||||||
l2_reg_ref_counts,
|
l2_reg_ref_counts,
|
||||||
config: _,
|
config: _,
|
||||||
} = self;
|
} = self;
|
||||||
entries.clear();
|
entries.clear();
|
||||||
l2_reg_ref_counts.fill(0);
|
l2_reg_ref_counts.fill(0);
|
||||||
|
for i in l1_reg_ref_counts {
|
||||||
|
i.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(
|
||||||
|
|
@ -487,7 +542,15 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
||||||
for entry in &renamed_entries {
|
for entry in &renamed_entries {
|
||||||
entry.for_each_reg(
|
entry.for_each_reg(
|
||||||
(),
|
(),
|
||||||
|(), _l1| {},
|
|(), l1| {
|
||||||
|
if let Some(unit_index) = UnitNum::index_sim(&l1.unit_num) {
|
||||||
|
let ref_count = &mut self.l1_reg_ref_counts[unit_index]
|
||||||
|
[UnitOutRegNum::value_sim(&l1.unit_out_reg)];
|
||||||
|
*ref_count = ref_count.checked_sub(1).unwrap_or_else(|| {
|
||||||
|
unreachable!("ReorderBuffer: l1 ref count went negative: {l1:?}")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|(), l2| {
|
|(), l2| {
|
||||||
let ref_count = &mut self.l2_reg_ref_counts[L2RegNum::value_sim(l2)];
|
let ref_count = &mut self.l2_reg_ref_counts[L2RegNum::value_sim(l2)];
|
||||||
*ref_count = ref_count.checked_sub(1).unwrap_or_else(|| {
|
*ref_count = ref_count.checked_sub(1).unwrap_or_else(|| {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
2899
crates/cpu/tests/expected/rename_execute_retire_head_n1.vcd
generated
2899
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