forked from libre-chip/cpu
WIP: adding load/store unit
This commit is contained in:
parent
fb0b07fbb2
commit
126119301e
2 changed files with 159 additions and 1 deletions
|
|
@ -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<DestReg, SrcReg>),
|
||||
}
|
||||
|
|
|
|||
157
crates/cpu/src/unit/load_store.rs
Normal file
157
crates/cpu/src/unit/load_store.rs
Normal file
|
|
@ -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<CpuConfig>,
|
||||
unit_index: usize,
|
||||
filter: LoadStoreFilter,
|
||||
cd: Expr<ClockDomain>,
|
||||
from_execute: Expr<ExecuteToUnitInterface<PhantomConst<CpuConfig>>>,
|
||||
mut sim: ExternModuleSimulationState,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
struct LoadStoreFilter {
|
||||
load: bool,
|
||||
store: bool,
|
||||
}
|
||||
|
||||
impl LoadStoreFilter {
|
||||
fn new(
|
||||
from_execute: ExecuteToUnitInterface<PhantomConst<CpuConfig>>,
|
||||
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<CpuConfig>,
|
||||
unit_index: usize,
|
||||
filter: &mut impl RenamedMOpFilter,
|
||||
) {
|
||||
#[hdl]
|
||||
let cd: ClockDomain = m.input();
|
||||
|
||||
#[hdl]
|
||||
let from_execute: ExecuteToUnitInterface<PhantomConst<CpuConfig>> =
|
||||
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<CpuConfig>,
|
||||
module: Interned<Module<load_store>>,
|
||||
}
|
||||
|
||||
impl LoadStore {
|
||||
pub fn new(
|
||||
config: PhantomConst<CpuConfig>,
|
||||
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<Module<Self::Type>> {
|
||||
self.module
|
||||
}
|
||||
|
||||
fn cd(&self, this: Expr<Self::Type>) -> Option<Expr<ClockDomain>> {
|
||||
Some(this.cd)
|
||||
}
|
||||
|
||||
fn from_execute(
|
||||
&self,
|
||||
this: Expr<Self::Type>,
|
||||
) -> Expr<ExecuteToUnitInterface<PhantomConst<CpuConfig>>> {
|
||||
this.from_execute
|
||||
}
|
||||
|
||||
fn to_dyn(&self) -> DynUnit {
|
||||
DynUnitWrapper(*self).to_dyn()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue