WIP: adding ExecuteToUnitInterface::is_no_longer_speculative_prediction
Some checks failed
/ test (pull_request) Failing after 2m37s
Some checks failed
/ test (pull_request) Failing after 2m37s
This commit is contained in:
parent
a81d85d9c0
commit
7038be9268
6 changed files with 133 additions and 24 deletions
|
|
@ -203,6 +203,16 @@ pub struct UnitMOpCantCauseCancel<C: PhantomConstGet<CpuConfig>> {
|
|||
pub config: C,
|
||||
}
|
||||
|
||||
/// This tells the Unit that if [`Self::if_cant_cause_cancel_id`] can no longer cause a cancel
|
||||
/// (either via [`UnitMOpCantCauseCancel`] or [`UnitFinishCauseCancel`] without a cancel),
|
||||
/// then [`Self::then_no_longer_speculative_id`] will no longer be speculative.
|
||||
#[hdl(no_static)]
|
||||
pub struct UnitMOpIsNoLongerSpeculativePrediction<C: PhantomConstGet<CpuConfig>> {
|
||||
pub if_cant_cause_cancel_id: MOpId,
|
||||
pub then_no_longer_speculative_id: MOpId,
|
||||
pub config: C,
|
||||
}
|
||||
|
||||
/// Interface from the Rename/Execute/Retire control logic to a single Unit.
|
||||
///
|
||||
/// ## State diagram for a single µOp in a Unit
|
||||
|
|
@ -223,6 +233,8 @@ pub struct ExecuteToUnitInterface<C: PhantomConstGet<CpuConfig>> {
|
|||
pub inputs_ready: HdlOption<UnitInputsReady<C>>,
|
||||
/// if [`Self::unit_outputs_ready`] is `false`, then this is always [`HdlNone`]
|
||||
pub is_no_longer_speculative: HdlOption<UnitMOpIsNoLongerSpeculative<C>>,
|
||||
/// if [`Self::unit_outputs_ready`] is `false`, then this is always [`HdlNone`]
|
||||
pub is_no_longer_speculative_prediction: HdlOption<UnitMOpIsNoLongerSpeculativePrediction<C>>,
|
||||
/// this uses [`Self::unit_outputs_ready`] as a shared ready flag
|
||||
#[hdl(flip)]
|
||||
pub cant_cause_cancel: HdlOption<UnitMOpCantCauseCancel<C>>,
|
||||
|
|
@ -1263,31 +1275,62 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
|||
fn get_unit_mop_is_no_longer_speculative(
|
||||
&self,
|
||||
unit_index: usize,
|
||||
) -> SimValue<HdlOption<UnitMOpIsNoLongerSpeculative<C>>> {
|
||||
let ret_ty = HdlOption[UnitMOpIsNoLongerSpeculative[self.config]];
|
||||
) -> Option<SimValue<UnitMOpIsNoLongerSpeculative<C>>> {
|
||||
if self.is_canceling() {
|
||||
let retval = #[hdl(sim)]
|
||||
ret_ty.HdlNone();
|
||||
return retval; // separate variable to work around rust-analyzer parse error
|
||||
return None;
|
||||
}
|
||||
for rob in self.rob.renamed() {
|
||||
if rob.unit_index == unit_index
|
||||
&& !rob.is_speculative
|
||||
&& let Some(_) = rob.mop_in_unit_state.without_speculative()
|
||||
{
|
||||
let retval = #[hdl(sim)]
|
||||
ret_ty.HdlSome(
|
||||
return Some(
|
||||
#[hdl(sim)]
|
||||
UnitMOpIsNoLongerSpeculative::<_> {
|
||||
id: &rob.mop.id,
|
||||
config: self.config,
|
||||
},
|
||||
);
|
||||
return retval; // separate variable to work around rust-analyzer parse error
|
||||
}
|
||||
}
|
||||
#[hdl(sim)]
|
||||
ret_ty.HdlNone()
|
||||
None
|
||||
}
|
||||
#[hdl]
|
||||
fn get_unit_mop_is_no_longer_speculative_prediction(
|
||||
&self,
|
||||
unit_index: usize,
|
||||
) -> Option<SimValue<UnitMOpIsNoLongerSpeculativePrediction<C>>> {
|
||||
if self.is_canceling() {
|
||||
return None;
|
||||
}
|
||||
let mut renamed_iter = self.rob.renamed();
|
||||
let if_cant_cause_cancel_id = loop {
|
||||
let Some(renamed) = renamed_iter.next() else {
|
||||
return None;
|
||||
};
|
||||
if renamed.can_cause_cancel() {
|
||||
if renamed.unit_index != unit_index {
|
||||
return None;
|
||||
}
|
||||
break &renamed.mop.id;
|
||||
}
|
||||
};
|
||||
for renamed in renamed_iter {
|
||||
if renamed.unit_index == unit_index {
|
||||
return Some(
|
||||
#[hdl(sim)]
|
||||
UnitMOpIsNoLongerSpeculativePrediction::<_> {
|
||||
if_cant_cause_cancel_id,
|
||||
then_no_longer_speculative_id: &renamed.mop.id,
|
||||
config: self.config,
|
||||
},
|
||||
);
|
||||
}
|
||||
if renamed.can_cause_cancel() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
#[hdl]
|
||||
fn unit_output_ready(&mut self, output_ready: SimValue<UnitOutputReady<C>>) {
|
||||
|
|
@ -1618,21 +1661,8 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
|||
};
|
||||
}
|
||||
for renamed in self.rob.renamed_mut() {
|
||||
let can_cause_cancel = match renamed.mop_in_unit_state {
|
||||
MOpInUnitState::NotYetEnqueued => true,
|
||||
MOpInUnitState::InputsNotReadySpeculative { can_cause_cancel } => can_cause_cancel,
|
||||
MOpInUnitState::InputsReady {
|
||||
speculative: _,
|
||||
can_cause_cancel,
|
||||
} => can_cause_cancel,
|
||||
MOpInUnitState::OutputReady {
|
||||
speculative: _,
|
||||
can_cause_cancel,
|
||||
} => can_cause_cancel,
|
||||
MOpInUnitState::FinishedAndOrCausedCancel => renamed.caused_cancel.is_some(),
|
||||
};
|
||||
renamed.is_speculative = false;
|
||||
if can_cause_cancel {
|
||||
if renamed.can_cause_cancel() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1719,6 +1749,7 @@ async fn rename_execute_retire_run(
|
|||
enqueue,
|
||||
inputs_ready,
|
||||
is_no_longer_speculative,
|
||||
is_no_longer_speculative_prediction,
|
||||
cant_cause_cancel: _,
|
||||
output_ready: _,
|
||||
finish_cause_cancel: _,
|
||||
|
|
@ -1747,6 +1778,11 @@ async fn rename_execute_retire_run(
|
|||
state.get_unit_mop_is_no_longer_speculative(unit_index),
|
||||
)
|
||||
.await;
|
||||
sim.write(
|
||||
is_no_longer_speculative_prediction,
|
||||
state.get_unit_mop_is_no_longer_speculative_prediction(unit_index),
|
||||
)
|
||||
.await;
|
||||
sim.write(unit_outputs_ready, !is_canceling).await;
|
||||
}
|
||||
sim.wait_for_clock_edge(cd.clk).await;
|
||||
|
|
@ -1767,6 +1803,7 @@ async fn rename_execute_retire_run(
|
|||
enqueue,
|
||||
inputs_ready,
|
||||
is_no_longer_speculative,
|
||||
is_no_longer_speculative_prediction: _, // no action necessary
|
||||
cant_cause_cancel,
|
||||
output_ready,
|
||||
finish_cause_cancel,
|
||||
|
|
@ -1959,6 +1996,7 @@ pub fn rename_execute_retire(config: PhantomConst<CpuConfig>) {
|
|||
enqueue,
|
||||
inputs_ready,
|
||||
is_no_longer_speculative,
|
||||
is_no_longer_speculative_prediction,
|
||||
cant_cause_cancel: _,
|
||||
output_ready: _,
|
||||
finish_cause_cancel: _,
|
||||
|
|
@ -1992,6 +2030,12 @@ pub fn rename_execute_retire(config: PhantomConst<CpuConfig>) {
|
|||
(is_no_longer_speculative.ty()).HdlNone(),
|
||||
)
|
||||
.await;
|
||||
sim.write(
|
||||
is_no_longer_speculative_prediction,
|
||||
#[hdl(sim)]
|
||||
(is_no_longer_speculative_prediction.ty()).HdlNone(),
|
||||
)
|
||||
.await;
|
||||
sim.write(unit_outputs_ready, false).await;
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -173,6 +173,21 @@ impl<C: PhantomConstCpuConfig> RobEntry<C> {
|
|||
}
|
||||
}
|
||||
}
|
||||
pub(crate) fn can_cause_cancel(&self) -> bool {
|
||||
match self.mop_in_unit_state {
|
||||
MOpInUnitState::NotYetEnqueued => true,
|
||||
MOpInUnitState::InputsNotReadySpeculative { can_cause_cancel } => can_cause_cancel,
|
||||
MOpInUnitState::InputsReady {
|
||||
speculative: _,
|
||||
can_cause_cancel,
|
||||
} => can_cause_cancel,
|
||||
MOpInUnitState::OutputReady {
|
||||
speculative: _,
|
||||
can_cause_cancel,
|
||||
} => can_cause_cancel,
|
||||
MOpInUnitState::FinishedAndOrCausedCancel => self.caused_cancel.is_some(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ fn connect_to_unit_nop<C: Type + PhantomConstGet<CpuConfig>>(
|
|||
enqueue,
|
||||
inputs_ready,
|
||||
is_no_longer_speculative,
|
||||
is_no_longer_speculative_prediction,
|
||||
cant_cause_cancel: _,
|
||||
output_ready: _,
|
||||
finish_cause_cancel: _,
|
||||
|
|
@ -218,6 +219,10 @@ fn connect_to_unit_nop<C: Type + PhantomConstGet<CpuConfig>>(
|
|||
is_no_longer_speculative,
|
||||
is_no_longer_speculative.ty().HdlNone(),
|
||||
);
|
||||
connect(
|
||||
is_no_longer_speculative_prediction,
|
||||
is_no_longer_speculative_prediction.ty().HdlNone(),
|
||||
);
|
||||
connect(unit_outputs_ready, false);
|
||||
connect(cancel_all.data, HdlNone());
|
||||
}
|
||||
|
|
@ -506,6 +511,7 @@ impl<C: PhantomConstCpuConfig, MaxMOpCount: Size> DecodeAndRunSingleInsnState<C,
|
|||
enqueue,
|
||||
inputs_ready,
|
||||
is_no_longer_speculative,
|
||||
is_no_longer_speculative_prediction,
|
||||
cant_cause_cancel: _, // we don't track if it can cause a cancel
|
||||
output_ready,
|
||||
finish_cause_cancel,
|
||||
|
|
@ -513,6 +519,10 @@ impl<C: PhantomConstCpuConfig, MaxMOpCount: Size> DecodeAndRunSingleInsnState<C,
|
|||
cancel_all,
|
||||
config: _,
|
||||
} = to_unit;
|
||||
connect(
|
||||
is_no_longer_speculative_prediction,
|
||||
is_no_longer_speculative_prediction.ty().HdlNone(),
|
||||
);
|
||||
connect(unit_outputs_ready, true);
|
||||
connect(cancel_all.data, HdlNone());
|
||||
#[hdl]
|
||||
|
|
|
|||
|
|
@ -1260,6 +1260,7 @@ pub fn alu_branch(
|
|||
enqueue,
|
||||
inputs_ready,
|
||||
is_no_longer_speculative: _, // we don't care about being speculative for these instructions
|
||||
is_no_longer_speculative_prediction: _,
|
||||
cant_cause_cancel,
|
||||
output_ready,
|
||||
finish_cause_cancel,
|
||||
|
|
|
|||
|
|
@ -988,6 +988,7 @@ async fn load_store_impl(
|
|||
enqueue,
|
||||
inputs_ready: _,
|
||||
is_no_longer_speculative: _,
|
||||
is_no_longer_speculative_prediction: _,
|
||||
cant_cause_cancel,
|
||||
output_ready,
|
||||
finish_cause_cancel,
|
||||
|
|
@ -1042,6 +1043,7 @@ async fn load_store_impl(
|
|||
enqueue,
|
||||
inputs_ready,
|
||||
is_no_longer_speculative,
|
||||
is_no_longer_speculative_prediction,
|
||||
cant_cause_cancel,
|
||||
output_ready,
|
||||
finish_cause_cancel,
|
||||
|
|
@ -1066,6 +1068,15 @@ async fn load_store_impl(
|
|||
{
|
||||
state.from_execute_is_no_longer_speculative(is_no_longer_speculative);
|
||||
}
|
||||
#[hdl(sim)]
|
||||
if let HdlSome(is_no_longer_speculative_prediction) = sim
|
||||
.read_past(is_no_longer_speculative_prediction, cd.clk)
|
||||
.await
|
||||
{
|
||||
state.from_execute_is_no_longer_speculative_prediction(
|
||||
is_no_longer_speculative_prediction,
|
||||
);
|
||||
}
|
||||
if sim.read_past_bool(unit_outputs_ready, cd.clk).await {
|
||||
#[hdl(sim)]
|
||||
if let HdlSome(cant_cause_cancel) = sim.read_past(cant_cause_cancel, cd.clk).await {
|
||||
|
|
@ -1221,6 +1232,7 @@ pub fn load_store(
|
|||
enqueue,
|
||||
inputs_ready: _,
|
||||
is_no_longer_speculative: _,
|
||||
is_no_longer_speculative_prediction: _,
|
||||
cant_cause_cancel,
|
||||
output_ready,
|
||||
finish_cause_cancel,
|
||||
|
|
|
|||
|
|
@ -2149,6 +2149,7 @@ async fn load_store_tester_impl<C: PhantomConstCpuConfig>(
|
|||
enqueue,
|
||||
inputs_ready,
|
||||
is_no_longer_speculative,
|
||||
is_no_longer_speculative_prediction,
|
||||
cant_cause_cancel: _,
|
||||
output_ready: _,
|
||||
finish_cause_cancel: _,
|
||||
|
|
@ -2168,6 +2169,11 @@ async fn load_store_tester_impl<C: PhantomConstCpuConfig>(
|
|||
state.to_load_store_is_no_longer_speculative(),
|
||||
)
|
||||
.await;
|
||||
sim.write(
|
||||
is_no_longer_speculative_prediction,
|
||||
state.to_load_store_is_no_longer_speculative_prediction(),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
sim.write(enqueue.data, enqueue.ty().data.HdlNone()).await;
|
||||
sim.write(inputs_ready, inputs_ready.ty().HdlNone()).await;
|
||||
|
|
@ -2176,6 +2182,11 @@ async fn load_store_tester_impl<C: PhantomConstCpuConfig>(
|
|||
is_no_longer_speculative.ty().HdlNone(),
|
||||
)
|
||||
.await;
|
||||
sim.write(
|
||||
is_no_longer_speculative_prediction,
|
||||
is_no_longer_speculative_prediction.ty().HdlNone(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
sim.write(cancel_all.data, state.to_load_store_cancel_all())
|
||||
.await;
|
||||
|
|
@ -2190,6 +2201,7 @@ async fn load_store_tester_impl<C: PhantomConstCpuConfig>(
|
|||
enqueue,
|
||||
inputs_ready,
|
||||
is_no_longer_speculative,
|
||||
is_no_longer_speculative_prediction,
|
||||
cant_cause_cancel,
|
||||
output_ready,
|
||||
finish_cause_cancel,
|
||||
|
|
@ -2213,6 +2225,15 @@ async fn load_store_tester_impl<C: PhantomConstCpuConfig>(
|
|||
{
|
||||
state.handle_to_load_store_is_no_longer_speculative(is_no_longer_speculative);
|
||||
}
|
||||
#[hdl(sim)]
|
||||
if let HdlSome(is_no_longer_speculative_prediction) = sim
|
||||
.read_past(is_no_longer_speculative_prediction, cd.clk)
|
||||
.await
|
||||
{
|
||||
state.handle_to_load_store_is_no_longer_speculative_prediction(
|
||||
is_no_longer_speculative_prediction,
|
||||
);
|
||||
}
|
||||
if sim.read_past_bool(unit_outputs_ready, cd.clk).await {
|
||||
#[hdl(sim)]
|
||||
if let HdlSome(cant_cause_cancel) = sim.read_past(cant_cause_cancel, cd.clk).await {
|
||||
|
|
@ -2293,6 +2314,7 @@ fn load_store_tester(config: PhantomConst<CpuConfig>) {
|
|||
enqueue,
|
||||
inputs_ready,
|
||||
is_no_longer_speculative,
|
||||
is_no_longer_speculative_prediction,
|
||||
cant_cause_cancel: _,
|
||||
output_ready: _,
|
||||
finish_cause_cancel: _,
|
||||
|
|
@ -2318,6 +2340,11 @@ fn load_store_tester(config: PhantomConst<CpuConfig>) {
|
|||
is_no_longer_speculative.ty().HdlNone(),
|
||||
)
|
||||
.await;
|
||||
sim.write(
|
||||
is_no_longer_speculative_prediction,
|
||||
is_no_longer_speculative_prediction.ty().HdlNone(),
|
||||
)
|
||||
.await;
|
||||
sim.write(unit_outputs_ready, false).await;
|
||||
sim.write(cancel_all.data, HdlNone()).await;
|
||||
sim.write(test_passed, false).await;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue