forked from libre-chip/cpu
WIP: adding load/store unit
This commit is contained in:
parent
bc2bcf4434
commit
304100b492
6 changed files with 1392 additions and 3 deletions
|
|
@ -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,7 +127,46 @@ 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]
|
||||||
|
|
|
||||||
|
|
@ -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>),
|
||||||
}
|
}
|
||||||
|
|
@ -391,6 +393,7 @@ impl RenamedMOpFilter for () {
|
||||||
pub struct UnitIO {
|
pub struct UnitIO {
|
||||||
pub cd: Option<Expr<ClockDomain>>,
|
pub cd: Option<Expr<ClockDomain>>,
|
||||||
pub from_execute: Expr<ExecuteToUnitInterface<PhantomConst<CpuConfig>>>,
|
pub from_execute: Expr<ExecuteToUnitInterface<PhantomConst<CpuConfig>>>,
|
||||||
|
pub to_d_cache: Option<Expr<LoadStoreToDCacheInterface<PhantomConst<CpuConfig>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait UnitTrait:
|
pub trait UnitTrait:
|
||||||
|
|
|
||||||
|
|
@ -1617,6 +1617,7 @@ impl UnitTrait for AluBranch {
|
||||||
UnitIO {
|
UnitIO {
|
||||||
cd: None,
|
cd: None,
|
||||||
from_execute: this.from_execute,
|
from_execute: this.from_execute,
|
||||||
|
to_d_cache: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
1328
crates/cpu/src/unit/load_store.rs
Normal file
1328
crates/cpu/src/unit/load_store.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -94,13 +94,17 @@ fn formal_harness(
|
||||||
let UnitIO {
|
let UnitIO {
|
||||||
cd: unit_cd,
|
cd: unit_cd,
|
||||||
from_execute: unit_from_execute,
|
from_execute: unit_from_execute,
|
||||||
|
to_d_cache,
|
||||||
} = dyn_unit.io(unit);
|
} = dyn_unit.io(unit);
|
||||||
|
if let Some(unit_cd) = unit_cd {
|
||||||
|
connect(unit_cd, cd);
|
||||||
|
}
|
||||||
connect(
|
connect(
|
||||||
unit_from_execute,
|
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) = unit_cd {
|
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