diff --git a/crates/cpu/src/unit.rs b/crates/cpu/src/unit.rs index ce024a4..0c0c4e1 100644 --- a/crates/cpu/src/unit.rs +++ b/crates/cpu/src/unit.rs @@ -18,6 +18,7 @@ use serde::{Deserialize, Serialize}; use std::ops::ControlFlow; pub mod alu_branch; +pub mod load_store; macro_rules! all_units { ( @@ -333,7 +334,7 @@ all_units! { #[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)] 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)] LoadStore(LoadStoreMOp), } diff --git a/crates/cpu/src/unit/load_store.rs b/crates/cpu/src/unit/load_store.rs new file mode 100644 index 0000000..0b6bbd0 --- /dev/null +++ b/crates/cpu/src/unit/load_store.rs @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// See Notices.txt for copyright information + +use crate::{ + config::CpuConfig, + instruction::LoadStoreMOp, + next_pc::CallStackOp, + register::PRegValue, + rename_execute_retire::{ + ExecuteToUnitInterface, NextPcPredictorOp, RenamedMOp, UnitCausedCancel, + UnitFinishCauseCancel, UnitInputsReady, UnitOutputReady, + }, + unit::{DynUnit, DynUnitWrapper, RenamedMOpFilter, UnitKind, UnitTrait}, +}; +use fayalite::{intern::Interned, prelude::*}; + +#[hdl] +async fn load_store_impl( + config: PhantomConst, + unit_index: usize, + filter: LoadStoreFilter, + cd: Expr, + from_execute: Expr>>, + mut sim: ExternModuleSimulationState, +) { + todo!() +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +struct LoadStoreFilter { + load: bool, + store: bool, +} + +impl LoadStoreFilter { + fn new( + from_execute: ExecuteToUnitInterface>, + filter: &mut impl RenamedMOpFilter, + ) -> Self { + let LoadStoreMOp { Load, Store } = from_execute + .inputs_ready + .HdlSome + .mop + .mop + .inner_ty() + .LoadStore; + Self { + load: filter.should_include_ty(Load), + store: filter.should_include_ty(Store), + } + } +} + +#[hdl_module(extern)] +pub fn load_store( + config: PhantomConst, + unit_index: usize, + filter: &mut impl RenamedMOpFilter, +) { + #[hdl] + let cd: ClockDomain = m.input(); + + #[hdl] + let from_execute: ExecuteToUnitInterface> = + m.input(ExecuteToUnitInterface[config]); + + let filter = LoadStoreFilter::new(from_execute.ty(), filter); + + assert_eq!(config.get().units[unit_index].kind, UnitKind::LoadStore); + + m.register_clock_for_past(cd.clk); + + m.extern_module_simulation_fn( + (config, unit_index, filter, cd, from_execute), + async |(config, unit_index, filter, cd, from_execute), mut sim| { + sim.resettable( + cd, + async |mut sim| { + #[hdl] + let ExecuteToUnitInterface::<_> { + global_state: _, + enqueue, + inputs_ready: _, + is_no_longer_speculative: _, + cant_cause_cancel, + output_ready, + finish_cause_cancel, + unit_outputs_ready: _, + cancel_all, + config: _, + } = from_execute; + sim.write(enqueue.ready, false).await; + sim.write(cant_cause_cancel, cant_cause_cancel.ty().HdlNone()) + .await; + sim.write(output_ready, output_ready.ty().HdlNone()).await; + sim.write(finish_cause_cancel, finish_cause_cancel.ty().HdlNone()) + .await; + sim.write(cancel_all.ready, false).await; + }, + async |sim, ()| { + load_store_impl(config, unit_index, filter, cd, from_execute, sim).await + }, + ) + .await + }, + ); +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct LoadStore { + config: PhantomConst, + module: Interned>, +} + +impl LoadStore { + pub fn new( + config: PhantomConst, + unit_index: usize, + filter: &mut impl RenamedMOpFilter, + ) -> Self { + Self { + config, + module: load_store(config, unit_index, filter), + } + } +} + +impl UnitTrait for LoadStore { + type Type = load_store; + + fn ty(&self) -> Self::Type { + self.module.io_ty() + } + + fn unit_kind(&self) -> UnitKind { + UnitKind::LoadStore + } + + fn module(&self) -> Interned> { + self.module + } + + fn cd(&self, this: Expr) -> Option> { + Some(this.cd) + } + + fn from_execute( + &self, + this: Expr, + ) -> Expr>> { + this.from_execute + } + + fn to_dyn(&self) -> DynUnit { + DynUnitWrapper(*self).to_dyn() + } +}