WIP fixing deadlock when running rename_execute_retire_save_restore_gprs
Some checks failed
/ test (pull_request) Failing after 5m52s
Some checks failed
/ test (pull_request) Failing after 5m52s
This commit is contained in:
parent
3e08a282ec
commit
ed331a3a96
1 changed files with 113 additions and 56 deletions
|
|
@ -256,16 +256,21 @@ impl<C: PhantomConstCpuConfig> SimValueDefault for RenameExecuteRetireDebugState
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(no_static)]
|
#[hdl(no_static)]
|
||||||
enum RenameTableEntry<C: PhantomConstGet<CpuConfig>> {
|
struct RenameTableEntry<C: PhantomConstGet<CpuConfig>> {
|
||||||
L1(PRegNum<C>),
|
l1: HdlOption<PRegNum<C>>,
|
||||||
L2(L2RegNum),
|
l2: HdlOption<L2RegNum>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: PhantomConstCpuConfig> RenameTableEntry<C> {
|
impl<C: PhantomConstCpuConfig> RenameTableEntry<C> {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn const_zero(self) -> SimValue<Self> {
|
fn const_zero(self) -> SimValue<Self> {
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
self.L1(self.L1.const_zero())
|
Self {
|
||||||
|
l1: #[hdl(sim)]
|
||||||
|
(self.l1).HdlSome(self.l1.HdlSome.const_zero()),
|
||||||
|
l2: #[hdl(sim)]
|
||||||
|
HdlNone(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -313,6 +318,7 @@ enum RenameTableUpdate<C: PhantomConstCpuConfig> {
|
||||||
dest: SimValue<L2RegNum>,
|
dest: SimValue<L2RegNum>,
|
||||||
src: SimValue<PRegNum<C>>,
|
src: SimValue<PRegNum<C>>,
|
||||||
},
|
},
|
||||||
|
DropAllL2RegFileOutputs,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
||||||
|
|
@ -352,39 +358,69 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
||||||
}
|
}
|
||||||
RenameTableUpdate::UpdateForReadL2Reg { dest, src } => {
|
RenameTableUpdate::UpdateForReadL2Reg { dest, src } => {
|
||||||
let new = #[hdl(sim)]
|
let new = #[hdl(sim)]
|
||||||
(RenameTableEntry[self.config]).L1(dest);
|
RenameTableEntry::<_> {
|
||||||
|
l1: #[hdl(sim)]
|
||||||
|
(HdlOption[dest.ty()]).HdlSome(dest),
|
||||||
|
l2: #[hdl(sim)]
|
||||||
|
HdlSome(src),
|
||||||
|
};
|
||||||
for (unrenamed_reg_num, entry) in self.entries.iter_mut().enumerate() {
|
for (unrenamed_reg_num, entry) in self.entries.iter_mut().enumerate() {
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
match entry.inner() {
|
if let HdlSome(l2) = &entry.inner().l2 {
|
||||||
RenameTableEntry::<_>::L1(_) => {}
|
if L2RegNum::value_sim(l2) == L2RegNum::value_sim(src) {
|
||||||
RenameTableEntry::<_>::L2(l2) => {
|
println!(
|
||||||
if L2RegNum::value_sim(l2) == L2RegNum::value_sim(src) {
|
"{rename_table_name}: UpdateForReadL2Reg: {unrenamed_reg_num:#x} \
|
||||||
println!(
|
updating from {entry:?} to {new:?}",
|
||||||
"{rename_table_name}: UpdateForReadL2Reg: {unrenamed_reg_num:#x} \
|
);
|
||||||
updating from {entry:?} to {new:?}",
|
#[hdl(sim)]
|
||||||
);
|
if let HdlSome(_) = &entry.inner().l1 {
|
||||||
*entry = new.to_trace_as_string();
|
unreachable!("l1 should be HdlNone: {entry:?}");
|
||||||
}
|
}
|
||||||
|
*entry = new.to_trace_as_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RenameTableUpdate::UpdateForWriteL2Reg { dest, src } => {
|
RenameTableUpdate::UpdateForWriteL2Reg { dest, src } => {
|
||||||
let new = #[hdl(sim)]
|
let new = #[hdl(sim)]
|
||||||
(RenameTableEntry[self.config]).L2(dest);
|
RenameTableEntry::<_> {
|
||||||
|
l1: #[hdl(sim)]
|
||||||
|
(HdlOption[src.ty()]).HdlNone(),
|
||||||
|
l2: #[hdl(sim)]
|
||||||
|
HdlSome(dest),
|
||||||
|
};
|
||||||
for (unrenamed_reg_num, entry) in self.entries.iter_mut().enumerate() {
|
for (unrenamed_reg_num, entry) in self.entries.iter_mut().enumerate() {
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
match entry.inner() {
|
if let HdlSome(l1) = &entry.inner().l1 {
|
||||||
RenameTableEntry::<_>::L1(l1) => {
|
if l1 == src {
|
||||||
if l1 == src {
|
println!(
|
||||||
println!(
|
"{rename_table_name}: UpdateForWriteL2Reg: {unrenamed_reg_num:#x} \
|
||||||
"{rename_table_name}: UpdateForWriteL2Reg: {unrenamed_reg_num:#x} \
|
updating from {entry:?} to {new:?}",
|
||||||
updating from {entry:?} to {new:?}",
|
);
|
||||||
);
|
#[hdl(sim)]
|
||||||
*entry = new.to_trace_as_string();
|
if let HdlSome(_) = &entry.inner().l2 {
|
||||||
|
unreachable!("l2 should be HdlNone: {entry:?}");
|
||||||
}
|
}
|
||||||
|
*entry = new.to_trace_as_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RenameTableUpdate::DropAllL2RegFileOutputs => {
|
||||||
|
for (unrenamed_reg_num, entry) in self.entries.iter_mut().enumerate() {
|
||||||
|
#[hdl(sim)]
|
||||||
|
if let HdlSome(_) = &entry.inner().l1 {
|
||||||
|
#[hdl(sim)]
|
||||||
|
if let HdlSome(_) = &entry.inner().l2 {
|
||||||
|
let mut new = entry.inner().clone();
|
||||||
|
new.l1 = #[hdl(sim)]
|
||||||
|
(new.l1.ty()).HdlNone();
|
||||||
|
println!(
|
||||||
|
"{rename_table_name}: DropAllL2RegFileOutputs: {unrenamed_reg_num:#x} \
|
||||||
|
updating from {entry:?} to {new:?}",
|
||||||
|
);
|
||||||
|
*entry = new.to_trace_as_string();
|
||||||
}
|
}
|
||||||
RenameTableEntry::<_>::L2(_) => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -395,13 +431,10 @@ impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
||||||
let mut seen = BTreeSet::new();
|
let mut seen = BTreeSet::new();
|
||||||
for entry in self.entries.iter() {
|
for entry in self.entries.iter() {
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
match entry.inner() {
|
if let HdlSome(v) = &entry.inner().l1 {
|
||||||
RenameTableEntry::<_>::L1(v) => {
|
if UnitNum::index_sim(&v.unit_num) == Some(unit_index) {
|
||||||
if UnitNum::index_sim(&v.unit_num) == Some(unit_index) {
|
seen.insert(UnitOutRegNum::value_sim(&v.unit_out_reg));
|
||||||
seen.insert(UnitOutRegNum::value_sim(&v.unit_out_reg));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RenameTableEntry::<_>::L2(_) => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
seen.len()
|
seen.len()
|
||||||
|
|
@ -581,7 +614,7 @@ impl MOpInUnitState {
|
||||||
Self::FinishedAndOrCausedCancel => None,
|
Self::FinishedAndOrCausedCancel => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn is_completed(self) -> bool {
|
fn is_finished_and_or_caused_cancel(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::NotYetEnqueued => false,
|
Self::NotYetEnqueued => false,
|
||||||
Self::InputsNotReadySpeculative { .. } => false,
|
Self::InputsNotReadySpeculative { .. } => false,
|
||||||
|
|
@ -1019,6 +1052,12 @@ impl<C: PhantomConstCpuConfig> ReorderBuffer<C> {
|
||||||
.rename_table_updates
|
.rename_table_updates
|
||||||
.push(update);
|
.push(update);
|
||||||
}
|
}
|
||||||
|
fn all_mops_are_finished_and_or_caused_cancel(&self) -> bool {
|
||||||
|
self.renamed().next().is_none_or(|entry| {
|
||||||
|
entry.all_prior_mops_are_finished
|
||||||
|
&& entry.mop_in_unit_state.is_finished_and_or_caused_cancel()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SimOnlyString = SimOnly<String>;
|
type SimOnlyString = SimOnly<String>;
|
||||||
|
|
@ -1222,7 +1261,9 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
||||||
fn space_available_for_unit(&self, unit_index: usize) -> usize {
|
fn space_available_for_unit(&self, unit_index: usize) -> usize {
|
||||||
let mut retval = self.config.get().unit_max_in_flight(unit_index);
|
let mut retval = self.config.get().unit_max_in_flight(unit_index);
|
||||||
for renamed in self.rob.renamed() {
|
for renamed in self.rob.renamed() {
|
||||||
if renamed.unit_index == unit_index && !renamed.mop_in_unit_state.is_completed() {
|
if renamed.unit_index == unit_index
|
||||||
|
&& !renamed.mop_in_unit_state.is_finished_and_or_caused_cancel()
|
||||||
|
{
|
||||||
let Some(v) = NonZero::new(retval.get() - 1) else {
|
let Some(v) = NonZero::new(retval.get() - 1) else {
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
@ -1259,13 +1300,10 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
||||||
.chain(self.retire_rename_table.entries.iter())
|
.chain(self.retire_rename_table.entries.iter())
|
||||||
{
|
{
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
match entry.inner() {
|
if let HdlSome(l1) = &entry.inner().l1 {
|
||||||
RenameTableEntry::<_>::L1(entry) => {
|
if Some(unit_index) == UnitNum::index_sim(&l1.unit_num) {
|
||||||
if Some(unit_index) == UnitNum::index_sim(&entry.unit_num) {
|
allocated_regs[UnitOutRegNum::value_sim(&l1.unit_out_reg)] = true;
|
||||||
allocated_regs[UnitOutRegNum::value_sim(&entry.unit_out_reg)] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RenameTableEntry::<_>::L2(_) => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
allocated_regs.iter().position(|v| !v)
|
allocated_regs.iter().position(|v| !v)
|
||||||
|
|
@ -1292,11 +1330,8 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
||||||
.chain(self.retire_rename_table.entries.iter())
|
.chain(self.retire_rename_table.entries.iter())
|
||||||
{
|
{
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
match entry.inner() {
|
if let HdlSome(l2) = &entry.inner().l2 {
|
||||||
RenameTableEntry::<_>::L1(_) => {}
|
allocated_regs[L2RegNum::value_sim(l2)] = true;
|
||||||
RenameTableEntry::<_>::L2(entry) => {
|
|
||||||
allocated_regs[L2RegNum::value_sim(entry)] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
allocated_regs.iter().position(|v| !v)
|
allocated_regs.iter().position(|v| !v)
|
||||||
|
|
@ -1499,13 +1534,10 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
||||||
"try_rename: checking that mop src reg ({renamed:?}) doesn't conflict with picked reg"
|
"try_rename: checking that mop src reg ({renamed:?}) doesn't conflict with picked reg"
|
||||||
);
|
);
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
match renamed.inner() {
|
if let HdlSome(l1) = &renamed.inner().l1 {
|
||||||
RenameTableEntry::<_>::L1(v) => {
|
if reg_to_free == *l1 {
|
||||||
if reg_to_free == *v {
|
any_collisions = true;
|
||||||
any_collisions = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RenameTableEntry::<_>::L2(_) => {}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if any_collisions {
|
if any_collisions {
|
||||||
|
|
@ -1600,10 +1632,16 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
||||||
let renamed = &self.rename_table.entries[MOpRegNum::reg_num_sim(&src_reg) as usize];
|
let renamed = &self.rename_table.entries[MOpRegNum::reg_num_sim(&src_reg) as usize];
|
||||||
println!("renaming src[{index}] from {src_reg:?} to {renamed:?}");
|
println!("renaming src[{index}] from {src_reg:?} to {renamed:?}");
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
match renamed.inner() {
|
match &renamed.inner().l1 {
|
||||||
RenameTableEntry::<_>::L1(v) => v.clone(),
|
HdlSome(l1) => l1.clone(),
|
||||||
RenameTableEntry::<_>::L2(v) => {
|
HdlNone => {
|
||||||
needed_load.get_or_insert_with(|| v.clone());
|
let l2 = #[hdl(sim)]
|
||||||
|
if let HdlSome(l2) = &renamed.inner().l2 {
|
||||||
|
l2
|
||||||
|
} else {
|
||||||
|
unreachable!("rename table entry has neither l1 nor l2: {src_reg:?}");
|
||||||
|
};
|
||||||
|
needed_load.get_or_insert_with(|| l2.clone());
|
||||||
PRegNum[self.config].const_zero_sim()
|
PRegNum[self.config].const_zero_sim()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1647,7 +1685,19 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
||||||
self.l2_reg_file_unit_index,
|
self.l2_reg_file_unit_index,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
println!("try_rename: l2 reg file has no space and/or has no free output regs");
|
println!("try_rename: read l2 reg");
|
||||||
|
Err(
|
||||||
|
#[hdl(sim)]
|
||||||
|
RenameDelayedEntry::<_> {
|
||||||
|
mop: insn,
|
||||||
|
delayed_for_l2_store,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else if self.rob.all_mops_are_finished_and_or_caused_cancel() {
|
||||||
|
todo!("dropping the L2 register file's outputs still doesn't fix deadlocks");
|
||||||
|
// TODO: add proper WaW and WaR tracking for renamed registers
|
||||||
|
println!("try_rename: dropping all l2 reg file outputs");
|
||||||
|
self.update_rename_table(&insn, RenameTableUpdate::DropAllL2RegFileOutputs);
|
||||||
Err(
|
Err(
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
RenameDelayedEntry::<_> {
|
RenameDelayedEntry::<_> {
|
||||||
|
|
@ -1656,7 +1706,9 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
println!("try_rename: l2 reg file has no space and/or has no free output regs");
|
println!(
|
||||||
|
"try_rename: waiting for all mops to finish before dropping all l2 reg file outputs"
|
||||||
|
);
|
||||||
Err(
|
Err(
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
RenameDelayedEntry::<_> {
|
RenameDelayedEntry::<_> {
|
||||||
|
|
@ -1673,7 +1725,12 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
||||||
)
|
)
|
||||||
.into_trace_as_string();
|
.into_trace_as_string();
|
||||||
let renamed_dest_reg = #[hdl(sim)]
|
let renamed_dest_reg = #[hdl(sim)]
|
||||||
(RenameTableEntry[self.config]).L1(renamed_dest_reg);
|
RenameTableEntry::<_> {
|
||||||
|
l1: #[hdl(sim)]
|
||||||
|
(HdlOption[renamed_dest_reg.ty()]).HdlSome(renamed_dest_reg),
|
||||||
|
l2: #[hdl(sim)]
|
||||||
|
HdlNone(),
|
||||||
|
};
|
||||||
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,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue