change CommonMOp to directly contain a generic immediate type
This commit is contained in:
parent
167bc4b6a6
commit
130c1b2892
4 changed files with 145693 additions and 156456 deletions
|
|
@ -11,7 +11,7 @@ use fayalite::{
|
|||
intern::Interned,
|
||||
module::wire_with_loc,
|
||||
prelude::*,
|
||||
ty::StaticType,
|
||||
ty::{StaticType, TypeProperties},
|
||||
util::ConstBool,
|
||||
};
|
||||
use std::{
|
||||
|
|
@ -130,28 +130,42 @@ pub trait MOpTrait: Type {
|
|||
pub trait CommonMOpTrait: MOpTrait {
|
||||
type PrefixPad: KnownSize;
|
||||
type SrcCount: KnownSize;
|
||||
type Imm: Type;
|
||||
type CommonMOpTraitMapped<NewDestReg: Type, NewSrcRegWidth: Size>: CommonMOpTrait<
|
||||
DestReg = NewDestReg,
|
||||
SrcRegWidth = NewSrcRegWidth,
|
||||
PrefixPad = Self::PrefixPad,
|
||||
SrcCount = Self::SrcCount,
|
||||
Imm = Self::Imm,
|
||||
>;
|
||||
type CommonMOpTraitDestReg: Type;
|
||||
type CommonMOpTraitSrcRegWidth: Size;
|
||||
fn common_mop_ty(
|
||||
self,
|
||||
) -> CommonMOp<Self::PrefixPad, Self::DestReg, Self::SrcRegWidth, Self::SrcCount>;
|
||||
) -> CommonMOp<Self::PrefixPad, Self::DestReg, Self::SrcRegWidth, Self::SrcCount, Self::Imm>;
|
||||
fn common_mop(
|
||||
input: impl ToExpr<Type = Self>,
|
||||
) -> Expr<CommonMOp<Self::PrefixPad, Self::DestReg, Self::SrcRegWidth, Self::SrcCount>>;
|
||||
) -> Expr<CommonMOp<Self::PrefixPad, Self::DestReg, Self::SrcRegWidth, Self::SrcCount, Self::Imm>>;
|
||||
fn with_common_mop_ty<NewDestReg: Type, NewSrcRegWidth: Size>(
|
||||
self,
|
||||
new_common_mop_ty: CommonMOp<Self::PrefixPad, NewDestReg, NewSrcRegWidth, Self::SrcCount>,
|
||||
new_common_mop_ty: CommonMOp<
|
||||
Self::PrefixPad,
|
||||
NewDestReg,
|
||||
NewSrcRegWidth,
|
||||
Self::SrcCount,
|
||||
Self::Imm,
|
||||
>,
|
||||
) -> Self::Mapped<NewDestReg, NewSrcRegWidth>;
|
||||
fn with_common_mop<NewDestReg: Type, NewSrcRegWidth: Size>(
|
||||
input: impl ToExpr<Type = Self>,
|
||||
new_common_mop: impl ToExpr<
|
||||
Type = CommonMOp<Self::PrefixPad, NewDestReg, NewSrcRegWidth, Self::SrcCount>,
|
||||
Type = CommonMOp<
|
||||
Self::PrefixPad,
|
||||
NewDestReg,
|
||||
NewSrcRegWidth,
|
||||
Self::SrcCount,
|
||||
Self::Imm,
|
||||
>,
|
||||
>,
|
||||
) -> Expr<Self::Mapped<NewDestReg, NewSrcRegWidth>>;
|
||||
}
|
||||
|
|
@ -161,6 +175,7 @@ pub type CommonMOpFor<T> = CommonMOp<
|
|||
<T as CommonMOpTrait>::CommonMOpTraitDestReg,
|
||||
<T as CommonMOpTrait>::CommonMOpTraitSrcRegWidth,
|
||||
<T as CommonMOpTrait>::SrcCount,
|
||||
<T as CommonMOpTrait>::Imm,
|
||||
>;
|
||||
|
||||
impl<T: CommonMOpTrait> MOpTrait for T {
|
||||
|
|
@ -192,10 +207,15 @@ impl<T: CommonMOpTrait> MOpTrait for T {
|
|||
new_dest_reg: NewDestReg,
|
||||
new_src_reg_width: NewSrcRegWidth::SizeType,
|
||||
) -> Self::Mapped<NewDestReg, NewSrcRegWidth> {
|
||||
self.with_common_mop_ty(
|
||||
CommonMOp[T::PrefixPad::SIZE][new_dest_reg][new_src_reg_width][T::SrcCount::SIZE],
|
||||
)
|
||||
let common_mop_ty = self.common_mop_ty();
|
||||
self.with_common_mop_ty(CommonMOp {
|
||||
prefix_pad: common_mop_ty.prefix_pad,
|
||||
dest: new_dest_reg,
|
||||
src: ArrayType[UIntType[new_src_reg_width]][T::SrcCount::SIZE],
|
||||
imm: common_mop_ty.imm,
|
||||
})
|
||||
}
|
||||
#[hdl]
|
||||
fn map_regs<NewDestReg: Type, NewSrcRegWidth: Size>(
|
||||
input: impl ToExpr<Type = Self>,
|
||||
new_dest: impl ToExpr<Type = NewDestReg>,
|
||||
|
|
@ -207,22 +227,21 @@ impl<T: CommonMOpTrait> MOpTrait for T {
|
|||
) -> Expr<Self::Mapped<NewDestReg, NewSrcRegWidth>> {
|
||||
let input = input.to_expr();
|
||||
let common = T::common_mop(input);
|
||||
let new_dest = new_dest.to_expr();
|
||||
T::with_common_mop(
|
||||
input,
|
||||
CommonMOp::new(
|
||||
common.prefix_pad,
|
||||
new_dest,
|
||||
ArrayLiteral::new(
|
||||
#[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: common.prefix_pad,
|
||||
dest: new_dest,
|
||||
src: ArrayLiteral::new(
|
||||
UIntType[new_src_reg_width],
|
||||
Interned::from_iter(
|
||||
(0..T::SrcCount::VALUE)
|
||||
.map(|index| Expr::canonical(map_src(common.src[index], index))),
|
||||
),
|
||||
)
|
||||
.to_expr(),
|
||||
CommonMOp::imm(common),
|
||||
),
|
||||
),
|
||||
imm: common.imm,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -288,173 +307,269 @@ pub const MOP_IMM_WIDTH: usize = 34;
|
|||
pub const MOP_MIN_REG_WIDTH: usize = 8;
|
||||
pub const COMMON_MOP_SRC_LEN: usize = 3;
|
||||
pub const COMMON_MOP_MIN_SRC_LEN_WITH_FULL_IMM: usize = 2;
|
||||
pub const COMMON_MOP_IMM_LOW_WIDTH: usize = CommonMOpWithMaxSrcCount::IMM_WIDTH - 1;
|
||||
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct CommonMOp<PrefixPad: KnownSize, DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||
pub prefix_pad: UIntType<PrefixPad>,
|
||||
pub dest: DestReg,
|
||||
pub src: Array<UIntType<SrcRegWidth>, { COMMON_MOP_SRC_LEN }>,
|
||||
pub imm_low: UInt<{ COMMON_MOP_IMM_LOW_WIDTH }>,
|
||||
pub imm_sign: SInt<1>,
|
||||
pub _phantom: PhantomData<SrcCount>,
|
||||
pub const fn common_mop_max_imm_size(src_count: usize) -> usize {
|
||||
assert!(src_count <= COMMON_MOP_SRC_LEN, "too many sources");
|
||||
assert!(COMMON_MOP_MIN_SRC_LEN_WITH_FULL_IMM <= COMMON_MOP_SRC_LEN);
|
||||
let sources_that_reduce_imm = src_count.saturating_sub(COMMON_MOP_MIN_SRC_LEN_WITH_FULL_IMM);
|
||||
MOP_IMM_WIDTH - sources_that_reduce_imm * MOP_MIN_REG_WIDTH
|
||||
}
|
||||
|
||||
impl<PrefixPad: KnownSize, DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> CommonMOpTrait
|
||||
for CommonMOp<PrefixPad, DestReg, SrcRegWidth, SrcCount>
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Default)]
|
||||
pub struct CommonMOpDefaultImm<SrcCount: KnownSize> {
|
||||
_phantom: PhantomData<SrcCount>,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct CommonMOpDefaultImmNoGenerics(());
|
||||
|
||||
#[expect(non_upper_case_globals)]
|
||||
pub const CommonMOpDefaultImm: CommonMOpDefaultImmNoGenerics = CommonMOpDefaultImmNoGenerics(());
|
||||
|
||||
impl<SrcCount: fayalite::int::SizeType<Size: KnownSize>> std::ops::Index<SrcCount>
|
||||
for CommonMOpDefaultImmNoGenerics
|
||||
{
|
||||
type Output = CommonMOpDefaultImm<SrcCount::Size>;
|
||||
|
||||
fn index(&self, _src_count: SrcCount) -> &Self::Output {
|
||||
const {
|
||||
// check generics for validity
|
||||
let _ = Self::Output::UNDERLYING_TYPE;
|
||||
&CommonMOpDefaultImm {
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<SrcCount: KnownSize> fmt::Debug for CommonMOpDefaultImm<SrcCount> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"CommonMOpDefaultImm<ConstUsize<{}>>({:?})",
|
||||
SrcCount::VALUE,
|
||||
Self::UNDERLYING_TYPE
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<SrcCount: KnownSize> CommonMOpDefaultImm<SrcCount> {
|
||||
pub const UNDERLYING_TYPE: SInt = SInt::new_dyn(common_mop_max_imm_size(SrcCount::VALUE));
|
||||
pub fn as_sint<S: Size>(this: impl ToExpr<Type = Self>) -> Expr<SIntType<S>> {
|
||||
Expr::from_canonical(Expr::canonical(this.to_expr()))
|
||||
}
|
||||
pub fn as_sint_dyn(this: impl ToExpr<Type = Self>) -> Expr<SInt> {
|
||||
Expr::from_canonical(Expr::canonical(this.to_expr()))
|
||||
}
|
||||
pub fn from_sint<S: Size>(v: impl ToExpr<Type = SIntType<S>>) -> Expr<Self> {
|
||||
Expr::from_canonical(Expr::canonical(v.to_expr()))
|
||||
}
|
||||
pub fn cast_from_sint<S: Size>(v: impl ToExpr<Type = SIntType<S>>) -> Expr<Self> {
|
||||
Expr::from_canonical(Expr::canonical(v.to_expr().cast_to(Self::UNDERLYING_TYPE)))
|
||||
}
|
||||
pub fn zero(self) -> SimValue<Self> {
|
||||
SimValue::from_value(self, Self::UNDERLYING_TYPE.zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<SrcCount: KnownSize> ToSimValueWithType<CommonMOpDefaultImm<SrcCount>> for SIntValue {
|
||||
fn to_sim_value_with_type(
|
||||
&self,
|
||||
ty: CommonMOpDefaultImm<SrcCount>,
|
||||
) -> SimValue<CommonMOpDefaultImm<SrcCount>> {
|
||||
SimValue::from_value(ty, self.clone())
|
||||
}
|
||||
fn into_sim_value_with_type(
|
||||
self,
|
||||
ty: CommonMOpDefaultImm<SrcCount>,
|
||||
) -> SimValue<CommonMOpDefaultImm<SrcCount>> {
|
||||
SimValue::from_value(ty, self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<SrcCount: KnownSize> Type for CommonMOpDefaultImm<SrcCount> {
|
||||
type BaseType = SInt;
|
||||
type MaskType = <Self::BaseType as Type>::MaskType;
|
||||
type SimValue = <Self::BaseType as Type>::SimValue;
|
||||
type MatchVariant = <Self::BaseType as Type>::MatchVariant;
|
||||
type MatchActiveScope = <Self::BaseType as Type>::MatchActiveScope;
|
||||
type MatchVariantAndInactiveScope = <Self::BaseType as Type>::MatchVariantAndInactiveScope;
|
||||
type MatchVariantsIter = <Self::BaseType as Type>::MatchVariantsIter;
|
||||
|
||||
fn match_variants(
|
||||
this: Expr<Self>,
|
||||
source_location: SourceLocation,
|
||||
) -> Self::MatchVariantsIter {
|
||||
Self::BaseType::match_variants(Expr::from_canonical(Expr::canonical(this)), source_location)
|
||||
}
|
||||
|
||||
fn mask_type(&self) -> Self::MaskType {
|
||||
Self::UNDERLYING_TYPE.mask_type()
|
||||
}
|
||||
|
||||
fn canonical(&self) -> CanonicalType {
|
||||
Self::UNDERLYING_TYPE.canonical()
|
||||
}
|
||||
|
||||
fn from_canonical(canonical_type: CanonicalType) -> Self {
|
||||
let underlying_type = Self::BaseType::from_canonical(canonical_type);
|
||||
assert_eq!(underlying_type, Self::UNDERLYING_TYPE);
|
||||
Self {
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn source_location() -> SourceLocation {
|
||||
SourceLocation::caller()
|
||||
}
|
||||
|
||||
fn sim_value_from_opaque(
|
||||
&self,
|
||||
opaque: fayalite::ty::OpaqueSimValueSlice<'_>,
|
||||
) -> Self::SimValue {
|
||||
Self::UNDERLYING_TYPE.sim_value_from_opaque(opaque)
|
||||
}
|
||||
|
||||
fn sim_value_clone_from_opaque(
|
||||
&self,
|
||||
value: &mut Self::SimValue,
|
||||
opaque: fayalite::ty::OpaqueSimValueSlice<'_>,
|
||||
) {
|
||||
Self::UNDERLYING_TYPE.sim_value_clone_from_opaque(value, opaque)
|
||||
}
|
||||
|
||||
fn sim_value_to_opaque<'w>(
|
||||
&self,
|
||||
value: &Self::SimValue,
|
||||
writer: fayalite::ty::OpaqueSimValueWriter<'w>,
|
||||
) -> fayalite::ty::OpaqueSimValueWritten<'w> {
|
||||
Self::UNDERLYING_TYPE.sim_value_to_opaque(value, writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<SrcCount: KnownSize> StaticType for CommonMOpDefaultImm<SrcCount> {
|
||||
const TYPE: Self = Self {
|
||||
_phantom: PhantomData,
|
||||
};
|
||||
const MASK_TYPE: Self::MaskType = Self::MaskType::TYPE;
|
||||
const TYPE_PROPERTIES: TypeProperties = Self::UNDERLYING_TYPE.type_properties_dyn();
|
||||
const MASK_TYPE_PROPERTIES: TypeProperties = Self::MaskType::TYPE_PROPERTIES;
|
||||
}
|
||||
|
||||
impl<SrcCount: KnownSize> HdlPartialEqImpl<Self> for CommonMOpDefaultImm<SrcCount> {
|
||||
#[track_caller]
|
||||
fn cmp_value_eq(
|
||||
_lhs: Self,
|
||||
lhs_value: Cow<'_, Self::SimValue>,
|
||||
_rhs: Self,
|
||||
rhs_value: Cow<'_, Self::SimValue>,
|
||||
) -> bool {
|
||||
*lhs_value == *rhs_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())
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn cmp_expr_ne(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
|
||||
lhs.cast_to_bits().cmp_ne(rhs.cast_to_bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct CommonMOp<
|
||||
PrefixPad: KnownSize,
|
||||
DestReg: Type,
|
||||
SrcRegWidth: Size,
|
||||
SrcCount: KnownSize,
|
||||
Imm: Type,
|
||||
> {
|
||||
pub prefix_pad: UIntType<PrefixPad>,
|
||||
pub dest: DestReg,
|
||||
pub src: ArrayType<UIntType<SrcRegWidth>, SrcCount>,
|
||||
pub imm: Imm,
|
||||
}
|
||||
|
||||
impl<PrefixPad: KnownSize, DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize, Imm: Type>
|
||||
CommonMOp<PrefixPad, DestReg, SrcRegWidth, SrcCount, Imm>
|
||||
{
|
||||
pub fn validate(self) {
|
||||
let imm_type_properties = self.imm.canonical().type_properties();
|
||||
assert!(
|
||||
imm_type_properties.bit_width <= common_mop_max_imm_size(SrcCount::VALUE),
|
||||
"{self:#?}",
|
||||
);
|
||||
// TODO: reg_alloc tests don't respect the min reg width,
|
||||
// we should probably add padding to `CommonMOp` after `src` to compensate
|
||||
// assert!(self.src.element().width() >= MOP_MIN_REG_WIDTH, "{self:#?}");
|
||||
}
|
||||
}
|
||||
|
||||
impl<PrefixPad: KnownSize, DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize, Imm: Type>
|
||||
CommonMOpTrait for CommonMOp<PrefixPad, DestReg, SrcRegWidth, SrcCount, Imm>
|
||||
{
|
||||
type PrefixPad = PrefixPad;
|
||||
type SrcCount = SrcCount;
|
||||
type Imm = Imm;
|
||||
type CommonMOpTraitMapped<NewDestReg: Type, NewSrcRegWidth: Size> =
|
||||
CommonMOp<PrefixPad, NewDestReg, NewSrcRegWidth, SrcCount>;
|
||||
CommonMOp<PrefixPad, NewDestReg, NewSrcRegWidth, SrcCount, Imm>;
|
||||
type CommonMOpTraitDestReg = DestReg;
|
||||
type CommonMOpTraitSrcRegWidth = SrcRegWidth;
|
||||
fn common_mop_ty(
|
||||
self,
|
||||
) -> CommonMOp<Self::PrefixPad, Self::DestReg, Self::SrcRegWidth, Self::SrcCount> {
|
||||
) -> CommonMOp<Self::PrefixPad, Self::DestReg, Self::SrcRegWidth, Self::SrcCount, Self::Imm>
|
||||
{
|
||||
self.validate();
|
||||
self
|
||||
}
|
||||
fn common_mop(
|
||||
input: impl ToExpr<Type = Self>,
|
||||
) -> Expr<CommonMOp<Self::PrefixPad, Self::DestReg, Self::SrcRegWidth, Self::SrcCount>> {
|
||||
input.to_expr()
|
||||
) -> Expr<CommonMOp<Self::PrefixPad, Self::DestReg, Self::SrcRegWidth, Self::SrcCount, Self::Imm>>
|
||||
{
|
||||
let input = input.to_expr();
|
||||
input.ty().validate();
|
||||
input
|
||||
}
|
||||
fn with_common_mop_ty<NewDestReg: Type, NewSrcRegWidth: Size>(
|
||||
self,
|
||||
new_common_mop_ty: CommonMOp<Self::PrefixPad, NewDestReg, NewSrcRegWidth, Self::SrcCount>,
|
||||
new_common_mop_ty: CommonMOp<
|
||||
Self::PrefixPad,
|
||||
NewDestReg,
|
||||
NewSrcRegWidth,
|
||||
Self::SrcCount,
|
||||
Self::Imm,
|
||||
>,
|
||||
) -> Self::Mapped<NewDestReg, NewSrcRegWidth> {
|
||||
self.validate();
|
||||
new_common_mop_ty.validate();
|
||||
new_common_mop_ty
|
||||
}
|
||||
fn with_common_mop<NewDestReg: Type, NewSrcRegWidth: Size>(
|
||||
input: impl ToExpr<Type = Self>,
|
||||
new_common_mop: impl ToExpr<
|
||||
Type = CommonMOp<Self::PrefixPad, NewDestReg, NewSrcRegWidth, Self::SrcCount>,
|
||||
Type = CommonMOp<
|
||||
Self::PrefixPad,
|
||||
NewDestReg,
|
||||
NewSrcRegWidth,
|
||||
Self::SrcCount,
|
||||
Self::Imm,
|
||||
>,
|
||||
>,
|
||||
) -> Expr<Self::Mapped<NewDestReg, NewSrcRegWidth>> {
|
||||
let _ = input.to_expr();
|
||||
new_common_mop.to_expr()
|
||||
let input = input.to_expr();
|
||||
let new_common_mop = new_common_mop.to_expr();
|
||||
input.ty().validate();
|
||||
new_common_mop.ty().validate();
|
||||
new_common_mop
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct CommonMOpImmParts<ImmInSrcCount: Size> {
|
||||
// fields must be in this exact order
|
||||
pub imm_low: UInt<{ COMMON_MOP_IMM_LOW_WIDTH }>,
|
||||
pub reversed_src: ArrayType<UInt<{ MOP_MIN_REG_WIDTH }>, ImmInSrcCount>,
|
||||
pub imm_sign: SInt<1>,
|
||||
}
|
||||
|
||||
type CommonMOpWithMaxSrcCount = CommonMOpForImm<{ COMMON_MOP_SRC_LEN }>;
|
||||
|
||||
type CommonMOpForImm<const SRC_COUNT: usize> =
|
||||
CommonMOp<ConstUsize<0>, (), ConstUsize<{ MOP_MIN_REG_WIDTH }>, ConstUsize<SRC_COUNT>>;
|
||||
|
||||
pub const COMMON_MOP_0_IMM_WIDTH: usize = CommonMOpForImm::<0>::IMM_WIDTH;
|
||||
pub const COMMON_MOP_1_IMM_WIDTH: usize = CommonMOpForImm::<1>::IMM_WIDTH;
|
||||
pub const COMMON_MOP_2_IMM_WIDTH: usize = CommonMOpForImm::<2>::IMM_WIDTH;
|
||||
pub const COMMON_MOP_3_IMM_WIDTH: usize = CommonMOpForImm::<3>::IMM_WIDTH;
|
||||
const COMMON_MOP_0_IMM_IN_SRC_COUNT: usize = CommonMOpForImm::<0>::IMM_IN_SRC_COUNT;
|
||||
|
||||
impl<PrefixPad: KnownSize, DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize>
|
||||
CommonMOp<PrefixPad, DestReg, SrcRegWidth, SrcCount>
|
||||
{
|
||||
pub const IMM_IN_SRC_COUNT: usize = {
|
||||
assert!(SrcCount::VALUE <= COMMON_MOP_SRC_LEN, "too many sources");
|
||||
const _: () = assert!(COMMON_MOP_MIN_SRC_LEN_WITH_FULL_IMM <= COMMON_MOP_SRC_LEN);
|
||||
(COMMON_MOP_SRC_LEN - COMMON_MOP_MIN_SRC_LEN_WITH_FULL_IMM)
|
||||
- SrcCount::VALUE.saturating_sub(COMMON_MOP_MIN_SRC_LEN_WITH_FULL_IMM)
|
||||
};
|
||||
pub const IMM_IN_SRC_RANGE: Range<usize> =
|
||||
(COMMON_MOP_SRC_LEN - Self::IMM_IN_SRC_COUNT)..COMMON_MOP_SRC_LEN;
|
||||
pub const IMM_WIDTH: usize = {
|
||||
MOP_IMM_WIDTH - (COMMON_MOP_0_IMM_IN_SRC_COUNT - Self::IMM_IN_SRC_COUNT) * MOP_MIN_REG_WIDTH
|
||||
};
|
||||
pub fn imm_ty() -> SInt {
|
||||
SInt::new(Self::IMM_WIDTH)
|
||||
}
|
||||
pub fn imm_parts_ty() -> CommonMOpImmParts<DynSize> {
|
||||
let retval = CommonMOpImmParts[Self::IMM_IN_SRC_COUNT];
|
||||
assert_eq!(
|
||||
retval.canonical().bit_width(),
|
||||
Self::IMM_WIDTH,
|
||||
"{retval:#?}"
|
||||
);
|
||||
retval
|
||||
}
|
||||
#[hdl]
|
||||
pub fn new(
|
||||
prefix_pad: impl ToExpr<Type = UIntType<PrefixPad>>,
|
||||
dest: impl ToExpr<Type = DestReg>,
|
||||
src: impl ToExpr<Type = ArrayType<UIntType<SrcRegWidth>, SrcCount>>,
|
||||
imm: impl ToExpr<Type = SInt>,
|
||||
) -> Expr<Self> {
|
||||
let prefix_pad = prefix_pad.to_expr();
|
||||
let dest = dest.to_expr();
|
||||
let src_in = src.to_expr();
|
||||
let imm = imm.to_expr();
|
||||
assert_eq!(imm.ty(), Self::imm_ty());
|
||||
let src_reg_ty = src_in.ty().element();
|
||||
let imm_parts = imm.cast_to_bits().cast_bits_to(Self::imm_parts_ty());
|
||||
let mut src = [0_hdl_u0.cast_to(src_reg_ty); COMMON_MOP_SRC_LEN];
|
||||
for i in 0..SrcCount::VALUE {
|
||||
src[i] = src_in[i];
|
||||
}
|
||||
for (reversed_src_index, src_index) in Self::IMM_IN_SRC_RANGE.rev().enumerate() {
|
||||
src[src_index] = imm_parts.reversed_src[reversed_src_index].cast_to(src_reg_ty);
|
||||
}
|
||||
#[hdl]
|
||||
Self {
|
||||
prefix_pad,
|
||||
dest,
|
||||
src: ArrayLiteral::new(
|
||||
src_reg_ty,
|
||||
Interned::from_iter(src.iter().map(|v| Expr::canonical(*v))),
|
||||
)
|
||||
.to_expr(),
|
||||
imm_low: Expr::from_dyn_int(imm[..COMMON_MOP_IMM_LOW_WIDTH]),
|
||||
imm_sign: Expr::from_dyn_int(imm >> (Self::IMM_WIDTH - 1)),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
#[hdl]
|
||||
pub fn imm(expr: impl ToExpr<Type = Self>) -> Expr<SInt> {
|
||||
let expr = expr.to_expr();
|
||||
let reversed_src = Vec::from_iter(
|
||||
Self::IMM_IN_SRC_RANGE
|
||||
.rev()
|
||||
.map(|src_index| expr.src[src_index].cast_to_static()),
|
||||
);
|
||||
let imm_parts = {
|
||||
#[hdl]
|
||||
CommonMOpImmParts {
|
||||
imm_low: expr.imm_low,
|
||||
reversed_src,
|
||||
imm_sign: expr.imm_sign,
|
||||
}
|
||||
};
|
||||
imm_parts.cast_to_bits().cast_bits_to(Self::imm_ty())
|
||||
}
|
||||
#[hdl]
|
||||
pub fn connect_to_imm(expr: impl ToExpr<Type = Self>, imm: impl ToExpr<Type = SInt>) {
|
||||
let expr = expr.to_expr();
|
||||
let src_reg_ty = expr.ty().src.element();
|
||||
let imm = imm.to_expr();
|
||||
assert_eq!(imm.ty(), Self::imm_ty());
|
||||
let imm_parts = imm.cast_to_bits().cast_bits_to(Self::imm_parts_ty());
|
||||
let mut src = [Some(0_hdl_u0.cast_to(src_reg_ty)); COMMON_MOP_SRC_LEN];
|
||||
for i in 0..SrcCount::VALUE {
|
||||
src[i] = None;
|
||||
}
|
||||
for (reversed_src_index, src_index) in Self::IMM_IN_SRC_RANGE.rev().enumerate() {
|
||||
src[src_index] = Some(imm_parts.reversed_src[reversed_src_index].cast_to(src_reg_ty));
|
||||
}
|
||||
for i in 0..COMMON_MOP_SRC_LEN {
|
||||
if let Some(v) = src[i] {
|
||||
connect(expr.src[i], v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub const COMMON_MOP_0_IMM_WIDTH: usize = common_mop_max_imm_size(0);
|
||||
pub const COMMON_MOP_1_IMM_WIDTH: usize = common_mop_max_imm_size(1);
|
||||
pub const COMMON_MOP_2_IMM_WIDTH: usize = common_mop_max_imm_size(2);
|
||||
pub const COMMON_MOP_3_IMM_WIDTH: usize = common_mop_max_imm_size(3);
|
||||
|
||||
macro_rules! common_mop_struct {
|
||||
(
|
||||
|
|
@ -483,23 +598,24 @@ macro_rules! common_mop_struct {
|
|||
impl<$($Generic: $GenericBound),*> CommonMOpTrait for $MOp<$($Generic),*> {
|
||||
type PrefixPad = <$common_ty as CommonMOpTrait>::PrefixPad;
|
||||
type SrcCount = <$common_ty as CommonMOpTrait>::SrcCount;
|
||||
type Imm = <$common_ty as CommonMOpTrait>::Imm;
|
||||
type CommonMOpTraitMapped<$NewDestReg: Type, $SrcRegWidth: Size> = $mapped_ty;
|
||||
type CommonMOpTraitDestReg = <$common_ty as CommonMOpTrait>::CommonMOpTraitDestReg;
|
||||
type CommonMOpTraitSrcRegWidth = <$common_ty as CommonMOpTrait>::CommonMOpTraitSrcRegWidth;
|
||||
|
||||
fn common_mop_ty(
|
||||
self,
|
||||
) -> CommonMOp<Self::PrefixPad, Self::DestReg, Self::SrcRegWidth, Self::SrcCount> {
|
||||
) -> CommonMOp<Self::PrefixPad, Self::DestReg, Self::SrcRegWidth, Self::SrcCount, Self::Imm> {
|
||||
CommonMOpTrait::common_mop_ty(self.$common)
|
||||
}
|
||||
fn common_mop(
|
||||
input: impl ToExpr<Type = Self>,
|
||||
) -> Expr<CommonMOp<Self::PrefixPad, Self::DestReg, Self::SrcRegWidth, Self::SrcCount>> {
|
||||
) -> Expr<CommonMOp<Self::PrefixPad, Self::DestReg, Self::SrcRegWidth, Self::SrcCount, Self::Imm>> {
|
||||
CommonMOpTrait::common_mop(input.to_expr().$common)
|
||||
}
|
||||
fn with_common_mop_ty<NewDestReg: Type, NewSrcRegWidth: Size>(
|
||||
self,
|
||||
new_common_mop_ty: CommonMOp<Self::PrefixPad, NewDestReg, NewSrcRegWidth, Self::SrcCount>,
|
||||
new_common_mop_ty: CommonMOp<Self::PrefixPad, NewDestReg, NewSrcRegWidth, Self::SrcCount, Self::Imm>,
|
||||
) -> Self::Mapped<NewDestReg, NewSrcRegWidth> {
|
||||
$MOp {
|
||||
$common: CommonMOpTrait::with_common_mop_ty(self.$common, new_common_mop_ty),
|
||||
|
|
@ -510,7 +626,7 @@ macro_rules! common_mop_struct {
|
|||
fn with_common_mop<NewDestReg: Type, NewSrcRegWidth: Size>(
|
||||
input: impl ToExpr<Type = Self>,
|
||||
new_common_mop: impl ToExpr<
|
||||
Type = CommonMOp<Self::PrefixPad, NewDestReg, NewSrcRegWidth, Self::SrcCount>,
|
||||
Type = CommonMOp<Self::PrefixPad, NewDestReg, NewSrcRegWidth, Self::SrcCount, Self::Imm>,
|
||||
>,
|
||||
) -> Expr<Self::Mapped<NewDestReg, NewSrcRegWidth>> {
|
||||
let input = input.to_expr();
|
||||
|
|
@ -818,11 +934,11 @@ macro_rules! mop_enum {
|
|||
pub(crate) use mop_enum;
|
||||
|
||||
common_mop_struct! {
|
||||
#[mapped(<NewDestReg, NewSrcRegWidth> AluCommonMOp<NewDestReg, NewSrcRegWidth, SrcCount>)]
|
||||
#[mapped(<NewDestReg, NewSrcRegWidth> AluCommonMOp<NewDestReg, NewSrcRegWidth, SrcCount, Imm>)]
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct AluCommonMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||
pub struct AluCommonMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize, Imm: Type> {
|
||||
#[common]
|
||||
pub common: CommonMOp<ConstUsize<0>, DestReg, SrcRegWidth, SrcCount>,
|
||||
pub common: CommonMOp<ConstUsize<0>, DestReg, SrcRegWidth, SrcCount, Imm>,
|
||||
pub output_integer_mode: OutputIntegerMode,
|
||||
}
|
||||
}
|
||||
|
|
@ -832,7 +948,7 @@ common_mop_struct! {
|
|||
#[hdl(cmp_eq)]
|
||||
pub struct AddSubMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||
#[common]
|
||||
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, SrcCount>,
|
||||
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, SrcCount, CommonMOpDefaultImm<SrcCount>>,
|
||||
pub invert_src0: Bool,
|
||||
/// * if this is `true`, use `alu_common.src[1]`'s [`PRegFlagsPowerISA::xer_ca`] as a carry-in/borrow-in
|
||||
/// * else, use `alu_common.src[1]` as a normal addend
|
||||
|
|
@ -862,7 +978,13 @@ impl<DestReg: Type, SrcRegWidth: Size> AddSubMOp<DestReg, SrcRegWidth, ConstUsiz
|
|||
AddSubMOp {
|
||||
alu_common: #[hdl]
|
||||
AluCommonMOp {
|
||||
common: CommonMOp::new(0_hdl_u0, dest, src, Expr::as_dyn_int(imm.to_expr())),
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: 0_hdl_u0,
|
||||
dest,
|
||||
src,
|
||||
imm: CommonMOpDefaultImm::from_sint(imm.to_expr()),
|
||||
},
|
||||
output_integer_mode,
|
||||
},
|
||||
invert_src0,
|
||||
|
|
@ -894,7 +1016,13 @@ impl<DestReg: Type, SrcRegWidth: Size> AddSubMOp<DestReg, SrcRegWidth, ConstUsiz
|
|||
AddSubMOp {
|
||||
alu_common: #[hdl]
|
||||
AluCommonMOp {
|
||||
common: CommonMOp::new(0_hdl_u0, dest, src, Expr::as_dyn_int(imm.to_expr())),
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: 0_hdl_u0,
|
||||
dest,
|
||||
src,
|
||||
imm: CommonMOpDefaultImm::from_sint(imm.to_expr()),
|
||||
},
|
||||
output_integer_mode,
|
||||
},
|
||||
invert_src0,
|
||||
|
|
@ -987,18 +1115,6 @@ pub struct LogicalFlagsMOpImm {
|
|||
pub dest_count: UIntInRangeInclusive<0, { PRegFlags::FLAG_COUNT }>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[test]
|
||||
fn test_logical_flags_mop_imm_fits() {
|
||||
let needed_width = LogicalFlagsMOpImm.canonical().bit_width();
|
||||
let imm_width =
|
||||
CommonMOpFor::<LogicalFlagsMOp<MOpDestReg, ConstUsize<{ MOpRegNum::WIDTH }>>>::IMM_WIDTH;
|
||||
assert!(
|
||||
needed_width <= imm_width,
|
||||
"needed_width={needed_width} imm_width={imm_width}",
|
||||
);
|
||||
}
|
||||
|
||||
/// intentionally not publicly constructable
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct LogicalFlagsMOpImmFromSwizzleFnSrc<const SRC: usize> {
|
||||
|
|
@ -1087,20 +1203,6 @@ impl std::error::Error for LogicalFlagsMopImmTryFromSwizzleFnError {}
|
|||
|
||||
impl LogicalFlagsMOpImm {
|
||||
pub const SWIZZLE_CAPACITY: usize = 4;
|
||||
#[track_caller]
|
||||
pub fn from_imm(imm: impl ToExpr<Type = SInt>) -> Expr<Self> {
|
||||
let imm_ty =
|
||||
CommonMOpFor::<LogicalFlagsMOp<MOpDestReg, ConstUsize<{ MOpRegNum::WIDTH }>>>::imm_ty();
|
||||
let imm = imm.to_expr();
|
||||
assert_eq!(imm_ty, imm.ty(), "imm must have the correct width");
|
||||
imm.cast_to(UInt[LogicalFlagsMOpImm.canonical().bit_width()])
|
||||
.cast_bits_to(LogicalFlagsMOpImm)
|
||||
}
|
||||
pub fn to_imm(this: impl ToExpr<Type = Self>) -> Expr<SInt> {
|
||||
let imm_ty =
|
||||
CommonMOpFor::<LogicalFlagsMOp<MOpDestReg, ConstUsize<{ MOpRegNum::WIDTH }>>>::imm_ty();
|
||||
this.to_expr().cast_to_bits().cast_to(imm_ty)
|
||||
}
|
||||
fn flags_operation_impl<Flags, I, IU, C, CU, Lut, U, B, AF>(
|
||||
src0_start: I,
|
||||
src1_start: I,
|
||||
|
|
@ -1464,7 +1566,7 @@ common_mop_struct! {
|
|||
/// ```
|
||||
pub struct LogicalFlagsMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||
#[common]
|
||||
pub common: CommonMOp<ConstUsize<0>, DestReg, SrcRegWidth, ConstUsize<3>>,
|
||||
pub common: CommonMOp<ConstUsize<0>, DestReg, SrcRegWidth, ConstUsize<3>, LogicalFlagsMOpImm>,
|
||||
pub lut: Lut4,
|
||||
}
|
||||
}
|
||||
|
|
@ -1477,7 +1579,7 @@ impl<DestReg: Type, SrcRegWidth: Size> LogicalFlagsMOp<DestReg, SrcRegWidth> {
|
|||
) -> Expr<PRegValue> {
|
||||
let this = this.to_expr();
|
||||
let flags = LogicalFlagsMOpImm::flags_operation(
|
||||
Self::imm(this),
|
||||
this.common.imm,
|
||||
this.lut,
|
||||
src.to_expr().map(|v| v.flags),
|
||||
);
|
||||
|
|
@ -1496,10 +1598,18 @@ impl<DestReg: Type, SrcRegWidth: Size> LogicalFlagsMOp<DestReg, SrcRegWidth> {
|
|||
this: impl ToSimValue<Type = Self>,
|
||||
src: impl ToSimValue<Type = Array<PRegValue, 3>>,
|
||||
) -> SimValue<PRegValue> {
|
||||
let this = this.into_sim_value();
|
||||
#[hdl(sim)]
|
||||
let Self { common, lut } = this.into_sim_value();
|
||||
#[hdl(sim)]
|
||||
let CommonMOp::<_, _, _, _, _> {
|
||||
prefix_pad: _,
|
||||
dest: _,
|
||||
src: _,
|
||||
imm,
|
||||
} = common;
|
||||
let flags = LogicalFlagsMOpImm::flags_operation_sim(
|
||||
Self::imm(&this),
|
||||
SimValue::into_value(this).lut,
|
||||
imm,
|
||||
lut,
|
||||
SimValue::into_value(src.into_sim_value()).map(|v| SimValue::into_value(v).flags),
|
||||
);
|
||||
#[hdl(sim)]
|
||||
|
|
@ -1513,10 +1623,6 @@ impl<DestReg: Type, SrcRegWidth: Size> LogicalFlagsMOp<DestReg, SrcRegWidth> {
|
|||
}
|
||||
}
|
||||
#[hdl]
|
||||
pub fn imm(this: impl ToExpr<Type = Self>) -> Expr<LogicalFlagsMOpImm> {
|
||||
LogicalFlagsMOpImm::from_imm(CommonMOpFor::<Self>::imm(this.to_expr().common))
|
||||
}
|
||||
#[hdl]
|
||||
pub fn logical_flags<Target: MOpTrait>(
|
||||
dest: impl ToExpr<Type = DestReg>,
|
||||
src: impl ToExpr<Type = Array<UIntType<SrcRegWidth>, 3>>,
|
||||
|
|
@ -1529,12 +1635,13 @@ impl<DestReg: Type, SrcRegWidth: Size> LogicalFlagsMOp<DestReg, SrcRegWidth> {
|
|||
MOpInto::mop_into(
|
||||
#[hdl]
|
||||
LogicalFlagsMOp {
|
||||
common: CommonMOp::new(
|
||||
0_hdl_u0,
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: 0_hdl_u0,
|
||||
dest,
|
||||
src,
|
||||
LogicalFlagsMOpImm::to_imm(imm.to_expr()),
|
||||
),
|
||||
imm,
|
||||
},
|
||||
lut,
|
||||
},
|
||||
)
|
||||
|
|
@ -1546,7 +1653,7 @@ common_mop_struct! {
|
|||
#[hdl(cmp_eq)]
|
||||
pub struct LogicalMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||
#[common]
|
||||
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, SrcCount>,
|
||||
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, SrcCount, CommonMOpDefaultImm<SrcCount>>,
|
||||
pub lut: Lut4,
|
||||
}
|
||||
}
|
||||
|
|
@ -1568,7 +1675,13 @@ impl<DestReg: Type, SrcRegWidth: Size> LogicalMOp<DestReg, SrcRegWidth, ConstUsi
|
|||
LogicalMOp {
|
||||
alu_common: #[hdl]
|
||||
AluCommonMOp {
|
||||
common: CommonMOp::new(0_hdl_u0, dest, src, Expr::as_dyn_int(imm.to_expr())),
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: 0_hdl_u0,
|
||||
dest,
|
||||
src,
|
||||
imm: CommonMOpDefaultImm::from_sint(imm.to_expr()),
|
||||
},
|
||||
output_integer_mode,
|
||||
},
|
||||
lut,
|
||||
|
|
@ -1594,7 +1707,13 @@ impl<DestReg: Type, SrcRegWidth: Size> LogicalMOp<DestReg, SrcRegWidth, ConstUsi
|
|||
LogicalMOp {
|
||||
alu_common: #[hdl]
|
||||
AluCommonMOp {
|
||||
common: CommonMOp::new(0_hdl_u0, dest, src, Expr::as_dyn_int(imm.to_expr())),
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: 0_hdl_u0,
|
||||
dest,
|
||||
src,
|
||||
imm: CommonMOpDefaultImm::from_sint(imm.to_expr()),
|
||||
},
|
||||
output_integer_mode,
|
||||
},
|
||||
lut,
|
||||
|
|
@ -1748,50 +1867,17 @@ pub struct ShiftRotateMOpImm {
|
|||
pub dest_logic_op: HdlOption<ShiftRotateDestLogicOp>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[test]
|
||||
fn test_shift_rotate_mop_imm_fits() {
|
||||
let needed_width = ShiftRotateMOpImm.canonical().bit_width();
|
||||
let imm_width =
|
||||
CommonMOpFor::<ShiftRotateMOp<MOpDestReg, ConstUsize<{ MOpRegNum::WIDTH }>>>::IMM_WIDTH;
|
||||
assert!(
|
||||
needed_width <= imm_width,
|
||||
"needed_width={needed_width} imm_width={imm_width}",
|
||||
);
|
||||
}
|
||||
|
||||
impl ShiftRotateMOpImm {
|
||||
#[track_caller]
|
||||
pub fn from_imm(imm: impl ToExpr<Type = SInt>) -> Expr<Self> {
|
||||
let imm_ty =
|
||||
CommonMOpFor::<ShiftRotateMOp<MOpDestReg, ConstUsize<{ MOpRegNum::WIDTH }>>>::imm_ty();
|
||||
let imm = imm.to_expr();
|
||||
assert_eq!(imm_ty, imm.ty(), "imm must have the correct width");
|
||||
imm.cast_to(UInt[ShiftRotateMOpImm.canonical().bit_width()])
|
||||
.cast_bits_to(ShiftRotateMOpImm)
|
||||
}
|
||||
pub fn to_imm(this: impl ToExpr<Type = Self>) -> Expr<SInt> {
|
||||
let imm_ty =
|
||||
CommonMOpFor::<ShiftRotateMOp<MOpDestReg, ConstUsize<{ MOpRegNum::WIDTH }>>>::imm_ty();
|
||||
this.to_expr().cast_to_bits().cast_to(imm_ty)
|
||||
}
|
||||
}
|
||||
|
||||
common_mop_struct! {
|
||||
#[mapped(<NewDestReg, NewSrcRegWidth> ShiftRotateMOp<NewDestReg, NewSrcRegWidth>)]
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct ShiftRotateMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||
#[common]
|
||||
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, ConstUsize<3>>,
|
||||
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, ConstUsize<3>, ShiftRotateMOpImm>,
|
||||
pub mode: ShiftRotateMode,
|
||||
}
|
||||
}
|
||||
|
||||
impl<DestReg: Type, SrcRegWidth: Size> ShiftRotateMOp<DestReg, SrcRegWidth> {
|
||||
#[hdl]
|
||||
pub fn imm(this: impl ToExpr<Type = Self>) -> Expr<ShiftRotateMOpImm> {
|
||||
ShiftRotateMOpImm::from_imm(CommonMOpFor::<Self>::imm(this.to_expr().alu_common.common))
|
||||
}
|
||||
#[hdl]
|
||||
pub fn shift_rotate<Target: MOpTrait>(
|
||||
dest: impl ToExpr<Type = DestReg>,
|
||||
|
|
@ -1808,12 +1894,13 @@ impl<DestReg: Type, SrcRegWidth: Size> ShiftRotateMOp<DestReg, SrcRegWidth> {
|
|||
ShiftRotateMOp {
|
||||
alu_common: #[hdl]
|
||||
AluCommonMOp {
|
||||
common: CommonMOp::new(
|
||||
0_hdl_u0,
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: 0_hdl_u0,
|
||||
dest,
|
||||
src,
|
||||
ShiftRotateMOpImm::to_imm(imm.to_expr()),
|
||||
),
|
||||
imm,
|
||||
},
|
||||
output_integer_mode,
|
||||
},
|
||||
mode,
|
||||
|
|
@ -1879,7 +1966,7 @@ common_mop_struct! {
|
|||
#[hdl(cmp_eq)]
|
||||
pub struct CompareMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||
#[common]
|
||||
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, SrcCount>,
|
||||
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, SrcCount, CommonMOpDefaultImm<SrcCount>>,
|
||||
pub compare_mode: CompareMode,
|
||||
}
|
||||
}
|
||||
|
|
@ -1901,7 +1988,13 @@ impl<DestReg: Type, SrcRegWidth: Size> CompareMOp<DestReg, SrcRegWidth, ConstUsi
|
|||
CompareMOp {
|
||||
alu_common: #[hdl]
|
||||
AluCommonMOp {
|
||||
common: CommonMOp::new(0_hdl_u0, dest, src, Expr::as_dyn_int(imm.to_expr())),
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: 0_hdl_u0,
|
||||
dest,
|
||||
src,
|
||||
imm: CommonMOpDefaultImm::from_sint(imm.to_expr()),
|
||||
},
|
||||
output_integer_mode,
|
||||
},
|
||||
compare_mode,
|
||||
|
|
@ -1927,7 +2020,13 @@ impl<DestReg: Type, SrcRegWidth: Size> CompareMOp<DestReg, SrcRegWidth, ConstUsi
|
|||
CompareMOp {
|
||||
alu_common: #[hdl]
|
||||
AluCommonMOp {
|
||||
common: CommonMOp::new(0_hdl_u0, dest, src, Expr::as_dyn_int(imm.to_expr())),
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: 0_hdl_u0,
|
||||
dest,
|
||||
src,
|
||||
imm: CommonMOpDefaultImm::from_sint(imm.to_expr()),
|
||||
},
|
||||
output_integer_mode,
|
||||
},
|
||||
compare_mode,
|
||||
|
|
@ -1992,7 +2091,7 @@ common_mop_struct! {
|
|||
/// The output value is the next instruction's address used for a return address when this is a call.
|
||||
pub struct BranchMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||
#[common]
|
||||
pub common: CommonMOp<ConstUsize<0>, DestReg, SrcRegWidth, SrcCount>,
|
||||
pub common: CommonMOp<ConstUsize<0>, DestReg, SrcRegWidth, SrcCount, CommonMOpDefaultImm<SrcCount>>,
|
||||
pub invert_src0_cond: Bool,
|
||||
pub src0_cond_mode: ConditionMode,
|
||||
/// `src2`'s condition passes if `src2`'s value `== 0`.
|
||||
|
|
@ -2022,7 +2121,13 @@ impl<DestReg: Type, SrcRegWidth: Size> BranchMOp<DestReg, SrcRegWidth, ConstUsiz
|
|||
MOpInto::mop_into(
|
||||
#[hdl]
|
||||
BranchMOp {
|
||||
common: CommonMOp::new(0_hdl_u0, dest, src, Expr::as_dyn_int(imm.to_expr())),
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: 0_hdl_u0,
|
||||
dest,
|
||||
src,
|
||||
imm: CommonMOpDefaultImm::from_sint(imm.to_expr()),
|
||||
},
|
||||
invert_src0_cond,
|
||||
src0_cond_mode,
|
||||
invert_src2_eq_zero: false,
|
||||
|
|
@ -2083,7 +2188,13 @@ impl<DestReg: Type, SrcRegWidth: Size> BranchMOp<DestReg, SrcRegWidth, ConstUsiz
|
|||
MOpInto::mop_into(
|
||||
#[hdl]
|
||||
BranchMOp {
|
||||
common: CommonMOp::new(0_hdl_u0, dest, src, Expr::as_dyn_int(imm.to_expr())),
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: 0_hdl_u0,
|
||||
dest,
|
||||
src,
|
||||
imm: CommonMOpDefaultImm::from_sint(imm.to_expr()),
|
||||
},
|
||||
invert_src0_cond,
|
||||
src0_cond_mode,
|
||||
invert_src2_eq_zero,
|
||||
|
|
@ -2150,7 +2261,7 @@ common_mop_struct! {
|
|||
#[hdl(cmp_eq)]
|
||||
pub struct ReadL2RegMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||
#[common]
|
||||
pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, ConstUsize<0>>,
|
||||
pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, ConstUsize<0>, CommonMOpDefaultImm<ConstUsize<0>>>,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2159,7 +2270,7 @@ common_mop_struct! {
|
|||
#[hdl(cmp_eq)]
|
||||
pub struct WriteL2RegMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||
#[common]
|
||||
pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, ConstUsize<1>>,
|
||||
pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, ConstUsize<1>, CommonMOpDefaultImm<ConstUsize<1>>>,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2261,7 +2372,7 @@ common_mop_struct! {
|
|||
/// `src0` is always the address to load from or store to.
|
||||
pub struct LoadStoreCommonMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||
#[common]
|
||||
pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, SrcCount>,
|
||||
pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, SrcCount, CommonMOpDefaultImm<SrcCount>>,
|
||||
pub width: LoadStoreWidth,
|
||||
pub conversion: LoadStoreConversion,
|
||||
}
|
||||
|
|
@ -2292,12 +2403,13 @@ impl<DestReg: Type, SrcRegWidth: Size> LoadMOp<DestReg, SrcRegWidth> {
|
|||
LoadMOp {
|
||||
load_store_common: #[hdl]
|
||||
LoadStoreCommonMOp {
|
||||
common: CommonMOp::new(
|
||||
0.cast_to_static::<UInt<_>>(),
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: UInt::TYPE.zero(),
|
||||
dest,
|
||||
src,
|
||||
SInt[COMMON_MOP_1_IMM_WIDTH].zero(),
|
||||
),
|
||||
imm: CommonMOpDefaultImm::TYPE.zero(),
|
||||
},
|
||||
width,
|
||||
conversion,
|
||||
},
|
||||
|
|
@ -2332,12 +2444,13 @@ impl<DestReg: Type, SrcRegWidth: Size> StoreMOp<DestReg, SrcRegWidth> {
|
|||
StoreMOp {
|
||||
load_store_common: #[hdl]
|
||||
LoadStoreCommonMOp {
|
||||
common: CommonMOp::new(
|
||||
0.cast_to_static::<UInt<_>>(),
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: UInt::TYPE.zero(),
|
||||
dest,
|
||||
src,
|
||||
SInt[COMMON_MOP_2_IMM_WIDTH].zero(),
|
||||
),
|
||||
imm: CommonMOpDefaultImm::TYPE.zero(),
|
||||
},
|
||||
width,
|
||||
conversion,
|
||||
},
|
||||
|
|
@ -2360,7 +2473,7 @@ common_mop_struct! {
|
|||
#[hdl(cmp_eq)]
|
||||
pub struct MoveRegMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||
#[common]
|
||||
pub common: CommonMOp<ConstUsize<4>, DestReg, SrcRegWidth, ConstUsize<1>>,
|
||||
pub common: CommonMOp<ConstUsize<4>, DestReg, SrcRegWidth, ConstUsize<1>, CommonMOpDefaultImm<ConstUsize<1>>>,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2395,12 +2508,13 @@ impl<DestReg: Type, SrcRegWidth: Size> MoveRegMOp<DestReg, SrcRegWidth> {
|
|||
MOpInto::mop_into(
|
||||
#[hdl]
|
||||
MoveRegMOp {
|
||||
common: CommonMOp::new(
|
||||
0.cast_to_static::<UInt<_>>(),
|
||||
common: #[hdl]
|
||||
CommonMOp {
|
||||
prefix_pad: UInt::TYPE.zero(),
|
||||
dest,
|
||||
src,
|
||||
Expr::as_dyn_int(imm.to_expr()),
|
||||
),
|
||||
imm: CommonMOpDefaultImm::from_sint(imm),
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
use crate::{
|
||||
config::CpuConfig,
|
||||
instruction::{
|
||||
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp,
|
||||
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOpDefaultImm,
|
||||
CompareMOp, LogicalFlagsMOp, LogicalMOp, MOpTrait, OutputIntegerMode, RenamedMOp,
|
||||
ShiftRotateMOp, UnitOutRegNum,
|
||||
},
|
||||
|
|
@ -42,11 +42,11 @@ fn add_sub<SrcCount: KnownSize>(
|
|||
add_pc,
|
||||
} = mop;
|
||||
#[hdl]
|
||||
let AluCommonMOp::<_, _, _> {
|
||||
let AluCommonMOp::<_, _, _, _> {
|
||||
common,
|
||||
output_integer_mode,
|
||||
} = alu_common;
|
||||
let imm: Expr<UInt<64>> = CommonMOp::imm(common).cast_to_static();
|
||||
let imm = CommonMOpDefaultImm::as_sint_dyn(common.imm).cast_to_static::<UInt<64>>();
|
||||
#[hdl]
|
||||
let carry_in_before_inversion = wire();
|
||||
connect(carry_in_before_inversion, false);
|
||||
|
|
|
|||
118780
crates/cpu/tests/expected/reg_alloc.vcd
generated
118780
crates/cpu/tests/expected/reg_alloc.vcd
generated
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue