forked from libre-chip/cpu
WIP: adding ExecuteToUnitInterface::is_no_longer_speculative_prediction
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,
|
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.
|
/// Interface from the Rename/Execute/Retire control logic to a single Unit.
|
||||||
///
|
///
|
||||||
/// ## State diagram for a single µOp in a 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>>,
|
pub inputs_ready: HdlOption<UnitInputsReady<C>>,
|
||||||
/// if [`Self::unit_outputs_ready`] is `false`, then this is always [`HdlNone`]
|
/// if [`Self::unit_outputs_ready`] is `false`, then this is always [`HdlNone`]
|
||||||
pub is_no_longer_speculative: HdlOption<UnitMOpIsNoLongerSpeculative<C>>,
|
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
|
/// this uses [`Self::unit_outputs_ready`] as a shared ready flag
|
||||||
#[hdl(flip)]
|
#[hdl(flip)]
|
||||||
pub cant_cause_cancel: HdlOption<UnitMOpCantCauseCancel<C>>,
|
pub cant_cause_cancel: HdlOption<UnitMOpCantCauseCancel<C>>,
|
||||||
|
|
@ -1263,31 +1275,62 @@ impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
||||||
fn get_unit_mop_is_no_longer_speculative(
|
fn get_unit_mop_is_no_longer_speculative(
|
||||||
&self,
|
&self,
|
||||||
unit_index: usize,
|
unit_index: usize,
|
||||||
) -> SimValue<HdlOption<UnitMOpIsNoLongerSpeculative<C>>> {
|
) -> Option<SimValue<UnitMOpIsNoLongerSpeculative<C>>> {
|
||||||
let ret_ty = HdlOption[UnitMOpIsNoLongerSpeculative[self.config]];
|
|
||||||
if self.is_canceling() {
|
if self.is_canceling() {
|
||||||
let retval = #[hdl(sim)]
|
return None;
|
||||||
ret_ty.HdlNone();
|
|
||||||
return retval; // separate variable to work around rust-analyzer parse error
|
|
||||||
}
|
}
|
||||||
for rob in self.rob.renamed() {
|
for rob in self.rob.renamed() {
|
||||||
if rob.unit_index == unit_index
|
if rob.unit_index == unit_index
|
||||||
&& !rob.is_speculative
|
&& !rob.is_speculative
|
||||||
&& let Some(_) = rob.mop_in_unit_state.without_speculative()
|
&& let Some(_) = rob.mop_in_unit_state.without_speculative()
|
||||||
{
|
{
|
||||||
let retval = #[hdl(sim)]
|
return Some(
|
||||||
ret_ty.HdlSome(
|
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
UnitMOpIsNoLongerSpeculative::<_> {
|
UnitMOpIsNoLongerSpeculative::<_> {
|
||||||
id: &rob.mop.id,
|
id: &rob.mop.id,
|
||||||
config: self.config,
|
config: self.config,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return retval; // separate variable to work around rust-analyzer parse error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[hdl(sim)]
|
None
|
||||||
ret_ty.HdlNone()
|
}
|
||||||
|
#[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]
|
#[hdl]
|
||||||
fn unit_output_ready(&mut self, output_ready: SimValue<UnitOutputReady<C>>) {
|
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() {
|
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;
|
renamed.is_speculative = false;
|
||||||
if can_cause_cancel {
|
if renamed.can_cause_cancel() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1719,6 +1749,7 @@ async fn rename_execute_retire_run(
|
||||||
enqueue,
|
enqueue,
|
||||||
inputs_ready,
|
inputs_ready,
|
||||||
is_no_longer_speculative,
|
is_no_longer_speculative,
|
||||||
|
is_no_longer_speculative_prediction,
|
||||||
cant_cause_cancel: _,
|
cant_cause_cancel: _,
|
||||||
output_ready: _,
|
output_ready: _,
|
||||||
finish_cause_cancel: _,
|
finish_cause_cancel: _,
|
||||||
|
|
@ -1747,6 +1778,11 @@ async fn rename_execute_retire_run(
|
||||||
state.get_unit_mop_is_no_longer_speculative(unit_index),
|
state.get_unit_mop_is_no_longer_speculative(unit_index),
|
||||||
)
|
)
|
||||||
.await;
|
.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.write(unit_outputs_ready, !is_canceling).await;
|
||||||
}
|
}
|
||||||
sim.wait_for_clock_edge(cd.clk).await;
|
sim.wait_for_clock_edge(cd.clk).await;
|
||||||
|
|
@ -1767,6 +1803,7 @@ async fn rename_execute_retire_run(
|
||||||
enqueue,
|
enqueue,
|
||||||
inputs_ready,
|
inputs_ready,
|
||||||
is_no_longer_speculative,
|
is_no_longer_speculative,
|
||||||
|
is_no_longer_speculative_prediction: _, // no action necessary
|
||||||
cant_cause_cancel,
|
cant_cause_cancel,
|
||||||
output_ready,
|
output_ready,
|
||||||
finish_cause_cancel,
|
finish_cause_cancel,
|
||||||
|
|
@ -1959,6 +1996,7 @@ pub fn rename_execute_retire(config: PhantomConst<CpuConfig>) {
|
||||||
enqueue,
|
enqueue,
|
||||||
inputs_ready,
|
inputs_ready,
|
||||||
is_no_longer_speculative,
|
is_no_longer_speculative,
|
||||||
|
is_no_longer_speculative_prediction,
|
||||||
cant_cause_cancel: _,
|
cant_cause_cancel: _,
|
||||||
output_ready: _,
|
output_ready: _,
|
||||||
finish_cause_cancel: _,
|
finish_cause_cancel: _,
|
||||||
|
|
@ -1992,6 +2030,12 @@ pub fn rename_execute_retire(config: PhantomConst<CpuConfig>) {
|
||||||
(is_no_longer_speculative.ty()).HdlNone(),
|
(is_no_longer_speculative.ty()).HdlNone(),
|
||||||
)
|
)
|
||||||
.await;
|
.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;
|
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]
|
#[hdl]
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,7 @@ fn connect_to_unit_nop<C: Type + PhantomConstGet<CpuConfig>>(
|
||||||
enqueue,
|
enqueue,
|
||||||
inputs_ready,
|
inputs_ready,
|
||||||
is_no_longer_speculative,
|
is_no_longer_speculative,
|
||||||
|
is_no_longer_speculative_prediction,
|
||||||
cant_cause_cancel: _,
|
cant_cause_cancel: _,
|
||||||
output_ready: _,
|
output_ready: _,
|
||||||
finish_cause_cancel: _,
|
finish_cause_cancel: _,
|
||||||
|
|
@ -218,6 +219,10 @@ fn connect_to_unit_nop<C: Type + PhantomConstGet<CpuConfig>>(
|
||||||
is_no_longer_speculative,
|
is_no_longer_speculative,
|
||||||
is_no_longer_speculative.ty().HdlNone(),
|
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(unit_outputs_ready, false);
|
||||||
connect(cancel_all.data, HdlNone());
|
connect(cancel_all.data, HdlNone());
|
||||||
}
|
}
|
||||||
|
|
@ -506,6 +511,7 @@ impl<C: PhantomConstCpuConfig, MaxMOpCount: Size> DecodeAndRunSingleInsnState<C,
|
||||||
enqueue,
|
enqueue,
|
||||||
inputs_ready,
|
inputs_ready,
|
||||||
is_no_longer_speculative,
|
is_no_longer_speculative,
|
||||||
|
is_no_longer_speculative_prediction,
|
||||||
cant_cause_cancel: _, // we don't track if it can cause a cancel
|
cant_cause_cancel: _, // we don't track if it can cause a cancel
|
||||||
output_ready,
|
output_ready,
|
||||||
finish_cause_cancel,
|
finish_cause_cancel,
|
||||||
|
|
@ -513,6 +519,10 @@ impl<C: PhantomConstCpuConfig, MaxMOpCount: Size> DecodeAndRunSingleInsnState<C,
|
||||||
cancel_all,
|
cancel_all,
|
||||||
config: _,
|
config: _,
|
||||||
} = to_unit;
|
} = to_unit;
|
||||||
|
connect(
|
||||||
|
is_no_longer_speculative_prediction,
|
||||||
|
is_no_longer_speculative_prediction.ty().HdlNone(),
|
||||||
|
);
|
||||||
connect(unit_outputs_ready, true);
|
connect(unit_outputs_ready, true);
|
||||||
connect(cancel_all.data, HdlNone());
|
connect(cancel_all.data, HdlNone());
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
|
||||||
|
|
@ -1260,6 +1260,7 @@ pub fn alu_branch(
|
||||||
enqueue,
|
enqueue,
|
||||||
inputs_ready,
|
inputs_ready,
|
||||||
is_no_longer_speculative: _, // we don't care about being speculative for these instructions
|
is_no_longer_speculative: _, // we don't care about being speculative for these instructions
|
||||||
|
is_no_longer_speculative_prediction: _,
|
||||||
cant_cause_cancel,
|
cant_cause_cancel,
|
||||||
output_ready,
|
output_ready,
|
||||||
finish_cause_cancel,
|
finish_cause_cancel,
|
||||||
|
|
|
||||||
|
|
@ -988,6 +988,7 @@ async fn load_store_impl(
|
||||||
enqueue,
|
enqueue,
|
||||||
inputs_ready: _,
|
inputs_ready: _,
|
||||||
is_no_longer_speculative: _,
|
is_no_longer_speculative: _,
|
||||||
|
is_no_longer_speculative_prediction: _,
|
||||||
cant_cause_cancel,
|
cant_cause_cancel,
|
||||||
output_ready,
|
output_ready,
|
||||||
finish_cause_cancel,
|
finish_cause_cancel,
|
||||||
|
|
@ -1042,6 +1043,7 @@ async fn load_store_impl(
|
||||||
enqueue,
|
enqueue,
|
||||||
inputs_ready,
|
inputs_ready,
|
||||||
is_no_longer_speculative,
|
is_no_longer_speculative,
|
||||||
|
is_no_longer_speculative_prediction,
|
||||||
cant_cause_cancel,
|
cant_cause_cancel,
|
||||||
output_ready,
|
output_ready,
|
||||||
finish_cause_cancel,
|
finish_cause_cancel,
|
||||||
|
|
@ -1066,6 +1068,15 @@ async fn load_store_impl(
|
||||||
{
|
{
|
||||||
state.from_execute_is_no_longer_speculative(is_no_longer_speculative);
|
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 {
|
if sim.read_past_bool(unit_outputs_ready, cd.clk).await {
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
if let HdlSome(cant_cause_cancel) = sim.read_past(cant_cause_cancel, cd.clk).await {
|
if let HdlSome(cant_cause_cancel) = sim.read_past(cant_cause_cancel, cd.clk).await {
|
||||||
|
|
@ -1221,6 +1232,7 @@ pub fn load_store(
|
||||||
enqueue,
|
enqueue,
|
||||||
inputs_ready: _,
|
inputs_ready: _,
|
||||||
is_no_longer_speculative: _,
|
is_no_longer_speculative: _,
|
||||||
|
is_no_longer_speculative_prediction: _,
|
||||||
cant_cause_cancel,
|
cant_cause_cancel,
|
||||||
output_ready,
|
output_ready,
|
||||||
finish_cause_cancel,
|
finish_cause_cancel,
|
||||||
|
|
|
||||||
|
|
@ -2149,6 +2149,7 @@ async fn load_store_tester_impl<C: PhantomConstCpuConfig>(
|
||||||
enqueue,
|
enqueue,
|
||||||
inputs_ready,
|
inputs_ready,
|
||||||
is_no_longer_speculative,
|
is_no_longer_speculative,
|
||||||
|
is_no_longer_speculative_prediction,
|
||||||
cant_cause_cancel: _,
|
cant_cause_cancel: _,
|
||||||
output_ready: _,
|
output_ready: _,
|
||||||
finish_cause_cancel: _,
|
finish_cause_cancel: _,
|
||||||
|
|
@ -2168,6 +2169,11 @@ async fn load_store_tester_impl<C: PhantomConstCpuConfig>(
|
||||||
state.to_load_store_is_no_longer_speculative(),
|
state.to_load_store_is_no_longer_speculative(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
sim.write(
|
||||||
|
is_no_longer_speculative_prediction,
|
||||||
|
state.to_load_store_is_no_longer_speculative_prediction(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
} else {
|
} else {
|
||||||
sim.write(enqueue.data, enqueue.ty().data.HdlNone()).await;
|
sim.write(enqueue.data, enqueue.ty().data.HdlNone()).await;
|
||||||
sim.write(inputs_ready, inputs_ready.ty().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(),
|
is_no_longer_speculative.ty().HdlNone(),
|
||||||
)
|
)
|
||||||
.await;
|
.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())
|
sim.write(cancel_all.data, state.to_load_store_cancel_all())
|
||||||
.await;
|
.await;
|
||||||
|
|
@ -2190,6 +2201,7 @@ async fn load_store_tester_impl<C: PhantomConstCpuConfig>(
|
||||||
enqueue,
|
enqueue,
|
||||||
inputs_ready,
|
inputs_ready,
|
||||||
is_no_longer_speculative,
|
is_no_longer_speculative,
|
||||||
|
is_no_longer_speculative_prediction,
|
||||||
cant_cause_cancel,
|
cant_cause_cancel,
|
||||||
output_ready,
|
output_ready,
|
||||||
finish_cause_cancel,
|
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);
|
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 {
|
if sim.read_past_bool(unit_outputs_ready, cd.clk).await {
|
||||||
#[hdl(sim)]
|
#[hdl(sim)]
|
||||||
if let HdlSome(cant_cause_cancel) = sim.read_past(cant_cause_cancel, cd.clk).await {
|
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,
|
enqueue,
|
||||||
inputs_ready,
|
inputs_ready,
|
||||||
is_no_longer_speculative,
|
is_no_longer_speculative,
|
||||||
|
is_no_longer_speculative_prediction,
|
||||||
cant_cause_cancel: _,
|
cant_cause_cancel: _,
|
||||||
output_ready: _,
|
output_ready: _,
|
||||||
finish_cause_cancel: _,
|
finish_cause_cancel: _,
|
||||||
|
|
@ -2318,6 +2340,11 @@ fn load_store_tester(config: PhantomConst<CpuConfig>) {
|
||||||
is_no_longer_speculative.ty().HdlNone(),
|
is_no_longer_speculative.ty().HdlNone(),
|
||||||
)
|
)
|
||||||
.await;
|
.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(unit_outputs_ready, false).await;
|
||||||
sim.write(cancel_all.data, HdlNone()).await;
|
sim.write(cancel_all.data, HdlNone()).await;
|
||||||
sim.write(test_passed, false).await;
|
sim.write(test_passed, false).await;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue