Compare commits

..

No commits in common. "rename-execute-retire" and "master" have entirely different histories.

24 changed files with 11451 additions and 622355 deletions

8
Cargo.lock generated
View file

@ -388,7 +388,7 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
[[package]]
name = "fayalite"
version = "0.3.0"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#26224abe1c145d1744da89e08b7f9c64ee2ee2ce"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#80b92c7dd3adcad8487a3f8224846e381219bfa6"
dependencies = [
"base64",
"bitvec",
@ -417,7 +417,7 @@ dependencies = [
[[package]]
name = "fayalite-proc-macros"
version = "0.3.0"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#26224abe1c145d1744da89e08b7f9c64ee2ee2ce"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#80b92c7dd3adcad8487a3f8224846e381219bfa6"
dependencies = [
"fayalite-proc-macros-impl",
]
@ -425,7 +425,7 @@ dependencies = [
[[package]]
name = "fayalite-proc-macros-impl"
version = "0.3.0"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#26224abe1c145d1744da89e08b7f9c64ee2ee2ce"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#80b92c7dd3adcad8487a3f8224846e381219bfa6"
dependencies = [
"base16ct 0.2.0",
"num-bigint",
@ -440,7 +440,7 @@ dependencies = [
[[package]]
name = "fayalite-visit-gen"
version = "0.3.0"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#26224abe1c145d1744da89e08b7f9c64ee2ee2ce"
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#80b92c7dd3adcad8487a3f8224846e381219bfa6"
dependencies = [
"indexmap",
"prettyplease",

View file

@ -33,6 +33,3 @@ hex-literal.workspace = true
regex = "1.12.2"
sha2.workspace = true
which.workspace = true
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(todo)'] }

View file

@ -1,7 +1,13 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{instruction::CONST_ZERO_UNIT_NUM, unit::UnitKind};
use fayalite::{expr::HdlPartialOrdImpl, prelude::*};
use crate::{
instruction::{CONST_ZERO_UNIT_NUM, MOpTrait, PRegNum, RenamedMOp, UnitNum, UnitOutRegNum},
unit::{
UnitCancelInput, UnitKind, UnitOutputWrite,
unit_base::{UnitForwardingInfo, UnitToRegAlloc},
},
};
use fayalite::prelude::*;
use serde::{Deserialize, Serialize};
use std::num::NonZeroUsize;
@ -95,20 +101,54 @@ impl CpuConfig {
pub fn unit_num_width(&self) -> usize {
UInt::range(CONST_ZERO_UNIT_NUM..self.non_const_unit_nums().end).width()
}
pub fn unit_num(&self) -> UnitNum<DynSize> {
UnitNum[self.unit_num_width()]
}
pub fn unit_out_reg_num(&self) -> UnitOutRegNum<DynSize> {
UnitOutRegNum[self.out_reg_num_width]
}
pub fn p_reg_num(&self) -> PRegNum<DynSize, DynSize> {
PRegNum[self.unit_num_width()][self.out_reg_num_width]
}
pub fn p_reg_num_width(&self) -> usize {
self.unit_num_width() + self.out_reg_num_width
}
pub fn renamed_mop_in_unit(&self) -> RenamedMOp<UnitOutRegNum<DynSize>, DynSize> {
RenamedMOp[self.unit_out_reg_num()][self.p_reg_num_width()]
}
pub fn unit_output_write(&self) -> UnitOutputWrite<DynSize> {
UnitOutputWrite[self.out_reg_num_width]
}
pub fn unit_output_writes(&self) -> Array<HdlOption<UnitOutputWrite<DynSize>>> {
Array[HdlOption[self.unit_output_write()]][self.non_const_unit_nums().len()]
}
pub fn unit_cancel_input(&self) -> UnitCancelInput<DynSize> {
UnitCancelInput[self.out_reg_num_width]
}
pub fn unit_forwarding_info(&self) -> UnitForwardingInfo<DynSize, DynSize, DynSize> {
UnitForwardingInfo[self.unit_num_width()][self.out_reg_num_width]
[self.non_const_unit_nums().len()]
}
pub fn unit_max_in_flight(&self, unit_index: usize) -> NonZeroUsize {
self.units[unit_index]
.max_in_flight
.unwrap_or(self.default_unit_max_in_flight)
}
/// the maximum of all [`unit_max_in_flight()`][Self::unit_max_in_flight()]
pub fn max_unit_max_in_flight(&self) -> NonZeroUsize {
(0..self.units.len())
.map(|unit_index| self.unit_max_in_flight(unit_index))
.max()
.unwrap_or(self.default_unit_max_in_flight)
pub fn unit_to_reg_alloc<
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>, SrcRegWidth = DynSize>,
ExtraOut: Type,
>(
&self,
mop_ty: MOp,
extra_out_ty: ExtraOut,
) -> UnitToRegAlloc<MOp, ExtraOut, DynSize, DynSize, DynSize> {
assert_eq!(
mop_ty.dest_reg_ty(),
self.unit_out_reg_num(),
"inconsistent types",
);
UnitToRegAlloc[mop_ty][extra_out_ty][self.unit_num_width()][self.out_reg_num_width]
[self.non_const_unit_nums().len()]
}
pub fn fetch_width_in_bytes(&self) -> usize {
1usize
@ -148,21 +188,6 @@ impl CpuConfig {
}
}
#[hdl(get(|c| c.out_reg_num_width))]
pub type CpuConfigOutRegNumWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(get(|c| c.unit_num_width()))]
pub type CpuConfigUnitNumWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(get(|c| c.p_reg_num_width()))]
pub type CpuConfigPRegNumWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(get(|c| 1 << c.out_reg_num_width))]
pub type CpuConfig2PowOutRegNumWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(get(|c| c.units.len()))]
pub type CpuConfigUnitCount<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(get(|c| c.fetch_width.get()))]
pub type CpuConfigFetchWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
@ -211,10 +236,6 @@ pub type CpuConfigL1ICacheMaxMissesInFlight<C: PhantomConstGet<CpuConfig>> = Dyn
#[hdl(get(|c| c.rob_size.get()))]
pub type CpuConfigRobSize<C: PhantomConstGet<CpuConfig>> = DynSize;
/// the maximum of all [`unit_max_in_flight()`][CpuConfig::unit_max_in_flight()]
#[hdl(get(|c| c.max_unit_max_in_flight().get()))]
pub type CpuConfigMaxUnitMaxInFlight<C: PhantomConstGet<CpuConfig>> = DynSize;
pub trait PhantomConstCpuConfig:
PhantomConstGet<CpuConfig>
+ Into<PhantomConst<CpuConfig>>
@ -222,7 +243,6 @@ pub trait PhantomConstCpuConfig:
+ Type
+ ToSimValue<Type = Self>
+ ToExpr<Type = Self>
+ HdlPartialOrdImpl<Self>
{
}

View file

@ -1656,6 +1656,7 @@ impl DecodeState<'_> {
MOpDestReg::new([crf(bf)], []),
[gpr(ra).value],
si.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
compare_mode,
),
);
@ -1683,6 +1684,8 @@ impl DecodeState<'_> {
CompareMOp::compare(
MOpDestReg::new([crf(bf)], []),
[gpr(ra).value, gpr(rb).value],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
compare_mode,
),
);
@ -1711,6 +1714,7 @@ impl DecodeState<'_> {
MOpDestReg::new([crf(bf)], []),
[gpr(ra).value],
ui.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
compare_mode,
),
);
@ -1738,6 +1742,8 @@ impl DecodeState<'_> {
CompareMOp::compare(
MOpDestReg::new([crf(bf)], []),
[gpr(ra).value, gpr(rb).value],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
compare_mode,
),
);
@ -1765,6 +1771,8 @@ impl DecodeState<'_> {
CompareMOp::compare(
MOpDestReg::new([crf(bf)], []),
[gpr(ra).value, gpr(rb).value],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
compare_mode,
),
);
@ -1784,6 +1792,8 @@ impl DecodeState<'_> {
CompareMOp::compare(
MOpDestReg::new([crf(bf)], []),
[gpr(ra).value, gpr(rb).value],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.CmpEqB(),
),
);

View file

@ -523,7 +523,7 @@ impl<C: PhantomConstCpuConfig> L1ICacheStateSim<C> {
kind,
read_data,
config: _,
} = memory_operation_finish.into_sim_value();
} = memory_operation_finish;
#[hdl(sim)]
match kind {
MemoryOperationFinishKind::Success(success) =>
@ -746,7 +746,7 @@ impl<C: PhantomConstCpuConfig> L1ICacheStateSim<C> {
let NextPcToFetchInterfaceInner {
start_pc,
fetch_block_id,
} = fetch.into_sim_value();
} = fetch;
let entry_ty = FetchQueueEntry[config];
self.queue.push_back(
#[hdl(sim)]
@ -895,7 +895,7 @@ impl<C: PhantomConstCpuConfig> L1ICacheStateSim<C> {
let CacheReadData::<_> {
cache_line_index: read_cache_line_index,
cache_line,
} = cache_read_data.into_sim_value();
} = cache_read_data;
let config = self.config();
for entry in &mut self.queue {
#[hdl(sim)]
@ -1151,6 +1151,8 @@ fn l1_i_cache_impl(config: PhantomConst<CpuConfig>) {
sim.wait_for_clock_edge(cd.clk).await;
}
sim.write(from_next_pc.cancel.ready, true).await;
let memory_interface_start_data_ty = memory_interface.start.data.ty();
let to_decode_fetched_data_ty = to_decode_fetched.data.ty();
let cache_read_data_ty = CacheReadData[config];
let mut state = L1ICacheStateSim::new(state_expr);
loop {
@ -1166,11 +1168,26 @@ fn l1_i_cache_impl(config: PhantomConst<CpuConfig>) {
.await;
sim.write(
memory_interface.start.data,
state.clone().try_start_memory_operation(),
if let Some(v) = state.clone().try_start_memory_operation() {
#[hdl(sim)]
memory_interface_start_data_ty.HdlSome(v)
} else {
#[hdl(sim)]
memory_interface_start_data_ty.HdlNone()
},
)
.await;
sim.write(
to_decode_fetched.data,
if let Some(v) = state.clone().to_decode_fetched() {
#[hdl(sim)]
to_decode_fetched_data_ty.HdlSome(v)
} else {
#[hdl(sim)]
to_decode_fetched_data_ty.HdlNone()
},
)
.await;
sim.write(to_decode_fetched.data, state.clone().to_decode_fetched())
.await;
state.write_debug_state(&mut sim).await;
sim.write(max_cancel_in_fetch, state.queue.len()).await;
state

File diff suppressed because it is too large Load diff

View file

@ -192,13 +192,6 @@ impl MOpRegNum {
power_isa_gpr_or_zero_reg
}
#[hdl]
pub fn power_isa_gpr_or_zero_reg_imm(index: usize) -> Expr<Self> {
#[hdl]
Self {
value: Self::power_isa_gpr_or_zero_reg_num(index).cast_to_static::<UInt<_>>(),
}
}
#[hdl]
pub fn power_isa_gpr_or_zero_reg_sim(reg_num: &SimValue<UInt<5>>) -> SimValue<Self> {
#[hdl(sim)]
Self {

View file

@ -7,9 +7,7 @@ pub mod instruction;
pub mod main_memory_and_io;
pub mod next_pc;
pub mod powerisa_instructions_xml;
#[cfg(todo)]
pub mod reg_alloc;
pub mod register;
pub mod rename_execute_retire;
pub mod unit;
pub mod util;

View file

@ -23,13 +23,14 @@ use crate::{
util::array_vec::ArrayVec,
};
use fayalite::{
expr::HdlPartialEqImpl,
int::{UIntInRange, UIntInRangeInclusive, UIntInRangeInclusiveType, UIntInRangeType},
prelude::*,
sim::value::SimOnlyValueTrait,
ty::StaticType,
util::{DebugAsDisplay, ready_valid::ReadyValid},
};
use std::fmt;
use std::{borrow::Cow, fmt};
pub const FETCH_BLOCK_ID_WIDTH: usize = FetchBlockIdInt::BITS as usize;
type FetchBlockIdInt = u8;
@ -52,7 +53,7 @@ pub struct NextPcToFetchInterface<C: PhantomConstGet<CpuConfig>> {
pub config: C,
}
#[hdl(cmp_eq)]
#[hdl]
/// WIP version of decoded instruction just good enough to represent stuff needed for [`next_pc()`]
/// since the actual instruction definition isn't finalized yet.
/// This will be replaced at a later point.
@ -92,6 +93,101 @@ impl WipDecodedInsnKind {
}
}
// TODO: replace with #[hdl(cmp_eq)] when that's implemented for enums
impl HdlPartialEqImpl<Self> for WipDecodedInsnKind {
#[track_caller]
fn cmp_value_eq(
lhs: Self,
lhs_value: Cow<'_, Self::SimValue>,
rhs: Self,
rhs_value: Cow<'_, Self::SimValue>,
) -> bool {
*Self::cmp_sim_value_eq(
Cow::Owned(SimValue::from_value(lhs, lhs_value.into_owned())),
Cow::Owned(SimValue::from_value(rhs, rhs_value.into_owned())),
)
}
#[hdl]
#[track_caller]
fn cmp_sim_value_eq(
lhs: Cow<'_, SimValue<Self>>,
rhs: Cow<'_, SimValue<Self>>,
) -> SimValue<Bool> {
let clear_unused_bits = |v: Cow<'_, SimValue<Self>>| {
#[hdl(sim)]
match &*v {
Self::NonBranch =>
{
#[hdl(sim)]
Self::NonBranch()
}
Self::Branch(target) =>
{
#[hdl(sim)]
Self::Branch(target)
}
Self::BranchCond(target) =>
{
#[hdl(sim)]
Self::BranchCond(target)
}
Self::IndirectBranch =>
{
#[hdl(sim)]
Self::IndirectBranch()
}
Self::Call(target) =>
{
#[hdl(sim)]
Self::Call(target)
}
Self::CallCond(target) =>
{
#[hdl(sim)]
Self::CallCond(target)
}
Self::IndirectCall =>
{
#[hdl(sim)]
Self::IndirectCall()
}
Self::Ret =>
{
#[hdl(sim)]
Self::Ret()
}
Self::RetCond =>
{
#[hdl(sim)]
Self::RetCond()
}
Self::Interrupt(target) =>
{
#[hdl(sim)]
Self::Interrupt(target)
}
Self::Unknown => v.into_owned(),
}
};
(SimValue::bits(&clear_unused_bits(lhs)) == SimValue::bits(&clear_unused_bits(rhs)))
.to_sim_value()
}
#[track_caller]
fn cmp_sim_value_ne(
lhs: Cow<'_, SimValue<Self>>,
rhs: Cow<'_, SimValue<Self>>,
) -> SimValue<Bool> {
!Self::cmp_sim_value_eq(lhs, rhs)
}
#[track_caller]
fn cmp_expr_eq(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
todo!()
}
}
#[hdl(cmp_eq)]
/// WIP version of decoded instruction just good enough to represent stuff needed for [`next_pc()`]
/// since the actual instruction definition isn't finalized yet.
@ -2685,10 +2781,8 @@ impl<T: SimValueDefault, N: Size> SimValueDefault for ArrayType<T, N> {
}
impl<T: Type> SimValueDefault for HdlOption<T> {
#[hdl]
fn sim_value_default(self) -> SimValue<Self> {
#[hdl(sim)]
self.HdlNone()
self.HdlNone().to_sim_value_with_type(self)
}
}
@ -2817,13 +2911,50 @@ impl ResetSteps for CallStack {
}
}
#[hdl(cmp_eq)]
#[hdl]
enum BTBEntryInsnKind {
Branch,
Call,
Ret,
}
// TODO: replace with #[hdl(cmp_eq)] when that's implemented for enums
impl HdlPartialEqImpl<Self> for BTBEntryInsnKind {
#[track_caller]
fn cmp_value_eq(
lhs: Self,
lhs_value: Cow<'_, Self::SimValue>,
rhs: Self,
rhs_value: Cow<'_, Self::SimValue>,
) -> bool {
*Self::cmp_sim_value_eq(
Cow::Owned(SimValue::from_value(lhs, lhs_value.into_owned())),
Cow::Owned(SimValue::from_value(rhs, rhs_value.into_owned())),
)
}
#[track_caller]
fn cmp_sim_value_eq(
lhs: Cow<'_, SimValue<Self>>,
rhs: Cow<'_, SimValue<Self>>,
) -> SimValue<Bool> {
(SimValue::bits(&*lhs) == SimValue::bits(&*rhs)).to_sim_value()
}
#[track_caller]
fn cmp_sim_value_ne(
lhs: Cow<'_, SimValue<Self>>,
rhs: Cow<'_, SimValue<Self>>,
) -> SimValue<Bool> {
(SimValue::bits(&*lhs) != SimValue::bits(&*rhs)).to_sim_value()
}
#[track_caller]
fn cmp_expr_eq(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits())
}
}
impl BTBEntryInsnKind {
#[hdl]
fn try_from_decoded_insn_kind(kind: &SimValue<WipDecodedInsnKind>) -> Option<SimValue<Self>> {
@ -2852,7 +2983,7 @@ impl BTBEntryInsnKind {
}
}
#[hdl(cmp_eq)]
#[hdl]
enum BTBEntryAddrKind {
Unconditional,
Indirect,
@ -2860,6 +2991,43 @@ enum BTBEntryAddrKind {
CondNotTaken,
}
// TODO: replace with #[hdl(cmp_eq)] when that's implemented for enums
impl HdlPartialEqImpl<Self> for BTBEntryAddrKind {
#[track_caller]
fn cmp_value_eq(
lhs: Self,
lhs_value: Cow<'_, Self::SimValue>,
rhs: Self,
rhs_value: Cow<'_, Self::SimValue>,
) -> bool {
*Self::cmp_sim_value_eq(
Cow::Owned(SimValue::from_value(lhs, lhs_value.into_owned())),
Cow::Owned(SimValue::from_value(rhs, rhs_value.into_owned())),
)
}
#[track_caller]
fn cmp_sim_value_eq(
lhs: Cow<'_, SimValue<Self>>,
rhs: Cow<'_, SimValue<Self>>,
) -> SimValue<Bool> {
(SimValue::bits(&*lhs) == SimValue::bits(&*rhs)).to_sim_value()
}
#[track_caller]
fn cmp_sim_value_ne(
lhs: Cow<'_, SimValue<Self>>,
rhs: Cow<'_, SimValue<Self>>,
) -> SimValue<Bool> {
(SimValue::bits(&*lhs) != SimValue::bits(&*rhs)).to_sim_value()
}
#[track_caller]
fn cmp_expr_eq(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits())
}
}
impl BTBEntryAddrKind {
#[hdl]
fn taken(this: &SimValue<Self>) -> bool {

View file

@ -8,7 +8,7 @@ use fayalite::{
prelude::*,
ty::StaticType,
};
use std::{any::Any, fmt};
use std::fmt;
#[hdl]
pub enum FlagsMode {
@ -47,11 +47,6 @@ pub trait PRegFlagsViewTrait: Type + PRegFlagsViewTraitSealed {
fn from_view_sim<T: ToSimValue>(view: Self::View<T>) -> SimValue<PRegFlags<T::Type>>;
fn view_unused_into_view<T>(unused: ViewUnused<T, PRegFlagsAllUnused>) -> Self::View<T>;
fn view_into_view_unused<T>(view: Self::View<T>) -> ViewUnused<T, PRegFlagsAllUnused>;
fn debug_fmt<'a, T: 'a, F: FnMut(&'a T, bool) -> Option<D>, D: fmt::Debug>(
view: &'a Self::View<T>,
field: F,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result;
}
pub struct ViewUnused<T, V: PRegFlagsViewTrait>(V::UnusedInner<T>);
@ -472,33 +467,6 @@ macro_rules! impl_view_trait {
};
fields.into_view_unused()
}
fn debug_fmt<'a, T: 'a, F: FnMut(&'a T, bool) -> Option<D>, D: fmt::Debug>(
view: &'a Self::View<T>,
mut field: F,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
let $View {
$unused: ViewUnused([$($unused_field,)*]),
$($view_field: $flags_field,)*
} = view;
let mut debug_struct = f.debug_struct(stringify!($FlagsMode));
#[allow(unused_mut)]
let mut any_skipped = false;
$(if let Some(v) = field($flags_field, true) {
debug_struct.field(stringify!($view_field), &v);
} else {
any_skipped = true;
})*
$(if let Some(v) = field($unused_field, false) {
debug_struct.field(stringify!($unused_field), &v);
})*
if any_skipped {
debug_struct.finish_non_exhaustive()
} else {
debug_struct.finish()
}
}
}
};
}
@ -771,31 +739,6 @@ impl<T: Type> PRegFlags<T> {
pub fn splat_sim(v: impl ToSimValue<Type = T>) -> SimValue<Self> {
Self::from_fields_sim(ViewUnused::splat(v.into_sim_value()))
}
#[hdl]
pub fn debug_fmt<V: PRegFlagsViewTrait>(
this: &SimValue<Self>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
if let Some(this) = <dyn Any>::downcast_ref::<SimValue<PRegFlags>>(this) {
V::debug_fmt(
&PRegFlags::view_sim_ref::<V>(this),
|v, _| v.then_some(*v),
f,
)
} else {
V::debug_fmt(&PRegFlags::view_sim_ref::<V>(this), |v, _| Some(*v), f)
}
}
#[hdl]
pub fn debug_fmt_mode(this: &SimValue<Self>, mode: &SimValue<FlagsMode>) -> impl fmt::Debug {
fmt::from_fn(move |f| {
#[hdl(sim)]
match mode {
FlagsMode::PowerISA(_) => Self::debug_fmt::<PRegFlagsPowerISA>(this, f),
FlagsMode::X86(_) => Self::debug_fmt::<PRegFlagsX86>(this, f),
}
})
}
}
impl PRegFlags<UIntInRange<0, { PRegFlags::FLAG_COUNT }>> {
@ -839,37 +782,4 @@ impl PRegValue {
flags: PRegFlags::zeroed(),
}
}
#[hdl]
pub fn zeroed_sim() -> SimValue<Self> {
#[hdl(sim)]
Self {
int_fp: 0u64,
flags: PRegFlags::zeroed_sim(),
}
}
#[hdl]
pub fn debug_fmt<V: PRegFlagsViewTrait>(this: &SimValue<Self>) -> impl fmt::Debug {
fmt::from_fn(move |f| {
#[hdl(sim)]
let Self { int_fp, flags } = this;
f.debug_struct("PRegValue")
.field("int_fp", int_fp)
.field(
"flags",
&fmt::from_fn(|f| PRegFlags::debug_fmt::<V>(flags, f)),
)
.finish()
})
}
#[hdl]
pub fn debug_fmt_mode(this: &SimValue<Self>, mode: &SimValue<FlagsMode>) -> impl fmt::Debug {
fmt::from_fn(move |f| {
#[hdl(sim)]
let Self { int_fp, flags } = this;
f.debug_struct("PRegValue")
.field("int_fp", int_fp)
.field("flags", &PRegFlags::debug_fmt_mode(flags, mode))
.finish()
})
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,207 +0,0 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{config::CpuConfig, rename_execute_retire::ExecuteToUnitInterface};
use fayalite::{
bundle::{BundleField, BundleType, NoBuilder},
expr::ops::FieldAccess,
intern::{Intern, Interned, Memoize},
prelude::*,
ty::{
OpaqueSimValue, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten,
SimValueDebug,
},
};
use std::{fmt, marker::PhantomData, ops::Index};
/// a bundle with fields of type [`ExecuteToUnitInterface<C>`] for each unit
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct ExecuteToUnitInterfaces<C: Type + PhantomConstGet<CpuConfig>> {
bundle_ty: Bundle,
config: C,
}
impl<C: Type + PhantomConstGet<CpuConfig>> fmt::Debug for ExecuteToUnitInterfaces<C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("ExecuteToUnitInterfaces ")?;
let fields = self.bundle_ty.fields();
let field_offsets = self.bundle_ty.field_offsets();
f.debug_set()
.entries(
fields.iter().enumerate().map(|(index, field)| {
field.fmt_debug_in_struct(field_offsets[index].bit_width)
}),
)
.finish()
}
}
const CONFIG_FIELD_NAME: &str = "config";
impl<C: Type + PhantomConstGet<CpuConfig>> ExecuteToUnitInterfaces<C> {
pub fn new(config: C) -> Self {
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
struct MyMemoize<C>(PhantomData<C>);
impl<C: Type + PhantomConstGet<CpuConfig>> Memoize for MyMemoize<C> {
type Input = C;
type InputOwned = C;
type Output = ExecuteToUnitInterfaces<C>;
fn inner(self, &config: &Self::Input) -> Self::Output {
let unit_ty = ExecuteToUnitInterface[config].canonical();
let bundle_ty = Bundle::new(
(0..config.get().units.len())
.map(|unit_index| BundleField {
name: format!(
"u{unit_index}_{:?}",
config.get().units[unit_index].kind,
)
.intern_deref(),
flipped: false,
ty: unit_ty,
})
.chain([BundleField {
name: CONFIG_FIELD_NAME.intern(),
flipped: false,
ty: config.canonical(),
}])
.collect(),
);
ExecuteToUnitInterfaces { bundle_ty, config }
}
}
MyMemoize(PhantomData).get_owned(config)
}
pub fn bundle_ty(self) -> Bundle {
self.bundle_ty
}
pub fn config(self) -> C {
self.config
}
#[track_caller]
pub fn unit_field_name(self, unit_index: usize) -> Interned<str> {
assert!(unit_index < self.config.get().units.len());
self.bundle_ty.fields()[unit_index].name
}
pub fn unit_fields(
this: impl ToExpr<Type = Self>,
) -> Interned<[Expr<ExecuteToUnitInterface<C>>]> {
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
struct MyMemoize<C>(PhantomData<C>);
impl<C: Type + PhantomConstGet<CpuConfig>> Memoize for MyMemoize<C> {
type Input = Expr<ExecuteToUnitInterfaces<C>>;
type InputOwned = Expr<ExecuteToUnitInterfaces<C>>;
type Output = Interned<[Expr<ExecuteToUnitInterface<C>>]>;
fn inner(self, this: &Self::Input) -> Self::Output {
let bundle = Expr::as_bundle(*this);
(0..this.ty().config.get().units.len())
.map(|unit_index| FieldAccess::new_by_index(bundle, unit_index).to_expr())
.collect()
}
}
MyMemoize(PhantomData).get_owned(this.to_expr())
}
}
#[doc(hidden)]
pub struct ExecuteToUnitInterfacesWithoutGenerics(());
#[expect(non_upper_case_globals)]
pub const ExecuteToUnitInterfaces: ExecuteToUnitInterfacesWithoutGenerics =
ExecuteToUnitInterfacesWithoutGenerics(());
impl<C: Type + PhantomConstGet<CpuConfig>> Index<C> for ExecuteToUnitInterfacesWithoutGenerics {
type Output = ExecuteToUnitInterfaces<C>;
fn index(&self, config: C) -> &Self::Output {
Interned::into_inner(ExecuteToUnitInterfaces::new(config).intern())
}
}
impl<C: Type + PhantomConstGet<CpuConfig>> SimValueDebug for ExecuteToUnitInterfaces<C> {
fn sim_value_debug(
value: &<Self as Type>::SimValue,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
fmt::Debug::fmt(value, f)
}
}
impl<C: Type + PhantomConstGet<CpuConfig>> Type for ExecuteToUnitInterfaces<C> {
type BaseType = Bundle;
type MaskType = Bundle;
type SimValue = OpaqueSimValue;
type MatchVariant = <Bundle as Type>::MatchVariant;
type MatchActiveScope = <Bundle as Type>::MatchActiveScope;
type MatchVariantAndInactiveScope = <Bundle as Type>::MatchVariantAndInactiveScope;
type MatchVariantsIter = <Bundle as Type>::MatchVariantsIter;
fn match_variants(
this: Expr<Self>,
source_location: SourceLocation,
) -> Self::MatchVariantsIter {
Type::match_variants(Expr::as_bundle(this), source_location)
}
fn mask_type(&self) -> Self::MaskType {
self.bundle_ty.mask_type()
}
fn canonical(&self) -> CanonicalType {
self.bundle_ty.canonical()
}
fn from_canonical(canonical_type: CanonicalType) -> Self {
let bundle_ty = Bundle::from_canonical(canonical_type);
let config = if let Some(BundleField {
name,
flipped: false,
ty,
}) = bundle_ty.fields().last()
&& **name == *CONFIG_FIELD_NAME
{
C::from_canonical(*ty)
} else {
panic!(
"ExecuteToUnitInterfaces must have `{}` field",
CONFIG_FIELD_NAME
);
};
let retval = Self::new(config);
assert_eq!(bundle_ty, retval.bundle_ty);
retval
}
fn source_location() -> SourceLocation {
SourceLocation::caller()
}
fn sim_value_from_opaque(&self, opaque: OpaqueSimValueSlice<'_>) -> Self::SimValue {
<Bundle as Type>::sim_value_from_opaque(&self.bundle_ty, opaque)
}
fn sim_value_clone_from_opaque(
&self,
value: &mut Self::SimValue,
opaque: OpaqueSimValueSlice<'_>,
) {
<Bundle as Type>::sim_value_clone_from_opaque(&self.bundle_ty, value, opaque)
}
fn sim_value_to_opaque<'w>(
&self,
value: &Self::SimValue,
writer: OpaqueSimValueWriter<'w>,
) -> OpaqueSimValueWritten<'w> {
<Bundle as Type>::sim_value_to_opaque(&self.bundle_ty, value, writer)
}
}
impl<C: Type + PhantomConstGet<CpuConfig>> BundleType for ExecuteToUnitInterfaces<C> {
type Builder = NoBuilder;
fn fields(&self) -> Interned<[BundleField]> {
self.bundle_ty.fields()
}
}

View file

@ -1,41 +0,0 @@
%% SPDX-License-Identifier: LGPL-3.0-or-later
%% See Notices.txt for copyright information
stateDiagram-v2
direction LR
state "Inputs not ready<br/>Speculative<br/>Can cause cancel" as inr_s_c
state "Inputs not ready<br/>Speculative" as inr_s
state "Inputs ready<br/>Speculative<br/>Can cause cancel" as ir_s_c
state "Inputs ready<br/>Speculative" as ir_s
state "Inputs ready<br/>Can cause cancel" as ir_c
state "Inputs ready" as ir
state "Output ready<br/>Speculative<br/>Can cause cancel" as or_s_c
state "Output ready<br/>Can cause cancel" as or_c
state "Output ready<br/>Speculative" as or_s
state "Output ready" as or
[*] --> inr_s_c: Enqueue
inr_s_c --> inr_s: Can't cause cancel
ir_s_c --> ir_s: Can't cause cancel
ir_c --> ir: Can't cause cancel
or_s_c --> or_s: Can't cause cancel
or_c --> or: Can't cause cancel
ir_s_c --> ir_c: No longer speculative
ir_s --> ir: No longer speculative
or_s_c --> or_c: No longer speculative
or_s --> or: No longer speculative
inr_s_c --> ir_s_c: Inputs ready
inr_s --> ir_s: Inputs ready
ir_s_c --> or_s_c: Output Ready
ir_c --> or_c: Output Ready
ir_s --> or_s: Output Ready
ir --> or: Output Ready
or_s_c --> [*]: Finish
or_c --> [*]: Finish
or_s --> [*]: Finish
or --> [*]: Finish

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information
use crate::{
config::{CpuConfig, PhantomConstCpuConfig},
config::CpuConfig,
instruction::{
AluBranchMOp, LoadStoreMOp, MOp, MOpDestReg, MOpInto, MOpRegNum, MOpTrait,
MOpVariantVisitOps, MOpVariantVisitor, MOpVisitVariants, RenamedMOp, UnitOutRegNum,
@ -26,13 +26,13 @@ macro_rules! all_units {
(
#[hdl_unit_kind = $HdlUnitKind:ident]
#[unit_kind = $UnitKind:ident]
#[hdl(custom_debug(sim))]
#[hdl]
$(#[$enum_meta:meta])*
$vis:vis enum $UnitMOpEnum:ident<$DestReg:ident: Type, $SrcRegWidth:ident: Size, #[MOp(get_ty = $transformed_move_op_get_ty:expr)] $TransformedMoveOp:ident: Type> {
$(
$(#[transformed_move $($transformed_move:tt)*])?
#[create_dyn_unit_fn = $create_dyn_unit_fn:expr]
#[extract($extract:ident, $extract_sim:ident, $extract_sim_ref:ident, $extract_sim_mut:ident)]
#[extract = $extract:ident]
$(#[$variant_meta:meta])*
$Unit:ident($Op:ty),
)*
@ -48,7 +48,7 @@ macro_rules! all_units {
}
impl $UnitKind {
pub fn unit(self, config: PhantomConst<CpuConfig>, unit_index: usize) -> DynUnit {
pub fn unit(self, config: &CpuConfig, unit_index: usize) -> DynUnit {
match self {
$($UnitKind::$Unit => $create_dyn_unit_fn(config, unit_index),)*
}
@ -83,7 +83,7 @@ macro_rules! all_units {
mop_enum! {
#[impl_mop_into = false]
#[hdl(custom_debug(sim))]
#[hdl]
$(#[$enum_meta])*
$vis enum $UnitMOpEnum<
$DestReg: Type,
@ -112,15 +112,6 @@ macro_rules! all_units {
}
unit_kind
}
#[hdl]
$vis fn kind_sim(expr: &SimValue<Self>) -> UnitKind {
#![allow(unreachable_patterns)]
#[hdl(sim)]
match expr {
$(Self::$Unit(_) => $UnitKind::$Unit,)*
_ => unreachable!(),
}
}
$(
#[hdl]
$vis fn $extract(expr: impl ToExpr<Type = Self>) -> Expr<HdlOption<$Op>> {
@ -135,34 +126,6 @@ macro_rules! all_units {
}
$extract
}
#[hdl]
$vis fn $extract_sim(expr: impl ToSimValue<Type = Self>) -> Option<SimValue<$Op>> {
let expr = expr.into_sim_value();
#[hdl(sim)]
if let Self::$Unit(v) = expr {
Some(v)
} else {
None
}
}
#[hdl]
$vis fn $extract_sim_ref(expr: &SimValue<Self>) -> Option<&SimValue<$Op>> {
#[hdl(sim)]
if let Self::$Unit(v) = expr {
Some(v)
} else {
None
}
}
#[hdl]
$vis fn $extract_sim_mut(expr: &mut SimValue<Self>) -> Option<&mut SimValue<$Op>> {
#[hdl(sim)]
if let Self::$Unit(v) = expr {
Some(v)
} else {
None
}
}
)*
$vis fn with_transformed_move_op_ty<T>(self, new_transformed_move_op_ty: T) -> $UnitMOpEnum<$DestReg, $SrcRegWidth, T>
where
@ -233,45 +196,6 @@ macro_rules! all_units {
}
with_transformed_move_op
}
#[hdl]
$vis fn try_with_transformed_move_op_sim<T, E>(
this: impl ToSimValue<Type = Self>,
new_transformed_move_op_ty: T,
f: impl FnOnce(SimValue<$TransformedMoveOp>) -> Result<SimValue<$UnitMOpEnum<$DestReg, $SrcRegWidth, T>>, E>,
) -> Result<SimValue<$UnitMOpEnum<$DestReg, $SrcRegWidth, T>>, E>
where
T: MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
$TransformedMoveOp: MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
{
#![allow(unreachable_patterns)]
let this = this.into_sim_value();
let new_ty = this.ty().with_transformed_move_op_ty(new_transformed_move_op_ty);
#[hdl(sim)]
match this {
$(Self::$BeforeUnit(unit) => Ok(
#[hdl(sim)]
new_ty.$BeforeUnit(unit)
),)*
Self::$TransformedMove(unit) => f(unit),
$(Self::$AfterUnit(unit) => Ok(
#[hdl(sim)]
new_ty.$AfterUnit(unit)
),)*
_ => unreachable!(),
}
}
$vis fn with_transformed_move_op_sim<T>(
this: impl ToSimValue<Type = Self>,
new_transformed_move_op_ty: T,
f: impl FnOnce(SimValue<$TransformedMoveOp>) -> SimValue<$UnitMOpEnum<$DestReg, $SrcRegWidth, T>>,
) -> SimValue<$UnitMOpEnum<$DestReg, $SrcRegWidth, T>>
where
T: MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
$TransformedMoveOp: MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
{
let Ok::<_, std::convert::Infallible>(retval) = Self::try_with_transformed_move_op_sim(this, new_transformed_move_op_ty, move |v| Ok(f(v)));
retval
}
}
const _: () = {
@ -321,7 +245,7 @@ macro_rules! all_units {
all_units! {
#[hdl_unit_kind = HdlUnitKind]
#[unit_kind = UnitKind]
#[hdl(custom_debug(sim))]
#[hdl]
pub enum UnitMOp<
DestReg: Type,
SrcRegWidth: Size,
@ -330,14 +254,14 @@ all_units! {
})] TransformedMoveOp: Type
> {
#[create_dyn_unit_fn = |config, unit_index| alu_branch::AluBranch::new(config, unit_index).to_dyn()]
#[extract(alu_branch_mop, alu_branch_mop_sim, alu_branch_mop_sim_ref, alu_branch_mop_sim_mut)]
#[extract = alu_branch_mop]
AluBranch(AluBranchMOp<DestReg, SrcRegWidth>),
#[transformed_move]
#[create_dyn_unit_fn = |config, unit_index| todo!()]
#[extract(transformed_move_mop, transformed_move_mop_sim, transformed_move_mop_sim_ref, transformed_move_mop_sim_mut)]
#[extract = transformed_move_mop]
TransformedMove(TransformedMoveOp),
#[create_dyn_unit_fn = |config, unit_index| todo!()]
#[extract(load_store_mop, load_store_mop_sim, load_store_mop_sim_ref, load_store_mop_sim_mut)]
#[extract = load_store_mop]
LoadStore(LoadStoreMOp<DestReg, SrcRegWidth>),
}
}
@ -353,9 +277,9 @@ pub struct UnitResultCompleted<ExtraOut> {
pub extra_out: ExtraOut,
}
#[hdl(cmp_eq, no_static)]
pub struct UnitOutputWrite<C: PhantomConstGet<CpuConfig>> {
pub which: UnitOutRegNum<C>,
#[hdl(cmp_eq)]
pub struct UnitOutputWrite<OutRegNumWidth: Size> {
pub which: UnitOutRegNum<OutRegNumWidth>,
pub value: PRegValue,
}
@ -376,21 +300,21 @@ impl<ExtraOut: Type> UnitResult<ExtraOut> {
}
}
#[hdl(no_static)]
pub struct UnitOutput<C: PhantomConstGet<CpuConfig>, ExtraOut> {
pub which: UnitOutRegNum<C>,
#[hdl]
pub struct UnitOutput<OutRegNumWidth: Size, ExtraOut> {
pub which: UnitOutRegNum<OutRegNumWidth>,
pub result: UnitResult<ExtraOut>,
}
impl<C: PhantomConstCpuConfig, ExtraOut: Type> UnitOutput<C, ExtraOut> {
impl<OutRegNumWidth: Size, ExtraOut: Type> UnitOutput<OutRegNumWidth, ExtraOut> {
pub fn extra_out_ty(self) -> ExtraOut {
self.result.extra_out_ty()
}
}
#[hdl(cmp_eq, no_static)]
pub struct UnitCancelInput<C: PhantomConstGet<CpuConfig>> {
pub which: UnitOutRegNum<C>,
#[hdl(cmp_eq)]
pub struct UnitCancelInput<OutRegNumWidth: Size> {
pub which: UnitOutRegNum<OutRegNumWidth>,
}
pub trait UnitTrait:
@ -408,7 +332,7 @@ pub trait UnitTrait:
fn extract_mop(
&self,
mop: Expr<RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
) -> Expr<HdlOption<Self::MOp>>;
fn module(&self) -> Interned<Module<Self::Type>>;
@ -416,7 +340,7 @@ pub trait UnitTrait:
fn unit_to_reg_alloc(
&self,
this: Expr<Self::Type>,
) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>>;
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>>;
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain>;
@ -466,7 +390,7 @@ impl UnitTrait for DynUnit {
fn extract_mop(
&self,
mop: Expr<RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
) -> Expr<HdlOption<Self::MOp>> {
self.unit.extract_mop(mop)
}
@ -478,7 +402,7 @@ impl UnitTrait for DynUnit {
fn unit_to_reg_alloc(
&self,
this: Expr<Self::Type>,
) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
self.unit.unit_to_reg_alloc(this)
}
@ -521,7 +445,7 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T
fn extract_mop(
&self,
mop: Expr<RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
) -> Expr<HdlOption<Self::MOp>> {
Expr::from_enum(Expr::as_enum(self.0.extract_mop(mop)))
}
@ -533,7 +457,7 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T
fn unit_to_reg_alloc(
&self,
this: Expr<Self::Type>,
) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
Expr::from_bundle(Expr::as_bundle(
self.0.unit_to_reg_alloc(Expr::from_bundle(this)),
))

View file

@ -19,13 +19,16 @@ use crate::{
},
};
use fayalite::{
intern::Interned, module::wire_with_loc, prelude::*, util::ready_valid::ReadyValid,
intern::{Intern, Interned},
module::wire_with_loc,
prelude::*,
util::ready_valid::ReadyValid,
};
use std::{collections::HashMap, ops::RangeTo};
#[hdl]
fn add_sub<SrcCount: KnownSize>(
mop: Expr<AddSubMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, SrcCount>>,
mop: Expr<AddSubMOp<UnitOutRegNum<DynSize>, DynSize, SrcCount>>,
pc: Expr<UInt<64>>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
@ -242,7 +245,7 @@ fn add_sub<SrcCount: KnownSize>(
#[hdl]
fn logical_flags(
mop: Expr<LogicalFlagsMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
mop: Expr<LogicalFlagsMOp<UnitOutRegNum<DynSize>, DynSize>>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
) -> Expr<UnitResultCompleted<()>> {
@ -256,7 +259,7 @@ fn logical_flags(
#[hdl]
fn logical(
mop: Expr<LogicalMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, ConstUsize<2>>>,
mop: Expr<LogicalMOp<UnitOutRegNum<DynSize>, DynSize, ConstUsize<2>>>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
) -> Expr<UnitResultCompleted<()>> {
@ -270,7 +273,7 @@ fn logical(
#[hdl]
fn logical_i(
mop: Expr<LogicalMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, ConstUsize<1>>>,
mop: Expr<LogicalMOp<UnitOutRegNum<DynSize>, DynSize, ConstUsize<1>>>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
) -> Expr<UnitResultCompleted<()>> {
@ -284,7 +287,7 @@ fn logical_i(
#[hdl]
fn shift_rotate(
mop: Expr<ShiftRotateMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
mop: Expr<ShiftRotateMOp<UnitOutRegNum<DynSize>, DynSize>>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
) -> Expr<UnitResultCompleted<()>> {
@ -298,7 +301,7 @@ fn shift_rotate(
#[hdl]
fn compare<SrcCount: KnownSize>(
mop: Expr<CompareMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, SrcCount>>,
mop: Expr<CompareMOp<UnitOutRegNum<DynSize>, DynSize, SrcCount>>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
) -> Expr<UnitResultCompleted<()>> {
@ -312,7 +315,7 @@ fn compare<SrcCount: KnownSize>(
#[hdl]
fn branch<SrcCount: KnownSize>(
mop: Expr<BranchMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, SrcCount>>,
mop: Expr<BranchMOp<UnitOutRegNum<DynSize>, DynSize, SrcCount>>,
pc: Expr<UInt<64>>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
@ -327,7 +330,7 @@ fn branch<SrcCount: KnownSize>(
#[hdl]
fn read_special(
mop: Expr<ReadSpecialMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
mop: Expr<ReadSpecialMOp<UnitOutRegNum<DynSize>, DynSize>>,
pc: Expr<UInt<64>>,
flags_mode: Expr<FlagsMode>,
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
@ -341,18 +344,20 @@ fn read_special(
}
#[hdl_module]
pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) {
pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
#[hdl]
let cd: ClockDomain = m.input();
#[hdl]
let unit_to_reg_alloc: UnitToRegAlloc<
PhantomConst<CpuConfig>,
AluBranchMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>,
AluBranchMOp<UnitOutRegNum<DynSize>, DynSize>,
(),
> = m.output(
UnitToRegAlloc[config][AluBranchMOp[UnitOutRegNum[config]][config.get().p_reg_num_width()]]
[()],
);
DynSize,
DynSize,
DynSize,
> = m.output(config.unit_to_reg_alloc(
AluBranchMOp[config.unit_out_reg_num()][config.p_reg_num_width()],
(),
));
#[hdl]
let global_state: GlobalState = m.input();
@ -370,11 +375,10 @@ pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) {
#[hdl]
if let HdlSome(execute_start) = ReadyValid::firing_data(unit_base.execute_start) {
#[hdl]
let ExecuteStart::<_, _> {
let ExecuteStart::<_> {
mop,
pc,
src_values,
config: _,
} = execute_start;
#[hdl]
match mop {
@ -576,14 +580,14 @@ pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct AluBranch {
config: PhantomConst<CpuConfig>,
config: Interned<CpuConfig>,
module: Interned<Module<alu_branch>>,
}
impl AluBranch {
pub fn new(config: PhantomConst<CpuConfig>, unit_index: usize) -> Self {
pub fn new(config: &CpuConfig, unit_index: usize) -> Self {
Self {
config,
config: config.intern(),
module: alu_branch(config, unit_index),
}
}
@ -592,7 +596,7 @@ impl AluBranch {
impl UnitTrait for AluBranch {
type Type = alu_branch;
type ExtraOut = ();
type MOp = AluBranchMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>;
type MOp = AluBranchMOp<UnitOutRegNum<DynSize>, DynSize>;
fn ty(&self) -> Self::Type {
self.module.io_ty()
@ -612,7 +616,7 @@ impl UnitTrait for AluBranch {
fn extract_mop(
&self,
mop: Expr<RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
) -> Expr<HdlOption<Self::MOp>> {
UnitMOp::alu_branch_mop(mop)
}
@ -624,7 +628,7 @@ impl UnitTrait for AluBranch {
fn unit_to_reg_alloc(
&self,
this: Expr<Self::Type>,
) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
this.unit_to_reg_alloc
}

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information
use crate::{
config::{CpuConfig, CpuConfigUnitCount, PhantomConstCpuConfig},
config::CpuConfig,
instruction::{COMMON_MOP_SRC_LEN, MOpTrait, PRegNum, UnitNum, UnitOutRegNum},
register::PRegValue,
unit::{UnitCancelInput, UnitOutput, UnitOutputWrite},
@ -15,11 +15,13 @@ use fayalite::{
ty::StaticType,
util::ready_valid::ReadyValid,
};
use std::marker::PhantomData;
#[hdl(no_static)]
pub struct UnitForwardingInfo<C: PhantomConstGet<CpuConfig>> {
pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<C>>, CpuConfigUnitCount<C>>,
pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<C>>, CpuConfigUnitCount<C>>,
#[hdl]
pub struct UnitForwardingInfo<UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size> {
pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<OutRegNumWidth>>, UnitCount>,
pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<OutRegNumWidth>>, UnitCount>,
pub _phantom: PhantomData<UnitNumWidth>,
}
#[hdl]
@ -28,18 +30,26 @@ pub struct UnitInput<MOp: Type> {
pub pc: UInt<64>,
}
#[hdl(no_static)]
pub struct UnitToRegAlloc<C: PhantomConstGet<CpuConfig>, MOp: Type, ExtraOut: Type> {
#[hdl]
pub struct UnitToRegAlloc<
MOp: Type,
ExtraOut: Type,
UnitNumWidth: Size,
OutRegNumWidth: Size,
UnitCount: Size,
> {
#[hdl(flip)]
pub unit_forwarding_info: UnitForwardingInfo<C>,
pub unit_forwarding_info: UnitForwardingInfo<UnitNumWidth, OutRegNumWidth, UnitCount>,
#[hdl(flip)]
pub input: ReadyValid<UnitInput<MOp>>,
#[hdl(flip)]
pub cancel_input: HdlOption<UnitCancelInput<C>>,
pub output: HdlOption<UnitOutput<C, ExtraOut>>,
pub cancel_input: HdlOption<UnitCancelInput<OutRegNumWidth>>,
pub output: HdlOption<UnitOutput<OutRegNumWidth, ExtraOut>>,
}
impl<C: PhantomConstCpuConfig, MOp: Type, ExtraOut: Type> UnitToRegAlloc<C, MOp, ExtraOut> {
impl<MOp: Type, ExtraOut: Type, UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size>
UnitToRegAlloc<MOp, ExtraOut, UnitNumWidth, OutRegNumWidth, UnitCount>
{
pub fn mop_ty(self) -> MOp {
self.input.data.HdlSome.mop
}
@ -48,20 +58,16 @@ impl<C: PhantomConstCpuConfig, MOp: Type, ExtraOut: Type> UnitToRegAlloc<C, MOp,
}
}
#[hdl(no_static)]
pub struct ExecuteStart<
C: PhantomConstGet<CpuConfig>,
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<C>>,
> {
#[hdl]
pub struct ExecuteStart<MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>>> {
pub mop: MOp,
pub pc: UInt<64>,
pub src_values: Array<PRegValue, { COMMON_MOP_SRC_LEN }>,
pub config: C,
}
#[hdl(no_static)]
pub struct ExecuteEnd<C: PhantomConstGet<CpuConfig>, ExtraOut> {
pub unit_output: UnitOutput<C, ExtraOut>,
#[hdl]
pub struct ExecuteEnd<OutRegNumWidth: Size, ExtraOut> {
pub unit_output: UnitOutput<OutRegNumWidth, ExtraOut>,
}
#[hdl]
@ -234,10 +240,10 @@ impl InFlightOpsSummary<DynSize> {
#[hdl_module]
pub fn unit_base<
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<PhantomConst<CpuConfig>>, SrcRegWidth = DynSize>,
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>, SrcRegWidth = DynSize>,
ExtraOut: Type,
>(
config: PhantomConst<CpuConfig>,
config: &CpuConfig,
unit_index: usize,
mop_ty: MOp,
extra_out_ty: ExtraOut,
@ -245,18 +251,17 @@ pub fn unit_base<
#[hdl]
let cd: ClockDomain = m.input();
#[hdl]
let unit_to_reg_alloc: UnitToRegAlloc<PhantomConst<CpuConfig>, MOp, ExtraOut> =
m.output(UnitToRegAlloc[config][mop_ty][extra_out_ty]);
let unit_to_reg_alloc: UnitToRegAlloc<MOp, ExtraOut, DynSize, DynSize, DynSize> =
m.output(config.unit_to_reg_alloc(mop_ty, extra_out_ty));
#[hdl]
let execute_start: ReadyValid<ExecuteStart<PhantomConst<CpuConfig>, MOp>> =
m.output(ReadyValid[ExecuteStart[config][mop_ty]]);
let execute_start: ReadyValid<ExecuteStart<MOp>> = m.output(ReadyValid[ExecuteStart[mop_ty]]);
#[hdl]
let execute_end: HdlOption<ExecuteEnd<PhantomConst<CpuConfig>, ExtraOut>> =
m.input(HdlOption[ExecuteEnd[config][extra_out_ty]]);
let execute_end: HdlOption<ExecuteEnd<DynSize, ExtraOut>> =
m.input(HdlOption[ExecuteEnd[config.out_reg_num_width][extra_out_ty]]);
connect(execute_start.data, execute_start.ty().data.HdlNone());
let max_in_flight = config.get().unit_max_in_flight(unit_index).get();
let max_in_flight = config.unit_max_in_flight(unit_index).get();
let in_flight_op_ty = InFlightOp[mop_ty];
#[hdl]
let in_flight_ops = reg_builder()
@ -274,15 +279,16 @@ pub fn unit_base<
);
#[hdl]
let UnitForwardingInfo::<_> {
let UnitForwardingInfo::<_, _, _> {
unit_output_writes,
unit_reg_frees,
_phantom: _,
} = unit_to_reg_alloc.unit_forwarding_info;
#[hdl]
let read_src_regs = wire(mop_ty.src_regs_ty());
connect(
read_src_regs,
repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
);
#[hdl]
let read_src_values = wire();
@ -291,7 +297,7 @@ pub fn unit_base<
let input_src_regs = wire(mop_ty.src_regs_ty());
connect(
input_src_regs,
repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
);
#[hdl]
let input_src_regs_valid = wire();
@ -303,7 +309,7 @@ pub fn unit_base<
Bool,
SourceLocation::caller(),
);
mem.depth(1 << config.get().out_reg_num_width);
mem.depth(1 << config.out_reg_num_width);
mem
})
.collect();
@ -313,11 +319,11 @@ pub fn unit_base<
PRegValue,
SourceLocation::caller(),
);
unit_output_regs.depth(1 << config.get().out_reg_num_width);
unit_output_regs.depth(1 << config.out_reg_num_width);
for src_index in 0..COMMON_MOP_SRC_LEN {
let read_port = unit_output_regs.new_read_port();
let p_reg_num = read_src_regs[src_index].cast_bits_to(PRegNum[config]);
let p_reg_num = read_src_regs[src_index].cast_bits_to(config.p_reg_num());
connect_any(read_port.addr, p_reg_num.unit_out_reg.value);
connect(read_port.en, false);
connect(read_port.clk, cd.clk);
@ -330,7 +336,7 @@ pub fn unit_base<
for src_index in 0..COMMON_MOP_SRC_LEN {
let read_port = unit_output_regs_valid[unit_index].new_read_port();
let p_reg_num = input_src_regs[src_index].cast_bits_to(PRegNum[config]);
let p_reg_num = input_src_regs[src_index].cast_bits_to(config.p_reg_num());
connect_any(read_port.addr, p_reg_num.unit_out_reg.value);
connect(read_port.en, false);
connect(read_port.clk, cd.clk);
@ -361,8 +367,8 @@ pub fn unit_base<
connect_any(ready_write_port.addr, unit_output_write.which.value);
connect(ready_write_port.en, true);
let p_reg_num = #[hdl]
PRegNum::<_> {
unit_num: UnitNum[config].from_index(unit_index),
PRegNum::<_, _> {
unit_num: config.unit_num().from_index(unit_index),
unit_out_reg: unit_output_write.which,
};
for src_index in 0..COMMON_MOP_SRC_LEN {
@ -393,11 +399,10 @@ pub fn unit_base<
execute_start.data,
HdlSome(
#[hdl]
ExecuteStart::<_, _> {
ExecuteStart::<_> {
mop: in_flight_op.mop,
pc: in_flight_op.pc,
src_values: read_src_values,
config,
},
),
);
@ -420,7 +425,7 @@ pub fn unit_base<
let input_mop_src_regs = wire(mop_ty.src_regs_ty());
connect(
input_mop_src_regs,
repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
);
MOp::connect_src_regs(mop, input_mop_src_regs);
let src_ready_flags = wire_with_loc(
@ -492,7 +497,7 @@ pub fn unit_base<
);
connect(
src_regs,
repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
);
MOp::connect_src_regs(mop, src_regs);
@ -516,8 +521,8 @@ pub fn unit_base<
value: _,
} = unit_output_write;
let p_reg_num = #[hdl]
PRegNum::<_> {
unit_num: UnitNum[config].from_index(unit_index),
PRegNum::<_, _> {
unit_num: config.unit_num().from_index(unit_index),
unit_out_reg,
};
for src_index in 0..COMMON_MOP_SRC_LEN {

File diff suppressed because it is too large Load diff

View file

@ -1163,7 +1163,13 @@ impl MockExecuteState {
id: &insn.id,
next_pc,
call_stack_op: mock_insn.call_stack_op(pc),
cond_br_taken,
cond_br_taken: if let Some(cond_br_taken) = cond_br_taken {
#[hdl(sim)]
HdlSome(cond_br_taken)
} else {
#[hdl(sim)]
HdlNone()
},
config: self.config,
},
)

View file

@ -1,6 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
#![cfg(todo)]
use cpu::{
config::{CpuConfig, UnitConfig},

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -152,7 +152,16 @@ fn test_decode_insn() {
} in test_cases::test_cases()
{
sim.write(sim.io().first_input, first_input);
sim.write(sim.io().second_input, second_input);
sim.write(
sim.io().second_input,
if let Some(v) = second_input {
#[hdl(sim)]
HdlSome(v)
} else {
#[hdl(sim)]
HdlNone()
},
);
sim.advance_time(SimDuration::from_micros(1));
let second_input_used = sim.read_bool(sim.io().second_input_used);
let is_illegal = sim.read_bool(sim.io().is_illegal);

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information
use crate::test_cases::{TestCase, insn_single};
use cpu::instruction::{CompareMOp, CompareMode, MOpDestReg, MOpRegNum};
use cpu::instruction::{CompareMOp, CompareMode, MOpDestReg, MOpRegNum, OutputIntegerMode};
use fayalite::prelude::*;
/// covers instructions in PowerISA v3.1C Book I 3.3.10 Fixed-Point Compare Instructions
@ -15,6 +15,7 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(4).value],
0x1234.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.S32(),
),
));
@ -26,6 +27,7 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(4).value],
(0x89abu16 as i16).cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.S64(),
),
));
@ -39,6 +41,8 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.S32(),
),
));
@ -52,6 +56,8 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.S64(),
),
));
@ -63,6 +69,7 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(4).value],
0x1234.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.U32(),
),
));
@ -74,6 +81,7 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(4).value],
0x89ab.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.U64(),
),
));
@ -87,6 +95,8 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.U32(),
),
));
@ -100,6 +110,8 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.U64(),
),
));
@ -113,6 +125,8 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.CmpRBOne(),
),
));
@ -126,6 +140,8 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.CmpRBTwo(),
),
));
@ -139,6 +155,8 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(4).value,
MOpRegNum::power_isa_gpr_reg_imm(5).value,
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
CompareMode.CmpEqB(),
),
));

View file

@ -30,7 +30,13 @@ fn rotate_imm(
) -> SimValue<ShiftRotateMOpImm> {
#[hdl(sim)]
ShiftRotateMOpImm {
shift_rotate_amount: amount.map(|amount| amount.cast_to_static::<UInt<_>>()),
shift_rotate_amount: if let Some(amount) = amount {
#[hdl(sim)]
HdlSome(amount.cast_to_static::<UInt<_>>())
} else {
#[hdl(sim)]
HdlNone()
},
shift_rotate_right: false,
dest_logic_op: if let Some((rotated_output_start, rotated_output_len)) =
rotated_output_start_and_len