Compare commits
8 commits
master
...
rename-exe
| Author | SHA1 | Date | |
|---|---|---|---|
| 409ca7bf97 | |||
| 9308e5d195 | |||
| 09c8c194e0 | |||
| 83b3f7bac9 | |||
| ba9ec3bd29 | |||
| 1229d9c758 | |||
| 283117d8df | |||
| 4d21ca622b |
24 changed files with 622360 additions and 11456 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -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#80b92c7dd3adcad8487a3f8224846e381219bfa6"
|
||||
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#26224abe1c145d1744da89e08b7f9c64ee2ee2ce"
|
||||
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#80b92c7dd3adcad8487a3f8224846e381219bfa6"
|
||||
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#26224abe1c145d1744da89e08b7f9c64ee2ee2ce"
|
||||
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#80b92c7dd3adcad8487a3f8224846e381219bfa6"
|
||||
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#26224abe1c145d1744da89e08b7f9c64ee2ee2ce"
|
||||
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#80b92c7dd3adcad8487a3f8224846e381219bfa6"
|
||||
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#26224abe1c145d1744da89e08b7f9c64ee2ee2ce"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"prettyplease",
|
||||
|
|
|
|||
|
|
@ -33,3 +33,6 @@ hex-literal.workspace = true
|
|||
regex = "1.12.2"
|
||||
sha2.workspace = true
|
||||
which.workspace = true
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(todo)'] }
|
||||
|
|
|
|||
|
|
@ -1,13 +1,7 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
use crate::{
|
||||
instruction::{CONST_ZERO_UNIT_NUM, MOpTrait, PRegNum, RenamedMOp, UnitNum, UnitOutRegNum},
|
||||
unit::{
|
||||
UnitCancelInput, UnitKind, UnitOutputWrite,
|
||||
unit_base::{UnitForwardingInfo, UnitToRegAlloc},
|
||||
},
|
||||
};
|
||||
use fayalite::prelude::*;
|
||||
use crate::{instruction::CONST_ZERO_UNIT_NUM, unit::UnitKind};
|
||||
use fayalite::{expr::HdlPartialOrdImpl, prelude::*};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
|
|
@ -101,54 +95,20 @@ 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)
|
||||
}
|
||||
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()]
|
||||
/// 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 fetch_width_in_bytes(&self) -> usize {
|
||||
1usize
|
||||
|
|
@ -188,6 +148,21 @@ 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;
|
||||
|
||||
|
|
@ -236,6 +211,10 @@ 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>>
|
||||
|
|
@ -243,6 +222,7 @@ pub trait PhantomConstCpuConfig:
|
|||
+ Type
|
||||
+ ToSimValue<Type = Self>
|
||||
+ ToExpr<Type = Self>
|
||||
+ HdlPartialOrdImpl<Self>
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1656,7 +1656,6 @@ impl DecodeState<'_> {
|
|||
MOpDestReg::new([crf(bf)], []),
|
||||
[gpr(ra).value],
|
||||
si.cast_to_static::<SInt<_>>(),
|
||||
OutputIntegerMode.Full64(),
|
||||
compare_mode,
|
||||
),
|
||||
);
|
||||
|
|
@ -1684,8 +1683,6 @@ impl DecodeState<'_> {
|
|||
CompareMOp::compare(
|
||||
MOpDestReg::new([crf(bf)], []),
|
||||
[gpr(ra).value, gpr(rb).value],
|
||||
0.cast_to_static::<SInt<_>>(),
|
||||
OutputIntegerMode.Full64(),
|
||||
compare_mode,
|
||||
),
|
||||
);
|
||||
|
|
@ -1714,7 +1711,6 @@ impl DecodeState<'_> {
|
|||
MOpDestReg::new([crf(bf)], []),
|
||||
[gpr(ra).value],
|
||||
ui.cast_to_static::<SInt<_>>(),
|
||||
OutputIntegerMode.Full64(),
|
||||
compare_mode,
|
||||
),
|
||||
);
|
||||
|
|
@ -1742,8 +1738,6 @@ impl DecodeState<'_> {
|
|||
CompareMOp::compare(
|
||||
MOpDestReg::new([crf(bf)], []),
|
||||
[gpr(ra).value, gpr(rb).value],
|
||||
0.cast_to_static::<SInt<_>>(),
|
||||
OutputIntegerMode.Full64(),
|
||||
compare_mode,
|
||||
),
|
||||
);
|
||||
|
|
@ -1771,8 +1765,6 @@ impl DecodeState<'_> {
|
|||
CompareMOp::compare(
|
||||
MOpDestReg::new([crf(bf)], []),
|
||||
[gpr(ra).value, gpr(rb).value],
|
||||
0.cast_to_static::<SInt<_>>(),
|
||||
OutputIntegerMode.Full64(),
|
||||
compare_mode,
|
||||
),
|
||||
);
|
||||
|
|
@ -1792,8 +1784,6 @@ impl DecodeState<'_> {
|
|||
CompareMOp::compare(
|
||||
MOpDestReg::new([crf(bf)], []),
|
||||
[gpr(ra).value, gpr(rb).value],
|
||||
0.cast_to_static::<SInt<_>>(),
|
||||
OutputIntegerMode.Full64(),
|
||||
CompareMode.CmpEqB(),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -523,7 +523,7 @@ impl<C: PhantomConstCpuConfig> L1ICacheStateSim<C> {
|
|||
kind,
|
||||
read_data,
|
||||
config: _,
|
||||
} = memory_operation_finish;
|
||||
} = memory_operation_finish.into_sim_value();
|
||||
#[hdl(sim)]
|
||||
match kind {
|
||||
MemoryOperationFinishKind::Success(success) =>
|
||||
|
|
@ -746,7 +746,7 @@ impl<C: PhantomConstCpuConfig> L1ICacheStateSim<C> {
|
|||
let NextPcToFetchInterfaceInner {
|
||||
start_pc,
|
||||
fetch_block_id,
|
||||
} = fetch;
|
||||
} = fetch.into_sim_value();
|
||||
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;
|
||||
} = cache_read_data.into_sim_value();
|
||||
let config = self.config();
|
||||
for entry in &mut self.queue {
|
||||
#[hdl(sim)]
|
||||
|
|
@ -1151,8 +1151,6 @@ 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 {
|
||||
|
|
@ -1168,26 +1166,11 @@ fn l1_i_cache_impl(config: PhantomConst<CpuConfig>) {
|
|||
.await;
|
||||
sim.write(
|
||||
memory_interface.start.data,
|
||||
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()
|
||||
},
|
||||
state.clone().try_start_memory_operation(),
|
||||
)
|
||||
.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
|
|
@ -192,6 +192,13 @@ 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 {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ 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;
|
||||
|
|
|
|||
|
|
@ -23,14 +23,13 @@ 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::{borrow::Cow, fmt};
|
||||
use std::fmt;
|
||||
|
||||
pub const FETCH_BLOCK_ID_WIDTH: usize = FetchBlockIdInt::BITS as usize;
|
||||
type FetchBlockIdInt = u8;
|
||||
|
|
@ -53,7 +52,7 @@ pub struct NextPcToFetchInterface<C: PhantomConstGet<CpuConfig>> {
|
|||
pub config: C,
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
#[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.
|
||||
/// This will be replaced at a later point.
|
||||
|
|
@ -93,101 +92,6 @@ 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.
|
||||
|
|
@ -2781,8 +2685,10 @@ 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> {
|
||||
self.HdlNone().to_sim_value_with_type(self)
|
||||
#[hdl(sim)]
|
||||
self.HdlNone()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2911,50 +2817,13 @@ impl ResetSteps for CallStack {
|
|||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
#[hdl(cmp_eq)]
|
||||
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>> {
|
||||
|
|
@ -2983,7 +2852,7 @@ impl BTBEntryInsnKind {
|
|||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
#[hdl(cmp_eq)]
|
||||
enum BTBEntryAddrKind {
|
||||
Unconditional,
|
||||
Indirect,
|
||||
|
|
@ -2991,43 +2860,6 @@ 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 {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use fayalite::{
|
|||
prelude::*,
|
||||
ty::StaticType,
|
||||
};
|
||||
use std::fmt;
|
||||
use std::{any::Any, fmt};
|
||||
|
||||
#[hdl]
|
||||
pub enum FlagsMode {
|
||||
|
|
@ -47,6 +47,11 @@ 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>);
|
||||
|
|
@ -467,6 +472,33 @@ 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -739,6 +771,31 @@ 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 }>> {
|
||||
|
|
@ -782,4 +839,37 @@ 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()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2209
crates/cpu/src/rename_execute_retire.rs
Normal file
2209
crates/cpu/src/rename_execute_retire.rs
Normal file
File diff suppressed because it is too large
Load diff
207
crates/cpu/src/rename_execute_retire/to_unit_interfaces.rs
Normal file
207
crates/cpu/src/rename_execute_retire/to_unit_interfaces.rs
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
// 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()
|
||||
}
|
||||
}
|
||||
41
crates/cpu/src/rename_execute_retire/unit.mermaid
Normal file
41
crates/cpu/src/rename_execute_retire/unit.mermaid
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
%% 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
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
// See Notices.txt for copyright information
|
||||
|
||||
use crate::{
|
||||
config::CpuConfig,
|
||||
config::{CpuConfig, PhantomConstCpuConfig},
|
||||
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]
|
||||
#[hdl(custom_debug(sim))]
|
||||
$(#[$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($extract:ident, $extract_sim:ident, $extract_sim_ref:ident, $extract_sim_mut:ident)]
|
||||
$(#[$variant_meta:meta])*
|
||||
$Unit:ident($Op:ty),
|
||||
)*
|
||||
|
|
@ -48,7 +48,7 @@ macro_rules! all_units {
|
|||
}
|
||||
|
||||
impl $UnitKind {
|
||||
pub fn unit(self, config: &CpuConfig, unit_index: usize) -> DynUnit {
|
||||
pub fn unit(self, config: PhantomConst<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]
|
||||
#[hdl(custom_debug(sim))]
|
||||
$(#[$enum_meta])*
|
||||
$vis enum $UnitMOpEnum<
|
||||
$DestReg: Type,
|
||||
|
|
@ -112,6 +112,15 @@ 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>> {
|
||||
|
|
@ -126,6 +135,34 @@ 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
|
||||
|
|
@ -196,6 +233,45 @@ 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 _: () = {
|
||||
|
|
@ -245,7 +321,7 @@ macro_rules! all_units {
|
|||
all_units! {
|
||||
#[hdl_unit_kind = HdlUnitKind]
|
||||
#[unit_kind = UnitKind]
|
||||
#[hdl]
|
||||
#[hdl(custom_debug(sim))]
|
||||
pub enum UnitMOp<
|
||||
DestReg: Type,
|
||||
SrcRegWidth: Size,
|
||||
|
|
@ -254,14 +330,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]
|
||||
#[extract(alu_branch_mop, alu_branch_mop_sim, alu_branch_mop_sim_ref, alu_branch_mop_sim_mut)]
|
||||
AluBranch(AluBranchMOp<DestReg, SrcRegWidth>),
|
||||
#[transformed_move]
|
||||
#[create_dyn_unit_fn = |config, unit_index| todo!()]
|
||||
#[extract = transformed_move_mop]
|
||||
#[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| todo!()]
|
||||
#[extract = load_store_mop]
|
||||
#[extract(load_store_mop, load_store_mop_sim, load_store_mop_sim_ref, load_store_mop_sim_mut)]
|
||||
LoadStore(LoadStoreMOp<DestReg, SrcRegWidth>),
|
||||
}
|
||||
}
|
||||
|
|
@ -277,9 +353,9 @@ pub struct UnitResultCompleted<ExtraOut> {
|
|||
pub extra_out: ExtraOut,
|
||||
}
|
||||
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct UnitOutputWrite<OutRegNumWidth: Size> {
|
||||
pub which: UnitOutRegNum<OutRegNumWidth>,
|
||||
#[hdl(cmp_eq, no_static)]
|
||||
pub struct UnitOutputWrite<C: PhantomConstGet<CpuConfig>> {
|
||||
pub which: UnitOutRegNum<C>,
|
||||
pub value: PRegValue,
|
||||
}
|
||||
|
||||
|
|
@ -300,21 +376,21 @@ impl<ExtraOut: Type> UnitResult<ExtraOut> {
|
|||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
pub struct UnitOutput<OutRegNumWidth: Size, ExtraOut> {
|
||||
pub which: UnitOutRegNum<OutRegNumWidth>,
|
||||
#[hdl(no_static)]
|
||||
pub struct UnitOutput<C: PhantomConstGet<CpuConfig>, ExtraOut> {
|
||||
pub which: UnitOutRegNum<C>,
|
||||
pub result: UnitResult<ExtraOut>,
|
||||
}
|
||||
|
||||
impl<OutRegNumWidth: Size, ExtraOut: Type> UnitOutput<OutRegNumWidth, ExtraOut> {
|
||||
impl<C: PhantomConstCpuConfig, ExtraOut: Type> UnitOutput<C, ExtraOut> {
|
||||
pub fn extra_out_ty(self) -> ExtraOut {
|
||||
self.result.extra_out_ty()
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct UnitCancelInput<OutRegNumWidth: Size> {
|
||||
pub which: UnitOutRegNum<OutRegNumWidth>,
|
||||
#[hdl(cmp_eq, no_static)]
|
||||
pub struct UnitCancelInput<C: PhantomConstGet<CpuConfig>> {
|
||||
pub which: UnitOutRegNum<C>,
|
||||
}
|
||||
|
||||
pub trait UnitTrait:
|
||||
|
|
@ -332,7 +408,7 @@ pub trait UnitTrait:
|
|||
|
||||
fn extract_mop(
|
||||
&self,
|
||||
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
mop: Expr<RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
||||
) -> Expr<HdlOption<Self::MOp>>;
|
||||
|
||||
fn module(&self) -> Interned<Module<Self::Type>>;
|
||||
|
|
@ -340,7 +416,7 @@ pub trait UnitTrait:
|
|||
fn unit_to_reg_alloc(
|
||||
&self,
|
||||
this: Expr<Self::Type>,
|
||||
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>>;
|
||||
) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>>;
|
||||
|
||||
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain>;
|
||||
|
||||
|
|
@ -390,7 +466,7 @@ impl UnitTrait for DynUnit {
|
|||
|
||||
fn extract_mop(
|
||||
&self,
|
||||
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
mop: Expr<RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
||||
) -> Expr<HdlOption<Self::MOp>> {
|
||||
self.unit.extract_mop(mop)
|
||||
}
|
||||
|
|
@ -402,7 +478,7 @@ impl UnitTrait for DynUnit {
|
|||
fn unit_to_reg_alloc(
|
||||
&self,
|
||||
this: Expr<Self::Type>,
|
||||
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
|
||||
) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
|
||||
self.unit.unit_to_reg_alloc(this)
|
||||
}
|
||||
|
||||
|
|
@ -445,7 +521,7 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T
|
|||
|
||||
fn extract_mop(
|
||||
&self,
|
||||
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
mop: Expr<RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
||||
) -> Expr<HdlOption<Self::MOp>> {
|
||||
Expr::from_enum(Expr::as_enum(self.0.extract_mop(mop)))
|
||||
}
|
||||
|
|
@ -457,7 +533,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<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
|
||||
) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
|
||||
Expr::from_bundle(Expr::as_bundle(
|
||||
self.0.unit_to_reg_alloc(Expr::from_bundle(this)),
|
||||
))
|
||||
|
|
|
|||
|
|
@ -19,16 +19,13 @@ use crate::{
|
|||
},
|
||||
};
|
||||
use fayalite::{
|
||||
intern::{Intern, Interned},
|
||||
module::wire_with_loc,
|
||||
prelude::*,
|
||||
util::ready_valid::ReadyValid,
|
||||
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<DynSize>, DynSize, SrcCount>>,
|
||||
mop: Expr<AddSubMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, SrcCount>>,
|
||||
pc: Expr<UInt<64>>,
|
||||
flags_mode: Expr<FlagsMode>,
|
||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||
|
|
@ -245,7 +242,7 @@ fn add_sub<SrcCount: KnownSize>(
|
|||
|
||||
#[hdl]
|
||||
fn logical_flags(
|
||||
mop: Expr<LogicalFlagsMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
mop: Expr<LogicalFlagsMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
||||
flags_mode: Expr<FlagsMode>,
|
||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||
) -> Expr<UnitResultCompleted<()>> {
|
||||
|
|
@ -259,7 +256,7 @@ fn logical_flags(
|
|||
|
||||
#[hdl]
|
||||
fn logical(
|
||||
mop: Expr<LogicalMOp<UnitOutRegNum<DynSize>, DynSize, ConstUsize<2>>>,
|
||||
mop: Expr<LogicalMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, ConstUsize<2>>>,
|
||||
flags_mode: Expr<FlagsMode>,
|
||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||
) -> Expr<UnitResultCompleted<()>> {
|
||||
|
|
@ -273,7 +270,7 @@ fn logical(
|
|||
|
||||
#[hdl]
|
||||
fn logical_i(
|
||||
mop: Expr<LogicalMOp<UnitOutRegNum<DynSize>, DynSize, ConstUsize<1>>>,
|
||||
mop: Expr<LogicalMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, ConstUsize<1>>>,
|
||||
flags_mode: Expr<FlagsMode>,
|
||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||
) -> Expr<UnitResultCompleted<()>> {
|
||||
|
|
@ -287,7 +284,7 @@ fn logical_i(
|
|||
|
||||
#[hdl]
|
||||
fn shift_rotate(
|
||||
mop: Expr<ShiftRotateMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
mop: Expr<ShiftRotateMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
||||
flags_mode: Expr<FlagsMode>,
|
||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||
) -> Expr<UnitResultCompleted<()>> {
|
||||
|
|
@ -301,7 +298,7 @@ fn shift_rotate(
|
|||
|
||||
#[hdl]
|
||||
fn compare<SrcCount: KnownSize>(
|
||||
mop: Expr<CompareMOp<UnitOutRegNum<DynSize>, DynSize, SrcCount>>,
|
||||
mop: Expr<CompareMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, SrcCount>>,
|
||||
flags_mode: Expr<FlagsMode>,
|
||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||
) -> Expr<UnitResultCompleted<()>> {
|
||||
|
|
@ -315,7 +312,7 @@ fn compare<SrcCount: KnownSize>(
|
|||
|
||||
#[hdl]
|
||||
fn branch<SrcCount: KnownSize>(
|
||||
mop: Expr<BranchMOp<UnitOutRegNum<DynSize>, DynSize, SrcCount>>,
|
||||
mop: Expr<BranchMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, SrcCount>>,
|
||||
pc: Expr<UInt<64>>,
|
||||
flags_mode: Expr<FlagsMode>,
|
||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||
|
|
@ -330,7 +327,7 @@ fn branch<SrcCount: KnownSize>(
|
|||
|
||||
#[hdl]
|
||||
fn read_special(
|
||||
mop: Expr<ReadSpecialMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
mop: Expr<ReadSpecialMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
||||
pc: Expr<UInt<64>>,
|
||||
flags_mode: Expr<FlagsMode>,
|
||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||
|
|
@ -344,20 +341,18 @@ fn read_special(
|
|||
}
|
||||
|
||||
#[hdl_module]
|
||||
pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
|
||||
pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) {
|
||||
#[hdl]
|
||||
let cd: ClockDomain = m.input();
|
||||
#[hdl]
|
||||
let unit_to_reg_alloc: UnitToRegAlloc<
|
||||
AluBranchMOp<UnitOutRegNum<DynSize>, DynSize>,
|
||||
PhantomConst<CpuConfig>,
|
||||
AluBranchMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>,
|
||||
(),
|
||||
DynSize,
|
||||
DynSize,
|
||||
DynSize,
|
||||
> = m.output(config.unit_to_reg_alloc(
|
||||
AluBranchMOp[config.unit_out_reg_num()][config.p_reg_num_width()],
|
||||
(),
|
||||
));
|
||||
> = m.output(
|
||||
UnitToRegAlloc[config][AluBranchMOp[UnitOutRegNum[config]][config.get().p_reg_num_width()]]
|
||||
[()],
|
||||
);
|
||||
#[hdl]
|
||||
let global_state: GlobalState = m.input();
|
||||
|
||||
|
|
@ -375,10 +370,11 @@ pub fn alu_branch(config: &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 {
|
||||
|
|
@ -580,14 +576,14 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
|
|||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct AluBranch {
|
||||
config: Interned<CpuConfig>,
|
||||
config: PhantomConst<CpuConfig>,
|
||||
module: Interned<Module<alu_branch>>,
|
||||
}
|
||||
|
||||
impl AluBranch {
|
||||
pub fn new(config: &CpuConfig, unit_index: usize) -> Self {
|
||||
pub fn new(config: PhantomConst<CpuConfig>, unit_index: usize) -> Self {
|
||||
Self {
|
||||
config: config.intern(),
|
||||
config,
|
||||
module: alu_branch(config, unit_index),
|
||||
}
|
||||
}
|
||||
|
|
@ -596,7 +592,7 @@ impl AluBranch {
|
|||
impl UnitTrait for AluBranch {
|
||||
type Type = alu_branch;
|
||||
type ExtraOut = ();
|
||||
type MOp = AluBranchMOp<UnitOutRegNum<DynSize>, DynSize>;
|
||||
type MOp = AluBranchMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>;
|
||||
|
||||
fn ty(&self) -> Self::Type {
|
||||
self.module.io_ty()
|
||||
|
|
@ -616,7 +612,7 @@ impl UnitTrait for AluBranch {
|
|||
|
||||
fn extract_mop(
|
||||
&self,
|
||||
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
mop: Expr<RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
||||
) -> Expr<HdlOption<Self::MOp>> {
|
||||
UnitMOp::alu_branch_mop(mop)
|
||||
}
|
||||
|
|
@ -628,7 +624,7 @@ impl UnitTrait for AluBranch {
|
|||
fn unit_to_reg_alloc(
|
||||
&self,
|
||||
this: Expr<Self::Type>,
|
||||
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
|
||||
) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
|
||||
this.unit_to_reg_alloc
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// See Notices.txt for copyright information
|
||||
|
||||
use crate::{
|
||||
config::CpuConfig,
|
||||
config::{CpuConfig, CpuConfigUnitCount, PhantomConstCpuConfig},
|
||||
instruction::{COMMON_MOP_SRC_LEN, MOpTrait, PRegNum, UnitNum, UnitOutRegNum},
|
||||
register::PRegValue,
|
||||
unit::{UnitCancelInput, UnitOutput, UnitOutputWrite},
|
||||
|
|
@ -15,13 +15,11 @@ use fayalite::{
|
|||
ty::StaticType,
|
||||
util::ready_valid::ReadyValid,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[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(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]
|
||||
|
|
@ -30,26 +28,18 @@ pub struct UnitInput<MOp: Type> {
|
|||
pub pc: UInt<64>,
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
pub struct UnitToRegAlloc<
|
||||
MOp: Type,
|
||||
ExtraOut: Type,
|
||||
UnitNumWidth: Size,
|
||||
OutRegNumWidth: Size,
|
||||
UnitCount: Size,
|
||||
> {
|
||||
#[hdl(no_static)]
|
||||
pub struct UnitToRegAlloc<C: PhantomConstGet<CpuConfig>, MOp: Type, ExtraOut: Type> {
|
||||
#[hdl(flip)]
|
||||
pub unit_forwarding_info: UnitForwardingInfo<UnitNumWidth, OutRegNumWidth, UnitCount>,
|
||||
pub unit_forwarding_info: UnitForwardingInfo<C>,
|
||||
#[hdl(flip)]
|
||||
pub input: ReadyValid<UnitInput<MOp>>,
|
||||
#[hdl(flip)]
|
||||
pub cancel_input: HdlOption<UnitCancelInput<OutRegNumWidth>>,
|
||||
pub output: HdlOption<UnitOutput<OutRegNumWidth, ExtraOut>>,
|
||||
pub cancel_input: HdlOption<UnitCancelInput<C>>,
|
||||
pub output: HdlOption<UnitOutput<C, ExtraOut>>,
|
||||
}
|
||||
|
||||
impl<MOp: Type, ExtraOut: Type, UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size>
|
||||
UnitToRegAlloc<MOp, ExtraOut, UnitNumWidth, OutRegNumWidth, UnitCount>
|
||||
{
|
||||
impl<C: PhantomConstCpuConfig, MOp: Type, ExtraOut: Type> UnitToRegAlloc<C, MOp, ExtraOut> {
|
||||
pub fn mop_ty(self) -> MOp {
|
||||
self.input.data.HdlSome.mop
|
||||
}
|
||||
|
|
@ -58,16 +48,20 @@ impl<MOp: Type, ExtraOut: Type, UnitNumWidth: Size, OutRegNumWidth: Size, UnitCo
|
|||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
pub struct ExecuteStart<MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>>> {
|
||||
#[hdl(no_static)]
|
||||
pub struct ExecuteStart<
|
||||
C: PhantomConstGet<CpuConfig>,
|
||||
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<C>>,
|
||||
> {
|
||||
pub mop: MOp,
|
||||
pub pc: UInt<64>,
|
||||
pub src_values: Array<PRegValue, { COMMON_MOP_SRC_LEN }>,
|
||||
pub config: C,
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
pub struct ExecuteEnd<OutRegNumWidth: Size, ExtraOut> {
|
||||
pub unit_output: UnitOutput<OutRegNumWidth, ExtraOut>,
|
||||
#[hdl(no_static)]
|
||||
pub struct ExecuteEnd<C: PhantomConstGet<CpuConfig>, ExtraOut> {
|
||||
pub unit_output: UnitOutput<C, ExtraOut>,
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
|
|
@ -240,10 +234,10 @@ impl InFlightOpsSummary<DynSize> {
|
|||
|
||||
#[hdl_module]
|
||||
pub fn unit_base<
|
||||
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>, SrcRegWidth = DynSize>,
|
||||
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<PhantomConst<CpuConfig>>, SrcRegWidth = DynSize>,
|
||||
ExtraOut: Type,
|
||||
>(
|
||||
config: &CpuConfig,
|
||||
config: PhantomConst<CpuConfig>,
|
||||
unit_index: usize,
|
||||
mop_ty: MOp,
|
||||
extra_out_ty: ExtraOut,
|
||||
|
|
@ -251,17 +245,18 @@ pub fn unit_base<
|
|||
#[hdl]
|
||||
let cd: ClockDomain = m.input();
|
||||
#[hdl]
|
||||
let unit_to_reg_alloc: UnitToRegAlloc<MOp, ExtraOut, DynSize, DynSize, DynSize> =
|
||||
m.output(config.unit_to_reg_alloc(mop_ty, extra_out_ty));
|
||||
let unit_to_reg_alloc: UnitToRegAlloc<PhantomConst<CpuConfig>, MOp, ExtraOut> =
|
||||
m.output(UnitToRegAlloc[config][mop_ty][extra_out_ty]);
|
||||
#[hdl]
|
||||
let execute_start: ReadyValid<ExecuteStart<MOp>> = m.output(ReadyValid[ExecuteStart[mop_ty]]);
|
||||
let execute_start: ReadyValid<ExecuteStart<PhantomConst<CpuConfig>, MOp>> =
|
||||
m.output(ReadyValid[ExecuteStart[config][mop_ty]]);
|
||||
#[hdl]
|
||||
let execute_end: HdlOption<ExecuteEnd<DynSize, ExtraOut>> =
|
||||
m.input(HdlOption[ExecuteEnd[config.out_reg_num_width][extra_out_ty]]);
|
||||
let execute_end: HdlOption<ExecuteEnd<PhantomConst<CpuConfig>, ExtraOut>> =
|
||||
m.input(HdlOption[ExecuteEnd[config][extra_out_ty]]);
|
||||
|
||||
connect(execute_start.data, execute_start.ty().data.HdlNone());
|
||||
|
||||
let max_in_flight = config.unit_max_in_flight(unit_index).get();
|
||||
let max_in_flight = config.get().unit_max_in_flight(unit_index).get();
|
||||
let in_flight_op_ty = InFlightOp[mop_ty];
|
||||
#[hdl]
|
||||
let in_flight_ops = reg_builder()
|
||||
|
|
@ -279,16 +274,15 @@ 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(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
|
||||
repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
|
||||
);
|
||||
#[hdl]
|
||||
let read_src_values = wire();
|
||||
|
|
@ -297,7 +291,7 @@ pub fn unit_base<
|
|||
let input_src_regs = wire(mop_ty.src_regs_ty());
|
||||
connect(
|
||||
input_src_regs,
|
||||
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
|
||||
repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
|
||||
);
|
||||
#[hdl]
|
||||
let input_src_regs_valid = wire();
|
||||
|
|
@ -309,7 +303,7 @@ pub fn unit_base<
|
|||
Bool,
|
||||
SourceLocation::caller(),
|
||||
);
|
||||
mem.depth(1 << config.out_reg_num_width);
|
||||
mem.depth(1 << config.get().out_reg_num_width);
|
||||
mem
|
||||
})
|
||||
.collect();
|
||||
|
|
@ -319,11 +313,11 @@ pub fn unit_base<
|
|||
PRegValue,
|
||||
SourceLocation::caller(),
|
||||
);
|
||||
unit_output_regs.depth(1 << config.out_reg_num_width);
|
||||
unit_output_regs.depth(1 << config.get().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(config.p_reg_num());
|
||||
let p_reg_num = read_src_regs[src_index].cast_bits_to(PRegNum[config]);
|
||||
connect_any(read_port.addr, p_reg_num.unit_out_reg.value);
|
||||
connect(read_port.en, false);
|
||||
connect(read_port.clk, cd.clk);
|
||||
|
|
@ -336,7 +330,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(config.p_reg_num());
|
||||
let p_reg_num = input_src_regs[src_index].cast_bits_to(PRegNum[config]);
|
||||
connect_any(read_port.addr, p_reg_num.unit_out_reg.value);
|
||||
connect(read_port.en, false);
|
||||
connect(read_port.clk, cd.clk);
|
||||
|
|
@ -367,8 +361,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: config.unit_num().from_index(unit_index),
|
||||
PRegNum::<_> {
|
||||
unit_num: UnitNum[config].from_index(unit_index),
|
||||
unit_out_reg: unit_output_write.which,
|
||||
};
|
||||
for src_index in 0..COMMON_MOP_SRC_LEN {
|
||||
|
|
@ -399,10 +393,11 @@ 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,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
@ -425,7 +420,7 @@ pub fn unit_base<
|
|||
let input_mop_src_regs = wire(mop_ty.src_regs_ty());
|
||||
connect(
|
||||
input_mop_src_regs,
|
||||
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
|
||||
repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
|
||||
);
|
||||
MOp::connect_src_regs(mop, input_mop_src_regs);
|
||||
let src_ready_flags = wire_with_loc(
|
||||
|
|
@ -497,7 +492,7 @@ pub fn unit_base<
|
|||
);
|
||||
connect(
|
||||
src_regs,
|
||||
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
|
||||
repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
|
||||
);
|
||||
MOp::connect_src_regs(mop, src_regs);
|
||||
|
||||
|
|
@ -521,8 +516,8 @@ pub fn unit_base<
|
|||
value: _,
|
||||
} = unit_output_write;
|
||||
let p_reg_num = #[hdl]
|
||||
PRegNum::<_, _> {
|
||||
unit_num: config.unit_num().from_index(unit_index),
|
||||
PRegNum::<_> {
|
||||
unit_num: UnitNum[config].from_index(unit_index),
|
||||
unit_out_reg,
|
||||
};
|
||||
for src_index in 0..COMMON_MOP_SRC_LEN {
|
||||
|
|
|
|||
606523
crates/cpu/tests/expected/rename_execute_retire_fibonacci.vcd
generated
Normal file
606523
crates/cpu/tests/expected/rename_execute_retire_fibonacci.vcd
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1163,13 +1163,7 @@ impl MockExecuteState {
|
|||
id: &insn.id,
|
||||
next_pc,
|
||||
call_stack_op: mock_insn.call_stack_op(pc),
|
||||
cond_br_taken: if let Some(cond_br_taken) = cond_br_taken {
|
||||
#[hdl(sim)]
|
||||
HdlSome(cond_br_taken)
|
||||
} else {
|
||||
#[hdl(sim)]
|
||||
HdlNone()
|
||||
},
|
||||
cond_br_taken,
|
||||
config: self.config,
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
#![cfg(todo)]
|
||||
|
||||
use cpu::{
|
||||
config::{CpuConfig, UnitConfig},
|
||||
|
|
|
|||
2985
crates/cpu/tests/rename_execute_retire.rs
Normal file
2985
crates/cpu/tests/rename_execute_retire.rs
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -152,16 +152,7 @@ fn test_decode_insn() {
|
|||
} in test_cases::test_cases()
|
||||
{
|
||||
sim.write(sim.io().first_input, first_input);
|
||||
sim.write(
|
||||
sim.io().second_input,
|
||||
if let Some(v) = second_input {
|
||||
#[hdl(sim)]
|
||||
HdlSome(v)
|
||||
} else {
|
||||
#[hdl(sim)]
|
||||
HdlNone()
|
||||
},
|
||||
);
|
||||
sim.write(sim.io().second_input, second_input);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// See Notices.txt for copyright information
|
||||
|
||||
use crate::test_cases::{TestCase, insn_single};
|
||||
use cpu::instruction::{CompareMOp, CompareMode, MOpDestReg, MOpRegNum, OutputIntegerMode};
|
||||
use cpu::instruction::{CompareMOp, CompareMode, MOpDestReg, MOpRegNum};
|
||||
use fayalite::prelude::*;
|
||||
|
||||
/// covers instructions in PowerISA v3.1C Book I 3.3.10 Fixed-Point Compare Instructions
|
||||
|
|
@ -15,7 +15,6 @@ 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(),
|
||||
),
|
||||
));
|
||||
|
|
@ -27,7 +26,6 @@ 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(),
|
||||
),
|
||||
));
|
||||
|
|
@ -41,8 +39,6 @@ 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(),
|
||||
),
|
||||
));
|
||||
|
|
@ -56,8 +52,6 @@ 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(),
|
||||
),
|
||||
));
|
||||
|
|
@ -69,7 +63,6 @@ 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(),
|
||||
),
|
||||
));
|
||||
|
|
@ -81,7 +74,6 @@ 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(),
|
||||
),
|
||||
));
|
||||
|
|
@ -95,8 +87,6 @@ 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(),
|
||||
),
|
||||
));
|
||||
|
|
@ -110,8 +100,6 @@ 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(),
|
||||
),
|
||||
));
|
||||
|
|
@ -125,8 +113,6 @@ 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(),
|
||||
),
|
||||
));
|
||||
|
|
@ -140,8 +126,6 @@ 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(),
|
||||
),
|
||||
));
|
||||
|
|
@ -155,8 +139,6 @@ 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(),
|
||||
),
|
||||
));
|
||||
|
|
|
|||
|
|
@ -30,13 +30,7 @@ fn rotate_imm(
|
|||
) -> SimValue<ShiftRotateMOpImm> {
|
||||
#[hdl(sim)]
|
||||
ShiftRotateMOpImm {
|
||||
shift_rotate_amount: if let Some(amount) = amount {
|
||||
#[hdl(sim)]
|
||||
HdlSome(amount.cast_to_static::<UInt<_>>())
|
||||
} else {
|
||||
#[hdl(sim)]
|
||||
HdlNone()
|
||||
},
|
||||
shift_rotate_amount: amount.map(|amount| amount.cast_to_static::<UInt<_>>()),
|
||||
shift_rotate_right: false,
|
||||
dest_logic_op: if let Some((rotated_output_start, rotated_output_len)) =
|
||||
rotated_output_start_and_len
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue