WIP: Add Load/Store Unit #16
13 changed files with 70817 additions and 71 deletions
4
.cargo/config.toml
Normal file
4
.cargo/config.toml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
# See Notices.txt for copyright information
|
||||||
|
[build]
|
||||||
|
rustflags = ["-Csymbol-mangling-version=v0", "-Cforce-frame-pointers=yes"]
|
||||||
|
|
@ -19,6 +19,7 @@ use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
fmt,
|
fmt,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
|
num::NonZeroU64,
|
||||||
ops::{ControlFlow, Range},
|
ops::{ControlFlow, Range},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2983,6 +2984,19 @@ pub enum LoadStoreWidth {
|
||||||
Width64Bit,
|
Width64Bit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl LoadStoreWidth {
|
||||||
|
#[hdl]
|
||||||
|
pub fn access_byte_size_sim(this: &<Self as Type>::SimValue) -> NonZeroU64 {
|
||||||
|
#[hdl(sim)]
|
||||||
|
match this {
|
||||||
|
Self::Width8Bit => const { NonZeroU64::new(1).unwrap() },
|
||||||
|
Self::Width16Bit => const { NonZeroU64::new(2).unwrap() },
|
||||||
|
Self::Width32Bit => const { NonZeroU64::new(4).unwrap() },
|
||||||
|
Self::Width64Bit => const { NonZeroU64::new(8).unwrap() },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl(cmp_eq)]
|
||||||
pub enum LoadStoreConversion {
|
pub enum LoadStoreConversion {
|
||||||
ZeroExt,
|
ZeroExt,
|
||||||
|
|
|
||||||
|
|
@ -127,8 +127,47 @@ impl AddressRange {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub const fn is_overlapping(self, other: Self) -> bool {
|
||||||
|
self.contains(other.start().0) || other.contains(self.start().0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const _: () = {
|
||||||
|
const N: u64 = 4;
|
||||||
|
const fn is_overlapping_reference(range1: AddressRange, range2: AddressRange) -> bool {
|
||||||
|
// we just need to check values < N since all starts/ends are < N
|
||||||
|
let mut v = 0;
|
||||||
|
while v < N {
|
||||||
|
if range1.contains(v) && range2.contains(v) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
v += 1;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
let mut start1 = 0;
|
||||||
|
while start1 < N {
|
||||||
|
let mut end1 = 0;
|
||||||
|
while end1 < N {
|
||||||
|
let mut start2 = 0;
|
||||||
|
while start2 < N {
|
||||||
|
let mut end2 = 0;
|
||||||
|
while end2 < N {
|
||||||
|
let range1 = AddressRange::from_wrapping_range_inclusive(start1..=end1);
|
||||||
|
let range2 = AddressRange::from_wrapping_range_inclusive(start2..=end2);
|
||||||
|
assert!(
|
||||||
|
range1.is_overlapping(range2) == is_overlapping_reference(range1, range2)
|
||||||
|
);
|
||||||
|
end2 += 1;
|
||||||
|
}
|
||||||
|
start2 += 1;
|
||||||
|
}
|
||||||
|
end1 += 1;
|
||||||
|
}
|
||||||
|
start1 += 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct MemoryInterfaceConfig {
|
pub struct MemoryInterfaceConfig {
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use crate::{
|
||||||
MOpVariantVisitOps, MOpVariantVisitor, MOpVisitVariants, RenamedMOp, mop_enum,
|
MOpVariantVisitOps, MOpVariantVisitor, MOpVisitVariants, RenamedMOp, mop_enum,
|
||||||
},
|
},
|
||||||
rename_execute_retire::ExecuteToUnitInterface,
|
rename_execute_retire::ExecuteToUnitInterface,
|
||||||
|
unit::load_store::LoadStoreToDCacheInterface,
|
||||||
};
|
};
|
||||||
use fayalite::{
|
use fayalite::{
|
||||||
bundle::{Bundle, BundleType},
|
bundle::{Bundle, BundleType},
|
||||||
|
|
@ -18,6 +19,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
pub mod alu_branch;
|
pub mod alu_branch;
|
||||||
|
pub mod load_store;
|
||||||
|
|
||||||
macro_rules! all_units {
|
macro_rules! all_units {
|
||||||
(
|
(
|
||||||
|
|
@ -333,7 +335,7 @@ all_units! {
|
||||||
#[create_dyn_unit_fn = |config, unit_index, filter| todo!()]
|
#[create_dyn_unit_fn = |config, unit_index, filter| todo!()]
|
||||||
#[extract(transformed_move_mop, transformed_move_mop_sim, transformed_move_mop_sim_ref, transformed_move_mop_sim_mut)]
|
#[extract(transformed_move_mop, transformed_move_mop_sim, transformed_move_mop_sim_ref, transformed_move_mop_sim_mut)]
|
||||||
TransformedMove(TransformedMoveOp),
|
TransformedMove(TransformedMoveOp),
|
||||||
#[create_dyn_unit_fn = |config, unit_index, filter| todo!()]
|
#[create_dyn_unit_fn = |config, unit_index, filter| load_store::LoadStore::new(config, unit_index, filter).to_dyn()]
|
||||||
#[extract(load_store_mop, load_store_mop_sim, load_store_mop_sim_ref, load_store_mop_sim_mut)]
|
#[extract(load_store_mop, load_store_mop_sim, load_store_mop_sim_ref, load_store_mop_sim_mut)]
|
||||||
LoadStore(LoadStoreMOp<DestReg, SrcReg>),
|
LoadStore(LoadStoreMOp<DestReg, SrcReg>),
|
||||||
}
|
}
|
||||||
|
|
@ -387,6 +389,13 @@ impl RenamedMOpFilter for () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub struct UnitIO {
|
||||||
|
pub cd: Option<Expr<ClockDomain>>,
|
||||||
|
pub from_execute: Expr<ExecuteToUnitInterface<PhantomConst<CpuConfig>>>,
|
||||||
|
pub to_d_cache: Option<Expr<LoadStoreToDCacheInterface<PhantomConst<CpuConfig>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait UnitTrait:
|
pub trait UnitTrait:
|
||||||
'static + Send + Sync + std::fmt::Debug + fayalite::intern::SupportsPtrEqWithTypeId
|
'static + Send + Sync + std::fmt::Debug + fayalite::intern::SupportsPtrEqWithTypeId
|
||||||
{
|
{
|
||||||
|
|
@ -395,11 +404,7 @@ pub trait UnitTrait:
|
||||||
fn ty(&self) -> Self::Type;
|
fn ty(&self) -> Self::Type;
|
||||||
fn unit_kind(&self) -> UnitKind;
|
fn unit_kind(&self) -> UnitKind;
|
||||||
fn module(&self) -> Interned<Module<Self::Type>>;
|
fn module(&self) -> Interned<Module<Self::Type>>;
|
||||||
fn cd(&self, this: Expr<Self::Type>) -> Option<Expr<ClockDomain>>;
|
fn io(&self, this: Expr<Self::Type>) -> UnitIO;
|
||||||
fn from_execute(
|
|
||||||
&self,
|
|
||||||
this: Expr<Self::Type>,
|
|
||||||
) -> Expr<ExecuteToUnitInterface<PhantomConst<CpuConfig>>>;
|
|
||||||
fn to_dyn(&self) -> DynUnit;
|
fn to_dyn(&self) -> DynUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -434,15 +439,8 @@ impl UnitTrait for DynUnit {
|
||||||
self.unit.module()
|
self.unit.module()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cd(&self, this: Expr<Self::Type>) -> Option<Expr<ClockDomain>> {
|
fn io(&self, this: Expr<Self::Type>) -> UnitIO {
|
||||||
self.unit.cd(this)
|
self.unit.io(this)
|
||||||
}
|
|
||||||
|
|
||||||
fn from_execute(
|
|
||||||
&self,
|
|
||||||
this: Expr<Self::Type>,
|
|
||||||
) -> Expr<ExecuteToUnitInterface<PhantomConst<CpuConfig>>> {
|
|
||||||
self.unit.from_execute(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_dyn(&self) -> DynUnit {
|
fn to_dyn(&self) -> DynUnit {
|
||||||
|
|
@ -468,15 +466,8 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T
|
||||||
self.0.module().canonical().intern_sized()
|
self.0.module().canonical().intern_sized()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cd(&self, this: Expr<Self::Type>) -> Option<Expr<ClockDomain>> {
|
fn io(&self, this: Expr<Self::Type>) -> UnitIO {
|
||||||
self.0.cd(Expr::from_bundle(this))
|
self.0.io(Expr::from_bundle(this))
|
||||||
}
|
|
||||||
|
|
||||||
fn from_execute(
|
|
||||||
&self,
|
|
||||||
this: Expr<Self::Type>,
|
|
||||||
) -> Expr<ExecuteToUnitInterface<PhantomConst<CpuConfig>>> {
|
|
||||||
self.0.from_execute(Expr::from_bundle(this))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_dyn(&self) -> DynUnit {
|
fn to_dyn(&self) -> DynUnit {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ use crate::{
|
||||||
ExecuteToUnitInterface, GlobalState, NextPcPredictorOp, RenamedMOp, UnitCausedCancel,
|
ExecuteToUnitInterface, GlobalState, NextPcPredictorOp, RenamedMOp, UnitCausedCancel,
|
||||||
UnitFinishCauseCancel, UnitInputsReady, UnitOutputReady,
|
UnitFinishCauseCancel, UnitInputsReady, UnitOutputReady,
|
||||||
},
|
},
|
||||||
unit::{DynUnit, DynUnitWrapper, RenamedMOpFilter, UnitKind, UnitTrait},
|
unit::{DynUnit, DynUnitWrapper, RenamedMOpFilter, UnitIO, UnitKind, UnitTrait},
|
||||||
};
|
};
|
||||||
use fayalite::{
|
use fayalite::{
|
||||||
expr::CastToImpl,
|
expr::CastToImpl,
|
||||||
|
|
@ -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,
|
||||||
|
|
@ -1613,15 +1614,12 @@ impl UnitTrait for AluBranch {
|
||||||
self.module
|
self.module
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cd(&self, _this: Expr<Self::Type>) -> Option<Expr<ClockDomain>> {
|
fn io(&self, this: Expr<Self::Type>) -> UnitIO {
|
||||||
None
|
UnitIO {
|
||||||
}
|
cd: None,
|
||||||
|
from_execute: this.from_execute,
|
||||||
fn from_execute(
|
to_d_cache: None,
|
||||||
&self,
|
}
|
||||||
this: Expr<Self::Type>,
|
|
||||||
) -> Expr<ExecuteToUnitInterface<PhantomConst<CpuConfig>>> {
|
|
||||||
this.from_execute
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_dyn(&self) -> DynUnit {
|
fn to_dyn(&self) -> DynUnit {
|
||||||
|
|
|
||||||
1342
crates/cpu/src/unit/load_store.rs
Normal file
1342
crates/cpu/src/unit/load_store.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,15 +1,8 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
use fayalite::{
|
use fayalite::{expr::ops::ArrayLiteral, module::wire_with_loc, prelude::*};
|
||||||
bundle::BundleType, expr::ops::ArrayLiteral, module::wire_with_loc, prelude::*,
|
use std::num::NonZero;
|
||||||
sim::vcd::VcdWriterDecls, util::RcWriter,
|
|
||||||
};
|
|
||||||
use std::{
|
|
||||||
num::NonZero,
|
|
||||||
panic::Location,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub mod array_vec;
|
pub mod array_vec;
|
||||||
pub mod tree_reduce;
|
pub mod tree_reduce;
|
||||||
|
|
|
||||||
66833
crates/cpu/tests/expected/load_store_unit_random.vcd
generated
Normal file
66833
crates/cpu/tests/expected/load_store_unit_random.vcd
generated
Normal file
File diff suppressed because it is too large
Load diff
2455
crates/cpu/tests/load_store_unit.rs
Normal file
2455
crates/cpu/tests/load_store_unit.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -14,7 +14,7 @@ use cpu::{
|
||||||
DecodeAndRunSingleInsnInput, DecodeAndRunSingleInsnOutput, DecodeOneInsnInput,
|
DecodeAndRunSingleInsnInput, DecodeAndRunSingleInsnOutput, DecodeOneInsnInput,
|
||||||
DecodeOneInsnMaxMOpCount, decode_and_run_single_insn,
|
DecodeOneInsnMaxMOpCount, decode_and_run_single_insn,
|
||||||
},
|
},
|
||||||
unit::{RenamedMOpFilter, UnitKind, UnitMOp, UnitTrait},
|
unit::{RenamedMOpFilter, UnitIO, UnitKind, UnitMOp, UnitTrait},
|
||||||
util::array_vec::ArrayVec,
|
util::array_vec::ArrayVec,
|
||||||
};
|
};
|
||||||
use fayalite::{
|
use fayalite::{
|
||||||
|
|
@ -91,12 +91,20 @@ fn formal_harness(
|
||||||
dyn_unit.module(),
|
dyn_unit.module(),
|
||||||
SourceLocation::caller(),
|
SourceLocation::caller(),
|
||||||
);
|
);
|
||||||
|
let UnitIO {
|
||||||
|
cd: unit_cd,
|
||||||
|
from_execute: unit_from_execute,
|
||||||
|
to_d_cache,
|
||||||
|
} = dyn_unit.io(unit);
|
||||||
|
if let Some(unit_cd) = unit_cd {
|
||||||
|
connect(unit_cd, cd);
|
||||||
|
}
|
||||||
connect(
|
connect(
|
||||||
dyn_unit.from_execute(unit),
|
unit_from_execute,
|
||||||
ExecuteToUnitInterfaces::unit_fields(decode_and_run.to_units)[unit_index],
|
ExecuteToUnitInterfaces::unit_fields(decode_and_run.to_units)[unit_index],
|
||||||
);
|
);
|
||||||
if let Some(unit_cd) = dyn_unit.cd(unit) {
|
if let Some(to_d_cache) = to_d_cache {
|
||||||
connect(unit_cd, cd);
|
unimplemented!("to_d_cache for {unit:?}: {to_d_cache:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hdl_assert(cd.clk, !decode_and_run.error, "");
|
hdl_assert(cd.clk, !decode_and_run.error, "");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue