diff --git a/Cargo.lock b/Cargo.lock index 78eca32..ade3f36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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#8e4eeef72340f1205ed5d2277dab112cdf352b35" +source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#226631594458f4137739baf98d2a9cd2c257242e" 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#8e4eeef72340f1205ed5d2277dab112cdf352b35" +source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#226631594458f4137739baf98d2a9cd2c257242e" 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#8e4eeef72340f1205ed5d2277dab112cdf352b35" +source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#226631594458f4137739baf98d2a9cd2c257242e" 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#8e4eeef72340f1205ed5d2277dab112cdf352b35" +source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#226631594458f4137739baf98d2a9cd2c257242e" dependencies = [ "indexmap", "prettyplease", diff --git a/crates/cpu/src/fetch.rs b/crates/cpu/src/fetch.rs index 52e3585..a87018d 100644 --- a/crates/cpu/src/fetch.rs +++ b/crates/cpu/src/fetch.rs @@ -523,7 +523,7 @@ impl L1ICacheStateSim { 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 L1ICacheStateSim { 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 L1ICacheStateSim { 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) { 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) { .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 diff --git a/crates/cpu/src/instruction.rs b/crates/cpu/src/instruction.rs index e8f2af1..969b1ee 100644 --- a/crates/cpu/src/instruction.rs +++ b/crates/cpu/src/instruction.rs @@ -12,7 +12,7 @@ use fayalite::{ intern::Interned, module::wire_with_loc, prelude::*, - ty::{StaticType, TypeProperties}, + ty::{SimValueDebug, StaticType, TypeProperties}, util::ConstBool, }; use std::{ @@ -86,14 +86,6 @@ pub trait MOpVisitVariants: MOpTrait { VisitOps::Target: MOpTrait; } -pub trait MOpDebug: MOpTrait { - fn mop_debug(this: &SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result; -} - -pub trait MOpImmDebug: Type { - fn mop_imm_debug(this: &SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result; -} - pub trait MOpTrait: Type { type Mapped: MOpTrait; type DestReg: Type; @@ -381,7 +373,7 @@ impl MOpVisitVariants for T { } } -#[hdl] +#[hdl(cmp_eq)] pub enum OutputIntegerMode { Full64, DupLow32, @@ -410,40 +402,6 @@ impl OutputIntegerMode { } } -impl HdlPartialEqImpl for OutputIntegerMode { - #[track_caller] - fn cmp_value_eq( - lhs: Self, - lhs_value: Cow<'_, Self::SimValue>, - rhs: Self, - rhs_value: Cow<'_, Self::SimValue>, - ) -> bool { - SimValue::opaque(&SimValue::from_value(lhs, lhs_value.into_owned())) - == SimValue::opaque(&SimValue::from_value(rhs, rhs_value.into_owned())) - } - - #[track_caller] - fn cmp_sim_value_eq( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) == SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_sim_value_ne( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) != SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_expr_eq(lhs: Expr, rhs: Expr) -> Expr { - lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits()) - } -} - pub const MOP_IMM_WIDTH: usize = 34; pub const MOP_MIN_REG_WIDTH: usize = 8; pub const COMMON_MOP_SRC_LEN: usize = 3; @@ -494,9 +452,12 @@ impl fmt::Debug for CommonMOpDefaultImm { } } -impl MOpImmDebug for CommonMOpDefaultImm { - fn mop_imm_debug(this: &SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ::fmt(this, f) +impl SimValueDebug for CommonMOpDefaultImm { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + ::fmt(value, f) } } @@ -625,7 +586,7 @@ impl HdlPartialEqImpl for CommonMOpDefaultImm + SimValueDebug for CommonMOp +{ + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Display::fmt(&Self::mop_debug(value, true), f) + } +} + impl CommonMOp { @@ -652,32 +624,11 @@ impl= MOP_MIN_REG_WIDTH, "{self:#?}"); } - fn debug_dest(this: &SimValue) -> impl fmt::Debug { - use std::any::Any; - fmt::from_fn(move |f| { - if let Some(dest) = ::downcast_ref::>(&this.dest) { - f.debug_set() - .entries( - MOpDestReg::regs_sim(dest) - .into_iter() - .filter(|&v| v != MOpRegNum::CONST_ZERO_REG_NUM), - ) - .finish() - } else if let Some(dest) = - ::downcast_ref::>>>(&this.dest) - { - fmt::Debug::fmt(&PRegNum::debug_sim(dest), f) - } else if let Some(dest) = ::downcast_ref::< - SimValue>>, - >(&this.dest) - { - fmt::Debug::fmt(&UnitOutRegNum::debug_sim(dest), f) - } else { - fmt::Debug::fmt(&this.dest, f) - } - }) - } - fn debug_sources(this: &SimValue, is_first: bool, is_last: bool) -> impl fmt::Display { + fn debug_sources( + this: &::SimValue, + is_first: bool, + is_last: bool, + ) -> impl fmt::Display { fmt::from_fn(move |f| { let mut need_comma = !is_first; for src in &this.src { @@ -694,15 +645,12 @@ impl, debug_imm: bool) -> impl fmt::Display - where - Imm: MOpImmDebug, - { + fn mop_debug(this: &::SimValue, debug_imm: bool) -> impl fmt::Display { fmt::from_fn(move |f| { - fmt::Debug::fmt(&Self::debug_dest(this), f)?; + write!(f, "{:?}", this.dest)?; fmt::Display::fmt(&Self::debug_sources(this, false, !debug_imm), f)?; if debug_imm { - MOpImmDebug::mop_imm_debug(&this.imm, f)?; + fmt::Debug::fmt(&this.imm, f)?; } Ok(()) }) @@ -814,7 +762,7 @@ pub const COMMON_MOP_3_IMM_WIDTH: usize = common_mop_max_imm_size(3); macro_rules! common_mop_struct { ( - #[debug($(#[$hdl:ident])? |$debug_this:ident, $debug_f:ident| $debug_block:block $(where $($debug_where:tt)*)?)] + #[debug($(#[$debug_hdl:ident])? |$debug_value:ident, $debug_f:ident| $debug_block:block $(where $($debug_where:tt)*)?)] #[mapped(<$NewDestReg:ident, $SrcRegWidth:ident> $mapped_ty:ty)] $(#[$struct_meta:meta])* $vis:vis struct $MOp:ident<$($Generic:ident: $GenericBound:ident),* $(,)?> { @@ -841,11 +789,11 @@ macro_rules! common_mop_struct { } } - impl<$($Generic: $GenericBound),*> MOpDebug for $MOp<$($Generic),*> + impl<$($Generic: $GenericBound),*> SimValueDebug for $MOp<$($Generic),*> $(where $($debug_where)*)? { - $(#[$hdl])? - fn mop_debug($debug_this: &SimValue, $debug_f: &mut fmt::Formatter<'_>) -> fmt::Result $debug_block + $(#[$debug_hdl])? + fn sim_value_debug($debug_value: &::SimValue, $debug_f: &mut fmt::Formatter<'_>) -> fmt::Result $debug_block } }; ( @@ -959,7 +907,6 @@ macro_rules! common_mop_struct { macro_rules! mop_enum { ( - $(#[debug(where $($debug_where:tt)*)])? #[impl_mop_into = $impl_mop_into:tt] $(#[$enum_meta:meta])* $vis:vis enum $MOp:ident< @@ -1028,23 +975,21 @@ macro_rules! mop_enum { impl< $DestReg: Type, $SrcRegWidth: Size, - $($MOpTypes: Type + MOpTrait,)* + $($MOpTypes: Type,)* $($Sizes: Size,)* - > crate::instruction::MOpDebug for $MOp< + > fayalite::ty::SimValueDebug for $MOp< $DestReg, $SrcRegWidth, $($MOpTypes,)* $($Sizes,)* - > - $(where $($debug_where)*)? - { + > { #[hdl] - fn mop_debug(this: &SimValue, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn sim_value_debug(this: &::SimValue, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { #![allow(unreachable_patterns)] #[hdl(sim)] match this { - Self::$FirstVariant(v) => <$first_ty as crate::instruction::MOpDebug>::mop_debug(v, f), - $(Self::$Variant(v) => <$ty as crate::instruction::MOpDebug>::mop_debug(v, f),)* + Self::$FirstVariant(v) => std::fmt::Debug::fmt(v, f), + $(Self::$Variant(v) => std::fmt::Debug::fmt(v, f),)* _ => std::fmt::Debug::fmt(this, f), } } @@ -1383,7 +1328,7 @@ common_mop_struct! { } } -impl +impl AluCommonMOp { #[hdl] @@ -1441,7 +1386,7 @@ common_mop_struct! { maybe_write_comma_flag!(f, add_pc, **add_pc) })] #[mapped( AddSubMOp)] - #[hdl(cmp_eq)] + #[hdl(cmp_eq, custom_debug(sim))] pub struct AddSubMOp { #[common] pub alu_common: AluCommonMOp>, @@ -1602,7 +1547,7 @@ impl Lut4 { } /// immediate values for [`LogicalFlagsMOp`]. See [`LogicalFlagsMOp`] for a description of the operation. -#[hdl(cmp_eq)] +#[hdl(cmp_eq, custom_debug(sim))] pub struct LogicalFlagsMOpImm { pub src0_start: UIntInRange<0, { PRegFlags::FLAG_COUNT }>, pub src1_start: UIntInRange<0, { PRegFlags::FLAG_COUNT }>, @@ -1611,17 +1556,20 @@ pub struct LogicalFlagsMOpImm { pub dest_count: UIntInRangeInclusive<0, { PRegFlags::FLAG_COUNT }>, } -impl MOpImmDebug for LogicalFlagsMOpImm { +impl SimValueDebug for LogicalFlagsMOpImm { #[hdl] - fn mop_imm_debug(this: &SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result { - #[hdl(sim)] - let Self { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + type SimValueT = ::SimValue; + let SimValueT:: { src0_start, src1_start, src2_start, dest_start, dest_count, - } = this; + } = value; write!( f, "{{[{dest_start}..][..{dest_count}] <= [{src0_start}..], [{src1_start}..], [{src2_start}..]}}" @@ -1843,7 +1791,7 @@ impl LogicalFlagsMOpImm { src2_start, dest_start, dest_count, - } = this; + } = this.into_sim_value(); Self::flags_operation_impl( src0_start, src1_start, @@ -2018,7 +1966,7 @@ common_mop_struct! { write!(f, "LogicalFlags {common}, {:?}", lut.lut) })] #[mapped( LogicalFlagsMOp)] - #[hdl(cmp_eq)] + #[hdl(cmp_eq, custom_debug(sim))] /// Operation: /// ``` /// # // set up a bunch of mock types and variables -- they don't necessarily match the real types @@ -2182,7 +2130,7 @@ common_mop_struct! { write!(f, "Logical {alu_common}, {:?}", lut.lut) })] #[mapped( LogicalMOp)] - #[hdl(cmp_eq)] + #[hdl(cmp_eq, custom_debug(sim))] pub struct LogicalMOp { #[common] pub alu_common: AluCommonMOp>, @@ -2254,7 +2202,7 @@ impl LogicalMOp for ShiftRotateMode { - #[track_caller] - fn cmp_value_eq( - lhs: Self, - lhs_value: Cow<'_, Self::SimValue>, - rhs: Self, - rhs_value: Cow<'_, Self::SimValue>, - ) -> bool { - SimValue::opaque(&SimValue::from_value(lhs, lhs_value.into_owned())) - == SimValue::opaque(&SimValue::from_value(rhs, rhs_value.into_owned())) - } - - #[track_caller] - fn cmp_sim_value_eq( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) == SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_sim_value_ne( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) != SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_expr_eq(lhs: Expr, rhs: Expr) -> Expr { - lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits()) - } -} - impl ShiftRotateMode { #[hdl] fn debug_str(this: &SimValue) -> &'static str { @@ -2407,7 +2321,7 @@ impl ShiftRotateDestLogicOp { } /// immediate values for [`ShiftRotateMOp`]. -#[hdl(cmp_eq)] +#[hdl(cmp_eq, custom_debug(sim))] pub struct ShiftRotateMOpImm { /// taken from `src2` if this is [`HdlNone`] pub shift_rotate_amount: HdlOption>, @@ -2416,15 +2330,18 @@ pub struct ShiftRotateMOpImm { pub dest_logic_op: HdlOption, } -impl MOpImmDebug for ShiftRotateMOpImm { +impl SimValueDebug for ShiftRotateMOpImm { #[hdl] - fn mop_imm_debug(this: &SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result { - #[hdl(sim)] - let Self { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + type SimValueT = ::SimValue; + let SimValueT:: { shift_rotate_amount, shift_rotate_right, dest_logic_op, - } = this; + } = value; let shift_op = if **shift_rotate_right { ">>" } else { "<<" }; #[hdl(sim)] match shift_rotate_amount { @@ -2465,7 +2382,7 @@ common_mop_struct! { write!(f, "ShiftRotate {alu_common}, {:?}", ShiftRotateMode::debug_str(mode)) })] #[mapped( ShiftRotateMOp)] - #[hdl(cmp_eq)] + #[hdl(cmp_eq, custom_debug(sim))] pub struct ShiftRotateMOp { #[common] pub alu_common: AluCommonMOp, ShiftRotateMOpImm>, @@ -2505,7 +2422,7 @@ impl ShiftRotateMOp { } } -#[hdl] +#[hdl(cmp_eq)] pub enum CompareMode { U64, S64, @@ -2523,40 +2440,6 @@ pub enum CompareMode { CmpEqB, } -impl HdlPartialEqImpl for CompareMode { - #[track_caller] - fn cmp_value_eq( - lhs: Self, - lhs_value: Cow<'_, Self::SimValue>, - rhs: Self, - rhs_value: Cow<'_, Self::SimValue>, - ) -> bool { - SimValue::opaque(&SimValue::from_value(lhs, lhs_value.into_owned())) - == SimValue::opaque(&SimValue::from_value(rhs, rhs_value.into_owned())) - } - - #[track_caller] - fn cmp_sim_value_eq( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) == SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_sim_value_ne( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) != SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_expr_eq(lhs: Expr, rhs: Expr) -> Expr { - lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits()) - } -} - impl CompareMode { #[hdl] fn debug_str(this: &SimValue) -> &'static str { @@ -2589,7 +2472,7 @@ common_mop_struct! { write!(f, "Compare {common}, {}", CompareMode::debug_str(compare_mode)) })] #[mapped( CompareMOp)] - #[hdl(cmp_eq)] + #[hdl(cmp_eq, custom_debug(sim))] pub struct CompareMOp { #[common] pub common: CommonMOp, DestReg, SrcRegWidth, SrcCount, CommonMOpDefaultImm>, @@ -2652,7 +2535,7 @@ impl CompareMOp for ConditionMode { - #[track_caller] - fn cmp_value_eq( - lhs: Self, - lhs_value: Cow<'_, Self::SimValue>, - rhs: Self, - rhs_value: Cow<'_, Self::SimValue>, - ) -> bool { - SimValue::opaque(&SimValue::from_value(lhs, lhs_value.into_owned())) - == SimValue::opaque(&SimValue::from_value(rhs, rhs_value.into_owned())) - } - - #[track_caller] - fn cmp_sim_value_eq( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) == SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_sim_value_ne( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) != SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_expr_eq(lhs: Expr, rhs: Expr) -> Expr { - lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits()) - } -} - impl ConditionMode { #[hdl] fn debug_str(this: &SimValue, inverted: bool) -> &'static str { @@ -2736,7 +2585,7 @@ common_mop_struct! { maybe_write_comma_flag!(f, is_ret, **is_ret) })] #[mapped( BranchMOp)] - #[hdl(cmp_eq)] + #[hdl(cmp_eq, custom_debug(sim))] /// `src0` is the value used for reading flags from. /// `src1 + imm + if pc_relative { pc } else { 0 }` is the target address. /// `src2` (if present) is the counter to compare against zero. @@ -2892,63 +2741,12 @@ impl BranchMOp for ReadSpecialMOpImm { - #[track_caller] - fn cmp_value_eq( - lhs: Self, - lhs_value: Cow<'_, Self::SimValue>, - rhs: Self, - rhs_value: Cow<'_, Self::SimValue>, - ) -> bool { - SimValue::opaque(&SimValue::from_value(lhs, lhs_value.into_owned())) - == SimValue::opaque(&SimValue::from_value(rhs, rhs_value.into_owned())) - } - - #[track_caller] - fn cmp_sim_value_eq( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) == SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_sim_value_ne( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) != SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_expr_eq(lhs: Expr, rhs: Expr) -> Expr { - lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits()) - } -} - -impl MOpImmDebug for ReadSpecialMOpImm { - fn mop_imm_debug(this: &SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(Self::debug_str(this)) - } -} - -impl ReadSpecialMOpImm { - #[hdl] - fn debug_str(this: &SimValue) -> &'static str { - #[hdl(sim)] - match this { - Self::PowerIsaTimeBase => "PowerIsaTimeBase", - Self::PowerIsaTimeBaseU => "PowerIsaTimeBaseU", - } - } -} - common_mop_struct! { #[debug(#[hdl] |this, f| { #[hdl(sim)] @@ -2959,7 +2757,7 @@ common_mop_struct! { write!(f, "ReadSpecial {common}") })] #[mapped( ReadSpecialMOp)] - #[hdl(cmp_eq)] + #[hdl(cmp_eq, custom_debug(sim))] pub struct ReadSpecialMOp { #[common] pub common: CommonMOp, DestReg, SrcRegWidth, ConstUsize<0>, ReadSpecialMOpImm>, @@ -2993,7 +2791,7 @@ impl ReadSpecialMOp { mop_enum! { #[impl_mop_into = true] - #[hdl] + #[hdl(custom_debug(sim))] pub enum AluBranchMOp { AddSub(AddSubMOp>), AddSubI(AddSubMOp>), @@ -3009,7 +2807,7 @@ mop_enum! { } } -#[hdl] +#[hdl(custom_debug(sim))] pub struct L2RegNum { pub value: UInt<{ MOpRegNum::WIDTH }>, } @@ -3028,14 +2826,14 @@ impl L2RegNum { value: u8::try_from(value).expect("value must fit"), } } - pub fn debug_sim(this: &SimValue) -> impl fmt::Debug { - fmt::from_fn(move |f| write!(f, "l2r{:#x}", Self::value_sim(this))) - } } -impl MOpImmDebug for L2RegNum { - fn mop_imm_debug(this: &SimValue, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&Self::debug_sim(this), f) +impl SimValueDebug for L2RegNum { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + write!(f, "l2r{:#x}", value.value.as_int()) } } @@ -3049,7 +2847,7 @@ common_mop_struct! { write!(f, "ReadL2Reg {common}") })] #[mapped( ReadL2RegMOp)] - #[hdl(cmp_eq)] + #[hdl(cmp_eq, custom_debug(sim))] pub struct ReadL2RegMOp { #[common] pub common: CommonMOp, DestReg, SrcRegWidth, ConstUsize<0>, L2RegNum>, @@ -3091,7 +2889,7 @@ common_mop_struct! { write!(f, "WriteL2Reg {common}") })] #[mapped( WriteL2RegMOp)] - #[hdl(cmp_eq)] + #[hdl(cmp_eq, custom_debug(sim))] pub struct WriteL2RegMOp { #[common] pub common: CommonMOp, DestReg, SrcRegWidth, ConstUsize<1>, L2RegNum>, @@ -3125,7 +2923,7 @@ impl WriteL2RegMOp { mop_enum! { #[impl_mop_into = true] - #[hdl] + #[hdl(custom_debug(sim))] pub enum L2RegisterFileMOp { ReadL2Reg(ReadL2RegMOp), WriteL2Reg(WriteL2RegMOp), @@ -3151,7 +2949,7 @@ where } } -#[hdl] +#[hdl(cmp_eq)] pub enum LoadStoreWidth { Width8Bit, Width16Bit, @@ -3159,81 +2957,13 @@ pub enum LoadStoreWidth { Width64Bit, } -impl HdlPartialEqImpl for LoadStoreWidth { - #[track_caller] - fn cmp_value_eq( - lhs: Self, - lhs_value: Cow<'_, Self::SimValue>, - rhs: Self, - rhs_value: Cow<'_, Self::SimValue>, - ) -> bool { - SimValue::opaque(&SimValue::from_value(lhs, lhs_value.into_owned())) - == SimValue::opaque(&SimValue::from_value(rhs, rhs_value.into_owned())) - } - - #[track_caller] - fn cmp_sim_value_eq( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) == SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_sim_value_ne( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) != SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_expr_eq(lhs: Expr, rhs: Expr) -> Expr { - lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits()) - } -} - -#[hdl] +#[hdl(cmp_eq)] pub enum LoadStoreConversion { ZeroExt, SignExt, // TODO(FP): add Power ISA's f32 in f64 format and RISC-V's ones-extension of floating-point } -impl HdlPartialEqImpl for LoadStoreConversion { - #[track_caller] - fn cmp_value_eq( - lhs: Self, - lhs_value: Cow<'_, Self::SimValue>, - rhs: Self, - rhs_value: Cow<'_, Self::SimValue>, - ) -> bool { - SimValue::opaque(&SimValue::from_value(lhs, lhs_value.into_owned())) - == SimValue::opaque(&SimValue::from_value(rhs, rhs_value.into_owned())) - } - - #[track_caller] - fn cmp_sim_value_eq( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) == SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_sim_value_ne( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::opaque(&lhs) != SimValue::opaque(&rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_expr_eq(lhs: Expr, rhs: Expr) -> Expr { - lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits()) - } -} - common_mop_struct! { #[mapped( LoadStoreCommonMOp)] #[hdl(cmp_eq)] @@ -3309,7 +3039,7 @@ common_mop_struct! { write!(f, "Load {load_store_common}") })] #[mapped( LoadMOp)] - #[hdl(cmp_eq)] + #[hdl(cmp_eq, custom_debug(sim))] pub struct LoadMOp { #[common] pub load_store_common: LoadStoreCommonMOp>, @@ -3357,7 +3087,7 @@ common_mop_struct! { write!(f, "Store {load_store_common}") })] #[mapped( StoreMOp)] - #[hdl(cmp_eq)] + #[hdl(cmp_eq, custom_debug(sim))] /// does `*src0 = convert(src1)` pub struct StoreMOp { #[common] @@ -3398,7 +3128,7 @@ impl StoreMOp { mop_enum! { #[impl_mop_into = true] - #[hdl] + #[hdl(custom_debug(sim))] pub enum LoadStoreMOp { Load(LoadMOp), Store(StoreMOp), @@ -3415,7 +3145,7 @@ common_mop_struct! { write!(f, "MoveReg {common}") })] #[mapped( MoveRegMOp)] - #[hdl(cmp_eq)] + #[hdl(cmp_eq, custom_debug(sim))] pub struct MoveRegMOp { #[common] pub common: CommonMOp, DestReg, SrcRegWidth, ConstUsize<1>, CommonMOpDefaultImm>>, @@ -3465,7 +3195,7 @@ impl MoveRegMOp { } } -#[hdl(cmp_eq, no_static)] +#[hdl(cmp_eq, no_static, custom_debug(sim))] /// there may be more than one unit of a given kind, so UnitNum is not the same as UnitKind. /// zero is used for built-in constants, such as the zero register pub struct UnitNum> { @@ -3473,6 +3203,30 @@ pub struct UnitNum> { pub config: C, } +impl> SimValueDebug for UnitNum { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + if let Some(index) = Self::index_sim(value) { + write!(f, "u{index}") + } else { + f.write_str("uz") + } + } +} + +impl> UnitNum { + pub fn index_sim(expr: &::SimValue) -> Option { + let adj_value = expr.adj_value.cast_to_static::>().as_int(); + if adj_value == 0 { + None + } else { + Some(adj_value as usize - 1) + } + } +} + impl UnitNum { pub fn const_zero(self) -> Expr { self.const_zero_sim().to_expr() @@ -3500,14 +3254,6 @@ impl UnitNum { let expr = expr.to_expr(); expr.ty().from_index(index).adj_value.cmp_eq(expr.adj_value) } - pub fn index_sim(expr: &SimValue) -> Option { - let adj_value = expr.adj_value.cast_to_static::>().as_int(); - if adj_value == 0 { - None - } else { - Some(adj_value as usize - 1) - } - } #[hdl] pub fn as_index( expr: impl ToExpr, @@ -3525,25 +3271,32 @@ impl UnitNum { } unit_index } - pub fn debug_sim(this: &SimValue) -> impl fmt::Debug { - fmt::from_fn(move |f| { - if let Some(index) = Self::index_sim(this) { - write!(f, "u{index}") - } else { - f.write_str("uz") - } - }) - } } pub const CONST_ZERO_UNIT_NUM: usize = 0; -#[hdl(cmp_eq, no_static)] +#[hdl(cmp_eq, no_static, custom_debug(sim))] pub struct UnitOutRegNum> { pub value: UIntType>, pub config: C, } +impl> SimValueDebug for UnitOutRegNum { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + let value = Self::value_sim(value); + write!(f, "or{value:#x}") + } +} + +impl> UnitOutRegNum { + pub fn value_sim(this: &::SimValue) -> usize { + this.value.cast_to_static::>().as_int() as usize + } +} + impl UnitOutRegNum { #[hdl] pub fn new_sim(self, value: usize) -> SimValue { @@ -3553,16 +3306,9 @@ impl UnitOutRegNum { config: self.config, } } - pub fn value_sim(this: &SimValue) -> usize { - this.value.cast_to_static::>().as_int() as usize - } - pub fn debug_sim(this: &SimValue) -> impl fmt::Debug { - let value = Self::value_sim(this); - fmt::from_fn(move |f| write!(f, "or{value:#x}")) - } } -#[hdl(cmp_eq, no_static)] +#[hdl(cmp_eq, no_static, custom_debug(sim))] /// Physical Register Number -- registers in the CPU's backend pub struct PRegNum> { pub unit_num: UnitNum, @@ -3582,27 +3328,20 @@ impl PRegNum { }, } } - #[hdl] - pub fn debug_sim(this: &SimValue) -> impl fmt::Debug { - fmt::from_fn(move |f| { - #[hdl(sim)] - let Self { - unit_num, - unit_out_reg, - } = this; - if let (None, 0) = ( - UnitNum::index_sim(unit_num), - UnitOutRegNum::value_sim(unit_out_reg), - ) { - return f.write_str("pzero"); - } - write!( - f, - "p{:?}_{:?}", - UnitNum::debug_sim(unit_num), - UnitOutRegNum::debug_sim(unit_out_reg), - ) - }) +} + +impl> SimValueDebug for PRegNum { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + if let (None, 0) = ( + UnitNum::index_sim(&value.unit_num), + UnitOutRegNum::value_sim(&value.unit_out_reg), + ) { + return f.write_str("pzero"); + } + write!(f, "p{:?}_{:?}", &value.unit_num, &value.unit_out_reg) } } @@ -3644,7 +3383,7 @@ impl MOpRegNum { Self::CONST_ZERO_REG_NUM + 1..Self::SPECIAL_REG_NUMS.start; } -#[hdl(cmp_eq)] +#[hdl(cmp_eq, custom_debug(sim))] /// all the registers this instruction will write to, they are all renamed to the same physical register. pub struct MOpDestReg { /// some instructions have multiple destination registers, e.g. x86 div @@ -3656,6 +3395,33 @@ pub struct MOpDestReg { pub flag_regs: Array, { range_u32_len(&MOpRegNum::FLAG_REG_NUMS) }>, } +impl SimValueDebug for MOpDestReg { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + if f.alternate() { + type SimValueT = ::SimValue; + let SimValueT:: { + normal_regs, + flag_regs, + } = value; + f.debug_struct("MOpDestReg") + .field("normal_regs", normal_regs) + .field("flag_regs", flag_regs) + .finish() + } else { + f.debug_set() + .entries( + Self::regs_sim(value) + .into_iter() + .filter(|&v| v != MOpRegNum::CONST_ZERO_REG_NUM), + ) + .finish() + } + } +} + impl MOpDestReg { #[hdl] #[track_caller] @@ -3890,8 +3656,7 @@ impl MOpDestReg { }) } #[hdl] - pub fn regs_sim(this: &SimValue) -> [u32; Self::REG_COUNT] { - let this = this.into_sim_value(); + pub fn regs_sim(this: &::SimValue) -> [u32; Self::REG_COUNT] { std::array::from_fn(|index| match Self::REG_KINDS[index] { MOpDestRegKind::NormalReg { dest_reg_index } => this.normal_regs[dest_reg_index] .value diff --git a/crates/cpu/src/next_pc.rs b/crates/cpu/src/next_pc.rs index fcc5286..7a0d063 100644 --- a/crates/cpu/src/next_pc.rs +++ b/crates/cpu/src/next_pc.rs @@ -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> { 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 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>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - let clear_unused_bits = |v: Cow<'_, SimValue>| { - #[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>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - !Self::cmp_sim_value_eq(lhs, rhs) - } - - #[track_caller] - fn cmp_expr_eq(lhs: Expr, rhs: Expr) -> Expr { - 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 SimValueDefault for ArrayType { } impl SimValueDefault for HdlOption { + #[hdl] fn sim_value_default(self) -> SimValue { - 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 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>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::bits(&*lhs) == SimValue::bits(&*rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_sim_value_ne( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::bits(&*lhs) != SimValue::bits(&*rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_expr_eq(lhs: Expr, rhs: Expr) -> Expr { - lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits()) - } -} - impl BTBEntryInsnKind { #[hdl] fn try_from_decoded_insn_kind(kind: &SimValue) -> Option> { @@ -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 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>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::bits(&*lhs) == SimValue::bits(&*rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_sim_value_ne( - lhs: Cow<'_, SimValue>, - rhs: Cow<'_, SimValue>, - ) -> SimValue { - (SimValue::bits(&*lhs) != SimValue::bits(&*rhs)).to_sim_value() - } - - #[track_caller] - fn cmp_expr_eq(lhs: Expr, rhs: Expr) -> Expr { - lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits()) - } -} - impl BTBEntryAddrKind { #[hdl] fn taken(this: &SimValue) -> bool { diff --git a/crates/cpu/src/rename_execute_retire.rs b/crates/cpu/src/rename_execute_retire.rs index 602d113..fe7b7db 100644 --- a/crates/cpu/src/rename_execute_retire.rs +++ b/crates/cpu/src/rename_execute_retire.rs @@ -10,8 +10,8 @@ use crate::{ CpuConfigRobSize, CpuConfigUnitCount, PhantomConstCpuConfig, TwiceCpuConfigFetchWidth, }, instruction::{ - COMMON_MOP_SRC_LEN, L2RegNum, L2RegisterFileMOp, MOp, MOpDebug, MOpDestReg, MOpRegNum, - MOpTrait, PRegNum, ReadL2RegMOp, UnitNum, UnitOutRegNum, + COMMON_MOP_SRC_LEN, L2RegNum, L2RegisterFileMOp, MOp, MOpDestReg, MOpRegNum, MOpTrait, + PRegNum, ReadL2RegMOp, UnitNum, UnitOutRegNum, }, next_pc::{CallStackOp, SimValueDefault}, register::PRegValue, @@ -22,7 +22,7 @@ use crate::{ use fayalite::{ int::UIntInRangeInclusiveType, prelude::*, - ty::{OpaqueSimValue, StaticType}, + ty::{OpaqueSimValue, SimValueDebug, StaticType}, util::ready_valid::ReadyValid, }; use std::{collections::VecDeque, fmt, mem, num::NonZero}; @@ -33,7 +33,7 @@ pub const MOP_ID_WIDTH: usize = 16; #[hdl] pub type MOpId = UInt<{ MOP_ID_WIDTH }>; -#[hdl] +#[hdl(custom_debug(sim))] /// A µOp along with the state needed for this instance of the µOp. pub struct MOpInstance { pub fetch_block_id: UInt<8>, @@ -50,6 +50,29 @@ pub struct MOpInstance { pub mop: MOp, } +impl SimValueDebug for MOpInstance { + #[hdl] + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + #[hdl(sim)] + let Self { + fetch_block_id, + id, + pc, + predicted_next_pc, + size_in_bytes, + is_first_mop_in_insn, + mop, + } = value; + write!( + f, + "fid={fetch_block_id:?} id={id:?} pc={pc:?} pn_pc={predicted_next_pc:?} sz={size_in_bytes:?} first={is_first_mop_in_insn}: {mop:?}" + ) + } +} + #[hdl(no_static)] /// TODO: merge with [`crate::next_pc::PostDecodeOutputInterface`] pub struct PostDecodeOutputInterface> { @@ -233,16 +256,6 @@ impl RenameTableEntry { #[hdl(sim)] self.L1(self.L1.const_zero()) } - #[hdl] - fn debug_sim(this: &SimValue) -> impl fmt::Debug { - fmt::from_fn(move |f| { - #[hdl(sim)] - match this { - Self::L1(v) => write!(f, "L1({:?})", PRegNum::debug_sim(v)), - Self::L2(v) => write!(f, "L2({:?})", L2RegNum::debug_sim(v)), - } - }) - } } /// make arrays dynamically-sized to avoid putting large types on the stack @@ -320,10 +333,7 @@ impl RenameTable { // writing to const zero reg does nothing return; } - println!( - "{rename_table_name}: Write: {unrenamed_reg_num:#x} <- {:?}", - RenameTableEntry::debug_sim(new), - ); + println!("{rename_table_name}: Write: {unrenamed_reg_num:#x} <- {new:?}"); self.entries[*unrenamed_reg_num as usize] = new.clone(); } RenameTableUpdate::UpdateForReadL2Reg { dest, src } => { @@ -336,9 +346,8 @@ impl RenameTable { RenameTableEntry::<_>::L2(l2) => { if L2RegNum::value_sim(l2) == L2RegNum::value_sim(src) { println!( - "{rename_table_name}: UpdateForReadL2Reg: {unrenamed_reg_num:#x} updating from {:?} to {:?}", - RenameTableEntry::debug_sim(&entry), - RenameTableEntry::debug_sim(&new), + "{rename_table_name}: UpdateForReadL2Reg: {unrenamed_reg_num:#x} \ + updating from {entry:?} to {new:?}", ); *entry = new.clone(); } @@ -355,9 +364,8 @@ impl RenameTable { RenameTableEntry::<_>::L1(l1) => { if l1 == src { println!( - "{rename_table_name}: UpdateForWriteL2Reg: {unrenamed_reg_num:#x} updating from {:?} to {:?}", - RenameTableEntry::debug_sim(&entry), - RenameTableEntry::debug_sim(&new), + "{rename_table_name}: UpdateForWriteL2Reg: {unrenamed_reg_num:#x} \ + updating from {entry:?} to {new:?}", ); *entry = new.clone(); } @@ -635,20 +643,8 @@ impl RobEntry { mop, mop_in_unit_state: SimOnlyValue::new(*mop_in_unit_state), is_speculative, - finished: if let Some(finished) = finished { - #[hdl(sim)] - (ret_ty.finished).HdlSome(finished) - } else { - #[hdl(sim)] - (ret_ty.finished).HdlNone() - }, - caused_cancel: if let Some(caused_cancel) = caused_cancel { - #[hdl(sim)] - (ret_ty.caused_cancel).HdlSome(caused_cancel) - } else { - #[hdl(sim)] - (ret_ty.caused_cancel).HdlNone() - }, + finished: finished.into_sim_value_with_type(ret_ty.finished), + caused_cancel: caused_cancel.into_sim_value_with_type(ret_ty.caused_cancel), } } } @@ -813,13 +809,7 @@ impl ReorderBuffer { entries.iter().map(RobEntries::debug_state), ) .expect("known to fit"), - incomplete_back_entry: if let Some(incomplete_back_entry) = incomplete_back_entry { - #[hdl(sim)] - HdlSome(incomplete_back_entry.debug_state()) - } else { - #[hdl(sim)] - HdlNone() - }, + incomplete_back_entry: incomplete_back_entry.as_ref().map(|v| v.debug_state()), renamed: ty .renamed .from_iter_sim( @@ -1036,15 +1026,15 @@ impl RenameExecuteRetireState { } write!( f, - ": {:#x}{}: ", + ": {:#x}{}: {:?}", rob.mop.pc.as_int(), if *rob.mop.is_first_mop_in_insn { "" } else { ".." }, - )?; - MOpDebug::mop_debug(&rob.mop.mop, f) + rob.mop.mop, + ) }) .to_string(); // TODO @@ -1085,18 +1075,7 @@ impl RenameExecuteRetireState { l1_reg_file: SimValue::from_array_elements( state_for_debug.ty().l1_reg_file, l1_reg_file.iter().map(|v| { - SimValue::from_array_elements( - state_for_debug.ty().l1_reg_file.element(), - v.iter().map(|v| { - if let Some(v) = v { - #[hdl(sim)] - HdlSome(v) - } else { - #[hdl(sim)] - HdlNone() - } - }), - ) + SimValue::from_array_elements(state_for_debug.ty().l1_reg_file.element(), v) }), ), per_insn_timeline: self.per_insn_timeline(), @@ -1249,10 +1228,7 @@ impl RenameExecuteRetireState { }); let [src_reg] = src_regs; let renamed_reg = self.rename_table.entries[src_reg as usize].clone(); - println!( - "moving from {src_reg:#x} renamed: {:?}", - RenameTableEntry::debug_sim(&renamed_reg), - ); + println!("moving from {src_reg:#x} renamed: {renamed_reg:?}"); let unrenamed_dest_regs = MOpDestReg::regs_sim(MOpTrait::dest_reg_sim_ref(move_reg_mop)); assert!(self.rob.incomplete_back_entry.is_none()); @@ -1350,10 +1326,7 @@ impl RenameExecuteRetireState { CpuConfigPRegNumWidth[self.config], &mut |src_reg, index| { let renamed = &self.rename_table.entries[src_reg.as_int() as usize]; - println!( - "renaming src[{index}] from {src_reg:?} to {:?}", - RenameTableEntry::debug_sim(renamed), - ); + println!("renaming src[{index}] from {src_reg:?} to {renamed:?}"); #[hdl(sim)] match renamed { RenameTableEntry::<_>::L1(v) => v.cast_to_bits(), diff --git a/crates/cpu/src/rename_execute_retire/to_unit_interfaces.rs b/crates/cpu/src/rename_execute_retire/to_unit_interfaces.rs index 2709083..d3ec39a 100644 --- a/crates/cpu/src/rename_execute_retire/to_unit_interfaces.rs +++ b/crates/cpu/src/rename_execute_retire/to_unit_interfaces.rs @@ -7,7 +7,10 @@ use fayalite::{ expr::ops::FieldAccess, intern::{Intern, Interned, Memoize}, prelude::*, - ty::{OpaqueSimValue, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten}, + ty::{ + OpaqueSimValue, OpaqueSimValueSlice, OpaqueSimValueWriter, OpaqueSimValueWritten, + SimValueDebug, + }, }; use std::{fmt, marker::PhantomData, ops::Index}; @@ -116,6 +119,15 @@ impl> Index for ExecuteToUnitInterfacesW } } +impl> SimValueDebug for ExecuteToUnitInterfaces { + fn sim_value_debug( + value: &::SimValue, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(value, f) + } +} + impl> Type for ExecuteToUnitInterfaces { type BaseType = Bundle; type MaskType = Bundle; diff --git a/crates/cpu/src/unit.rs b/crates/cpu/src/unit.rs index e249b38..79f03bf 100644 --- a/crates/cpu/src/unit.rs +++ b/crates/cpu/src/unit.rs @@ -26,7 +26,7 @@ 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> { $( @@ -82,9 +82,8 @@ macro_rules! all_units { } mop_enum! { - #[debug(where $TransformedMoveOp: crate::instruction::MOpDebug)] #[impl_mop_into = false] - #[hdl] + #[hdl(custom_debug(sim))] $(#[$enum_meta])* $vis enum $UnitMOpEnum< $DestReg: Type, @@ -322,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, diff --git a/crates/cpu/tests/next_pc.rs b/crates/cpu/tests/next_pc.rs index e17a8bd..2046a26 100644 --- a/crates/cpu/tests/next_pc.rs +++ b/crates/cpu/tests/next_pc.rs @@ -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, }, ) diff --git a/crates/cpu/tests/rename_execute_retire.rs b/crates/cpu/tests/rename_execute_retire.rs index fb4b14b..3a02f22 100644 --- a/crates/cpu/tests/rename_execute_retire.rs +++ b/crates/cpu/tests/rename_execute_retire.rs @@ -9,8 +9,8 @@ use cpu::{ instruction::{ AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp, CompareMOp, CompareMode, ConditionMode, L2RegisterFileMOp, LoadMOp, LoadStoreCommonMOp, - LoadStoreConversion, LoadStoreMOp, LoadStoreWidth, MOp, MOpDebug, MOpDestReg, MOpRegNum, - MOpTrait, MoveRegMOp, OutputIntegerMode, PRegNum, StoreMOp, UnitNum, + LoadStoreConversion, LoadStoreMOp, LoadStoreWidth, MOp, MOpDestReg, MOpRegNum, MOpTrait, + MoveRegMOp, OutputIntegerMode, PRegNum, StoreMOp, UnitNum, }, next_pc::CallStackOp, register::{PRegFlags, PRegFlagsPowerISA, PRegValue}, @@ -1817,20 +1817,8 @@ impl MockUnitOp { mop, src_values, sent_cant_cause_cancel, - output_ready: if let Some(output_ready) = output_ready { - #[hdl(sim)] - output_ready_ty.HdlSome(output_ready) - } else { - #[hdl(sim)] - output_ready_ty.HdlNone() - }, - caused_cancel: if let Some(caused_cancel) = caused_cancel { - #[hdl(sim)] - caused_cancel_ty.HdlSome(caused_cancel) - } else { - #[hdl(sim)] - caused_cancel_ty.HdlNone() - }, + output_ready: output_ready.into_sim_value_with_type(output_ready_ty), + caused_cancel: caused_cancel.into_sim_value_with_type(caused_cancel_ty), config, } } @@ -1842,11 +1830,7 @@ impl MockUnitOp { let (output, caused_cancel) = execution_state.run_mop(&self.mop, &self.src_values, self.config); assert!(output.is_some() || caused_cancel.is_some()); - println!( - "try_run: {:#x}: {}", - self.mop.pc.as_int(), - fmt::from_fn(|f| MOpDebug::mop_debug(&self.mop.mop, f)), - ); + println!("try_run: {:#x}: {:?}", self.mop.pc.as_int(), self.mop.mop); println!( "<- {:?}", self.src_values @@ -1985,20 +1969,8 @@ impl MockUnitState { if op.output_ready.is_none() && op.caused_cancel.is_none() { continue; } - let output_ready = if let Some(output_ready) = &op.output_ready { - #[hdl(sim)] - output_ready_ty.HdlSome(output_ready) - } else { - #[hdl(sim)] - output_ready_ty.HdlNone() - }; - let caused_cancel = if let Some(caused_cancel) = &op.caused_cancel { - #[hdl(sim)] - caused_cancel_ty.HdlSome(caused_cancel) - } else { - #[hdl(sim)] - caused_cancel_ty.HdlNone() - }; + let output_ready = op.output_ready.to_sim_value_with_type(output_ready_ty); + let caused_cancel = op.caused_cancel.to_sim_value_with_type(caused_cancel_ty); // TODO: add delay return ( output_ready, @@ -2301,20 +2273,8 @@ impl MockLoadStoreOp { MockLoadStoreOpDebugState::<_> { mop, is_speculative, - src_values: if let Some(v) = src_values { - #[hdl(sim)] - HdlSome(v) - } else { - #[hdl(sim)] - HdlNone() - }, - dest_value: if let Some(v) = dest_value { - #[hdl(sim)] - HdlSome(v) - } else { - #[hdl(sim)] - HdlNone() - }, + src_values, + dest_value, ran_nonspeculatively, sent_cant_cause_cancel, sent_output_ready, diff --git a/crates/cpu/tests/simple_power_isa_decoder/main.rs b/crates/cpu/tests/simple_power_isa_decoder/main.rs index 9fa5d3c..a345f44 100644 --- a/crates/cpu/tests/simple_power_isa_decoder/main.rs +++ b/crates/cpu/tests/simple_power_isa_decoder/main.rs @@ -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); diff --git a/crates/cpu/tests/simple_power_isa_decoder/test_cases/fixed_point_rotate_and_shift.rs b/crates/cpu/tests/simple_power_isa_decoder/test_cases/fixed_point_rotate_and_shift.rs index 29f84b4..6195154 100644 --- a/crates/cpu/tests/simple_power_isa_decoder/test_cases/fixed_point_rotate_and_shift.rs +++ b/crates/cpu/tests/simple_power_isa_decoder/test_cases/fixed_point_rotate_and_shift.rs @@ -30,13 +30,7 @@ fn rotate_imm( ) -> SimValue { #[hdl(sim)] ShiftRotateMOpImm { - shift_rotate_amount: if let Some(amount) = amount { - #[hdl(sim)] - HdlSome(amount.cast_to_static::>()) - } else { - #[hdl(sim)] - HdlNone() - }, + shift_rotate_amount: amount.map(|amount| amount.cast_to_static::>()), shift_rotate_right: false, dest_logic_op: if let Some((rotated_output_start, rotated_output_len)) = rotated_output_start_and_len