UnitMOp now has L2RegisterFileMOp after renaming and instead has MoveRegMOp before renaming
This commit is contained in:
parent
6c91d1b0b0
commit
518284685f
|
@ -1,10 +1,10 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
use crate::{
|
||||
instruction::{MOpTrait, PRegNum, UnitNum, UnitOutRegNum, CONST_ZERO_UNIT_NUM},
|
||||
instruction::{MOpTrait, PRegNum, RenamedMOp, UnitNum, UnitOutRegNum, CONST_ZERO_UNIT_NUM},
|
||||
unit::{
|
||||
unit_base::{UnitForwardingInfo, UnitToRegAlloc},
|
||||
UnitCancelInput, UnitKind, UnitMOp, UnitOutputWrite,
|
||||
UnitCancelInput, UnitKind, UnitOutputWrite,
|
||||
},
|
||||
};
|
||||
use fayalite::prelude::*;
|
||||
|
@ -79,8 +79,8 @@ impl CpuConfig {
|
|||
pub fn p_reg_num_width(&self) -> usize {
|
||||
self.unit_num_width() + self.out_reg_num_width
|
||||
}
|
||||
pub fn unit_mop_in_unit(&self) -> UnitMOp<UnitOutRegNum<DynSize>, DynSize> {
|
||||
UnitMOp[self.unit_out_reg_num()][self.p_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]
|
||||
|
|
|
@ -25,7 +25,10 @@ impl<T: MOpTrait> MOpInto<T> for T {
|
|||
}
|
||||
|
||||
pub trait MOpTrait: Type {
|
||||
type Mapped<NewDestReg: Type, NewSrcRegWidth: Size>: MOpTrait;
|
||||
type Mapped<NewDestReg: Type, NewSrcRegWidth: Size>: MOpTrait<
|
||||
DestReg = NewDestReg,
|
||||
SrcRegWidth = NewSrcRegWidth,
|
||||
>;
|
||||
type DestReg: Type;
|
||||
type SrcRegWidth: Size;
|
||||
fn dest_reg_ty(self) -> Self::DestReg;
|
||||
|
@ -69,7 +72,12 @@ pub trait MOpTrait: Type {
|
|||
pub trait CommonMOpTrait: MOpTrait {
|
||||
type PrefixPad: KnownSize;
|
||||
type SrcCount: KnownSize;
|
||||
type CommonMOpTraitMapped<NewDestReg: Type, NewSrcRegWidth: Size>: CommonMOpTrait;
|
||||
type CommonMOpTraitMapped<NewDestReg: Type, NewSrcRegWidth: Size>: CommonMOpTrait<
|
||||
DestReg = NewDestReg,
|
||||
SrcRegWidth = NewSrcRegWidth,
|
||||
PrefixPad = Self::PrefixPad,
|
||||
SrcCount = Self::SrcCount,
|
||||
>;
|
||||
type CommonMOpTraitDestReg: Type;
|
||||
type CommonMOpTraitSrcRegWidth: Size;
|
||||
fn common_mop_ty(
|
||||
|
@ -418,9 +426,15 @@ macro_rules! common_mop_struct {
|
|||
|
||||
macro_rules! mop_enum {
|
||||
(
|
||||
#[impl_mop_into = $impl_mop_into:tt]
|
||||
$(#[$enum_meta:meta])*
|
||||
$vis:vis enum $MOp:ident<$DestReg:ident: Type, $SrcRegWidth:ident: Size> {
|
||||
$(#[$first_variant_meta:meta])*
|
||||
$vis:vis enum $MOp:ident<
|
||||
$DestReg:ident: Type,
|
||||
$SrcRegWidth:ident: Size
|
||||
$(, #[MOp(get_ty = $mop_types_get_ty:expr)] $MOpTypes:ident: Type)*
|
||||
$(, #[Size(get_size = $sizes_get_size:expr)] $Sizes:ident: Size)*
|
||||
> {
|
||||
$(#[$($first_variant_meta:tt)*])*
|
||||
$FirstVariant:ident($first_ty:ty),
|
||||
$(
|
||||
$(#[$variant_meta:meta])*
|
||||
|
@ -429,7 +443,7 @@ macro_rules! mop_enum {
|
|||
}
|
||||
) => {
|
||||
$(#[$enum_meta])*
|
||||
$vis enum $MOp<$DestReg: Type, $SrcRegWidth: Size> {
|
||||
$vis enum $MOp<$DestReg: Type, $SrcRegWidth: Size $(, $MOpTypes: Type)* $(, $Sizes: Size)*> {
|
||||
$(#[$first_variant_meta])*
|
||||
$FirstVariant($first_ty),
|
||||
$(
|
||||
|
@ -438,32 +452,37 @@ macro_rules! mop_enum {
|
|||
)*
|
||||
}
|
||||
|
||||
impl<$DestReg: Type, $SrcRegWidth: Size, Target: MOpTrait> MOpInto<Target> for $first_ty
|
||||
where
|
||||
$MOp<$DestReg, $SrcRegWidth>: MOpInto<Target>
|
||||
{
|
||||
fn mop_into_ty(self) -> Target {
|
||||
MOpInto::mop_into_ty($MOp[MOpTrait::dest_reg_ty(self)][MOpTrait::src_reg_width(self)])
|
||||
}
|
||||
fn mop_into(this: Expr<Self>) -> Expr<Target> {
|
||||
MOpInto::mop_into(MOpInto::<$MOp<$DestReg, $SrcRegWidth>>::mop_into_ty(Expr::ty(this)).$FirstVariant(this))
|
||||
mop_enum! {
|
||||
@impl_variants
|
||||
#[impl_mop_into = $impl_mop_into]
|
||||
enum $MOp [
|
||||
$DestReg: Type,
|
||||
$SrcRegWidth: Size
|
||||
$(, #[MOp(get_ty = $mop_types_get_ty)] $MOpTypes: Type)*
|
||||
$(, #[Size(get_size = $sizes_get_size)] $Sizes: Size)*
|
||||
] {
|
||||
$FirstVariant($first_ty),
|
||||
$($Variant($ty),)*
|
||||
}
|
||||
}
|
||||
|
||||
$(impl<$DestReg: Type, $SrcRegWidth: Size, Target: MOpTrait> MOpInto<Target> for $ty
|
||||
where
|
||||
$MOp<$DestReg, $SrcRegWidth>: MOpInto<Target>
|
||||
{
|
||||
fn mop_into_ty(self) -> Target {
|
||||
MOpInto::mop_into_ty($MOp[MOpTrait::dest_reg_ty(self)][MOpTrait::src_reg_width(self)])
|
||||
}
|
||||
fn mop_into(this: Expr<Self>) -> Expr<Target> {
|
||||
MOpInto::mop_into(MOpInto::<$MOp<$DestReg, $SrcRegWidth>>::mop_into_ty(Expr::ty(this)).$Variant(this))
|
||||
}
|
||||
})*
|
||||
|
||||
impl<$DestReg: Type, $SrcRegWidth: Size> MOpTrait for $MOp<$DestReg, $SrcRegWidth> {
|
||||
type Mapped<NewDestReg: Type, NewSrcRegWidth: Size> = $MOp<NewDestReg, NewSrcRegWidth>;
|
||||
impl<
|
||||
$DestReg: Type,
|
||||
$SrcRegWidth: Size,
|
||||
$($MOpTypes: Type + MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,)*
|
||||
$($Sizes: Size,)*
|
||||
> MOpTrait for $MOp<
|
||||
$DestReg,
|
||||
$SrcRegWidth,
|
||||
$($MOpTypes,)*
|
||||
$($Sizes,)*
|
||||
> {
|
||||
type Mapped<NewDestReg: Type, NewSrcRegWidth: Size> = $MOp<
|
||||
NewDestReg,
|
||||
NewSrcRegWidth,
|
||||
$(<$MOpTypes as MOpTrait>::Mapped<NewDestReg, NewSrcRegWidth>,)*
|
||||
$($Sizes,)*
|
||||
>;
|
||||
type DestReg = $DestReg;
|
||||
type SrcRegWidth = $SrcRegWidth;
|
||||
fn dest_reg_ty(self) -> Self::DestReg {
|
||||
|
@ -476,8 +495,8 @@ macro_rules! mop_enum {
|
|||
let dest_reg = wire(Expr::ty(input).dest_reg_ty());
|
||||
#[hdl]
|
||||
match input {
|
||||
$MOp::<_, _>::$FirstVariant(v) => connect(dest_reg, MOpTrait::dest_reg(v)),
|
||||
$($MOp::<_, _>::$Variant(v) => connect(dest_reg, MOpTrait::dest_reg(v)),)*
|
||||
Self::$FirstVariant(v) => connect(dest_reg, <$first_ty as MOpTrait>::dest_reg(v)),
|
||||
$(Self::$Variant(v) => connect(dest_reg, <$ty as MOpTrait>::dest_reg(v)),)*
|
||||
}
|
||||
dest_reg
|
||||
}
|
||||
|
@ -491,8 +510,8 @@ macro_rules! mop_enum {
|
|||
) {
|
||||
#[hdl]
|
||||
match input {
|
||||
$MOp::<_, _>::$FirstVariant(v) => MOpTrait::for_each_src_reg(v, f),
|
||||
$($MOp::<_, _>::$Variant(v) => MOpTrait::for_each_src_reg(v, f),)*
|
||||
Self::$FirstVariant(v) => MOpTrait::for_each_src_reg(v, f),
|
||||
$(Self::$Variant(v) => MOpTrait::for_each_src_reg(v, f),)*
|
||||
}
|
||||
}
|
||||
fn mapped_ty<NewDestReg: Type, NewSrcRegWidth: Size>(
|
||||
|
@ -500,7 +519,7 @@ macro_rules! mop_enum {
|
|||
new_dest_reg: NewDestReg,
|
||||
new_src_reg_width: NewSrcRegWidth::SizeType,
|
||||
) -> Self::Mapped<NewDestReg, NewSrcRegWidth> {
|
||||
$MOp[new_dest_reg][new_src_reg_width]
|
||||
$MOp[new_dest_reg][new_src_reg_width]$([$mop_types_get_ty(self, new_dest_reg, new_src_reg_width)])*$([$sizes_get_size(self)])*
|
||||
}
|
||||
#[hdl]
|
||||
fn map_regs<NewDestReg: Type, NewSrcRegWidth: Size>(
|
||||
|
@ -519,13 +538,52 @@ macro_rules! mop_enum {
|
|||
let mapped_regs = wire(mapped_ty);
|
||||
#[hdl]
|
||||
match input {
|
||||
$MOp::<_, _>::$FirstVariant(v) => connect(mapped_regs, mapped_ty.$FirstVariant(MOpTrait::map_regs(v, new_dest, new_src_reg_width, map_src))),
|
||||
$($MOp::<_, _>::$Variant(v) => connect(mapped_regs, mapped_ty.$Variant(MOpTrait::map_regs(v, new_dest, new_src_reg_width, map_src))),)*
|
||||
Self::$FirstVariant(v) => connect(mapped_regs, mapped_ty.$FirstVariant(MOpTrait::map_regs(v, new_dest, new_src_reg_width, map_src))),
|
||||
$(Self::$Variant(v) => connect(mapped_regs, mapped_ty.$Variant(MOpTrait::map_regs(v, new_dest, new_src_reg_width, map_src))),)*
|
||||
}
|
||||
mapped_regs
|
||||
}
|
||||
}
|
||||
};
|
||||
(
|
||||
@impl_variants
|
||||
#[impl_mop_into = true]
|
||||
enum $MOp:ident $generics:tt {
|
||||
$($Variant:ident($ty:ty),)+
|
||||
}
|
||||
) => {
|
||||
$(mop_enum! {
|
||||
@impl_variant
|
||||
enum $MOp $generics {
|
||||
$Variant($ty),
|
||||
}
|
||||
})+
|
||||
};
|
||||
(
|
||||
@impl_variants
|
||||
#[impl_mop_into = false]
|
||||
enum $MOp:ident $generics:tt {
|
||||
$($Variant:ident($ty:ty),)+
|
||||
}
|
||||
) => {};
|
||||
(
|
||||
@impl_variant
|
||||
enum $MOp:ident[$DestReg:ident: Type, $SrcRegWidth:ident: Size $(, #[Size(get_size = $sizes_get_size:expr)] $Sizes:ident: Size)*] {
|
||||
$Variant:ident($ty:ty),
|
||||
}
|
||||
) => {
|
||||
impl<$DestReg: Type, $SrcRegWidth: Size, Target: MOpTrait, $($Sizes: Size,)*> MOpInto<Target> for $ty
|
||||
where
|
||||
$MOp<$DestReg, $SrcRegWidth, $($Sizes,)*>: MOpInto<Target>
|
||||
{
|
||||
fn mop_into_ty(self) -> Target {
|
||||
MOpInto::mop_into_ty($MOp[MOpTrait::dest_reg_ty(self)][MOpTrait::src_reg_width(self)]$([$sizes_get_size(self)])*)
|
||||
}
|
||||
fn mop_into(this: Expr<Self>) -> Expr<Target> {
|
||||
MOpInto::mop_into(MOpInto::<$MOp<$DestReg, $SrcRegWidth, $($Sizes,)*>>::mop_into_ty(Expr::ty(this)).$Variant(this))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use mop_enum;
|
||||
|
@ -666,6 +724,7 @@ common_mop_struct! {
|
|||
}
|
||||
|
||||
mop_enum! {
|
||||
#[impl_mop_into = true]
|
||||
#[hdl]
|
||||
pub enum AluBranchMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||
AddSub(AddSubMOp<DestReg, SrcRegWidth, ConstUsize<3>>),
|
||||
|
@ -693,6 +752,7 @@ common_mop_struct! {
|
|||
}
|
||||
|
||||
mop_enum! {
|
||||
#[impl_mop_into = true]
|
||||
#[hdl]
|
||||
pub enum L2RegisterFileMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||
ReadL2Reg(ReadL2RegMOp<DestReg, SrcRegWidth>),
|
||||
|
@ -728,6 +788,7 @@ common_mop_struct! {
|
|||
}
|
||||
|
||||
mop_enum! {
|
||||
#[impl_mop_into = true]
|
||||
#[hdl]
|
||||
pub enum LoadStoreMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||
Load(CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, ConstUsize<0>>),
|
||||
|
@ -735,6 +796,15 @@ mop_enum! {
|
|||
}
|
||||
}
|
||||
|
||||
common_mop_struct! {
|
||||
#[mapped(<NewDestReg, NewSrcRegWidth> MoveRegMOp<NewDestReg, NewSrcRegWidth>)]
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct MoveRegMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||
#[common]
|
||||
pub common: CommonMOp<ConstUsize<2>, DestReg, SrcRegWidth, ConstUsize<1>>,
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl(cmp_eq)]
|
||||
/// 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
|
||||
|
@ -1014,4 +1084,12 @@ impl MOpDestReg {
|
|||
}
|
||||
|
||||
#[hdl]
|
||||
pub type MOp = UnitMOp<MOpDestReg, ConstUsize<{ MOpRegNum::WIDTH }>>;
|
||||
pub type MOp = UnitMOp<
|
||||
MOpDestReg,
|
||||
ConstUsize<{ MOpRegNum::WIDTH }>,
|
||||
MoveRegMOp<MOpDestReg, ConstUsize<{ MOpRegNum::WIDTH }>>,
|
||||
>;
|
||||
|
||||
#[hdl]
|
||||
pub type RenamedMOp<DestReg: Type, SrcRegWidth: Size> =
|
||||
UnitMOp<DestReg, SrcRegWidth, L2RegisterFileMOp<DestReg, SrcRegWidth>>;
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
use crate::{
|
||||
config::CpuConfig,
|
||||
instruction::{
|
||||
MOp, MOpDestReg, MOpRegNum, MOpTrait, PRegNum, RenameTableName, UnitOutRegNum,
|
||||
MOp, MOpDestReg, MOpRegNum, MOpTrait, MoveRegMOp, PRegNum, RenameTableName, UnitOutRegNum,
|
||||
COMMON_MOP_SRC_LEN,
|
||||
},
|
||||
unit::{
|
||||
unit_base::{UnitForwardingInfo, UnitInput},
|
||||
GlobalState, TrapData, UnitOutput, UnitOutputWrite, UnitResult, UnitResultCompleted,
|
||||
UnitTrait,
|
||||
GlobalState, TrapData, UnitMOp, UnitOutput, UnitOutputWrite, UnitResult,
|
||||
UnitResultCompleted, UnitTrait,
|
||||
},
|
||||
util::tree_reduce::tree_reduce_with_state,
|
||||
};
|
||||
|
@ -234,7 +234,7 @@ pub fn reg_alloc(config: &CpuConfig) {
|
|||
wire(Array[HdlOption[UInt[config.unit_num_width()]]][config.fetch_width.get()]);
|
||||
#[hdl]
|
||||
let renamed_mops =
|
||||
wire(Array[HdlOption[UnitInput[config.unit_mop_in_unit()]]][config.fetch_width.get()]);
|
||||
wire(Array[HdlOption[UnitInput[config.renamed_mop_in_unit()]]][config.fetch_width.get()]);
|
||||
#[hdl]
|
||||
let renamed_mops_out_reg = wire(Array[HdlOption[config.p_reg_num()]][config.fetch_width.get()]);
|
||||
for fetch_index in 0..config.fetch_width.get() {
|
||||
|
@ -358,27 +358,35 @@ pub fn reg_alloc(config: &CpuConfig) {
|
|||
#[hdl]
|
||||
if let HdlSome(renamed_mop_out_reg) = renamed_mops_out_reg[fetch_index] {
|
||||
let dest_reg = MOpTrait::dest_reg(decoded_insn.mop);
|
||||
connect(
|
||||
renamed_mops[fetch_index],
|
||||
HdlSome(
|
||||
#[hdl]
|
||||
UnitInput::<_> {
|
||||
mop: MOpTrait::map_regs(
|
||||
decoded_insn.mop,
|
||||
renamed_mop_out_reg.unit_out_reg,
|
||||
config.p_reg_num_width(),
|
||||
&mut |src_reg, src_index| {
|
||||
connect(
|
||||
rename_table_read_ports[src_index].addr,
|
||||
#[hdl]
|
||||
MOpRegNum { value: src_reg },
|
||||
);
|
||||
rename_table_read_ports[src_index].data.cast_to_bits()
|
||||
},
|
||||
),
|
||||
pc: decoded_insn.pc,
|
||||
let renamed_mop = UnitMOp::try_with_transformed_move_op(
|
||||
MOpTrait::map_regs(
|
||||
decoded_insn.mop,
|
||||
renamed_mop_out_reg.unit_out_reg,
|
||||
config.p_reg_num_width(),
|
||||
&mut |src_reg, src_index| {
|
||||
connect(
|
||||
rename_table_read_ports[src_index].addr,
|
||||
#[hdl]
|
||||
MOpRegNum { value: src_reg },
|
||||
);
|
||||
rename_table_read_ports[src_index].data.cast_to_bits()
|
||||
},
|
||||
),
|
||||
config.renamed_mop_in_unit().TransformedMove,
|
||||
|renamed_mop, renamed_move_op: Expr<MoveRegMOp<_, _>>| {
|
||||
// TODO: finish handling MoveRegMOp
|
||||
connect(renamed_mop, Expr::ty(renamed_mop).HdlNone());
|
||||
},
|
||||
);
|
||||
connect(
|
||||
renamed_mops[fetch_index],
|
||||
HdlOption::map(renamed_mop, |mop| {
|
||||
#[hdl]
|
||||
UnitInput::<_> {
|
||||
mop,
|
||||
pc: decoded_insn.pc,
|
||||
}
|
||||
}),
|
||||
);
|
||||
for (reg, reg_kind) in MOpDestReg::regs(dest_reg)
|
||||
.into_iter()
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
use crate::{
|
||||
config::CpuConfig,
|
||||
instruction::{
|
||||
mop_enum, AluBranchMOp, L2RegisterFileMOp, LoadStoreMOp, MOpInto, MOpTrait, UnitOutRegNum,
|
||||
mop_enum, AluBranchMOp, LoadStoreMOp, MOp, MOpDestReg, MOpInto, MOpRegNum, MOpTrait,
|
||||
RenamedMOp, UnitOutRegNum,
|
||||
},
|
||||
register::{FlagsMode, PRegValue},
|
||||
unit::unit_base::UnitToRegAlloc,
|
||||
|
@ -24,8 +25,9 @@ macro_rules! all_units {
|
|||
#[unit_kind = $UnitKind:ident]
|
||||
#[hdl]
|
||||
$(#[$enum_meta:meta])*
|
||||
$vis:vis enum $UnitMOpEnum:ident<$DestReg:ident: Type, $SrcRegWidth:ident: Size> {
|
||||
$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]
|
||||
$(#[$variant_meta:meta])*
|
||||
|
@ -70,9 +72,10 @@ macro_rules! all_units {
|
|||
}
|
||||
|
||||
mop_enum! {
|
||||
#[impl_mop_into = false]
|
||||
#[hdl]
|
||||
$(#[$enum_meta])*
|
||||
$vis enum $UnitMOpEnum<$DestReg: Type, $SrcRegWidth: Size> {
|
||||
$vis enum $UnitMOpEnum<$DestReg: Type, $SrcRegWidth: Size, #[MOp(get_ty = $transformed_move_op_get_ty)] $TransformedMoveOp: Type> {
|
||||
$(
|
||||
$(#[$variant_meta])*
|
||||
$Unit($Op),
|
||||
|
@ -80,14 +83,14 @@ macro_rules! all_units {
|
|||
}
|
||||
}
|
||||
|
||||
impl<$DestReg: Type, $SrcRegWidth: Size> $UnitMOpEnum<$DestReg, $SrcRegWidth> {
|
||||
impl<$DestReg: Type, $SrcRegWidth: Size, $TransformedMoveOp: Type> $UnitMOpEnum<$DestReg, $SrcRegWidth, $TransformedMoveOp> {
|
||||
#[hdl]
|
||||
$vis fn kind(expr: impl ToExpr<Type = Self>) -> Expr<$HdlUnitKind> {
|
||||
#[hdl]
|
||||
let unit_kind = wire();
|
||||
#[hdl]
|
||||
match expr {
|
||||
$($UnitMOpEnum::<_, _>::$Unit(_) => connect(unit_kind, $HdlUnitKind.$Unit()),)*
|
||||
$(Self::$Unit(_) => connect(unit_kind, $HdlUnitKind.$Unit()),)*
|
||||
}
|
||||
unit_kind
|
||||
}
|
||||
|
@ -100,12 +103,29 @@ macro_rules! all_units {
|
|||
let $extract = wire(HdlOption[ty.$Unit]);
|
||||
connect($extract, HdlOption[ty.$Unit].HdlNone());
|
||||
#[hdl]
|
||||
if let $UnitMOpEnum::<_, _>::$Unit(v) = expr {
|
||||
if let Self::$Unit(v) = expr {
|
||||
connect($extract, HdlSome(v));
|
||||
}
|
||||
$extract
|
||||
}
|
||||
)*
|
||||
$vis fn with_transformed_move_op_ty<T>(self, new_transformed_move_op_ty: T) -> $UnitMOpEnum<$DestReg, $SrcRegWidth, T>
|
||||
where
|
||||
T: MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
|
||||
$TransformedMoveOp: MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
|
||||
{
|
||||
$UnitMOpEnum[self.dest_reg_ty()][self.src_reg_width()][new_transformed_move_op_ty]
|
||||
}
|
||||
}
|
||||
|
||||
all_units! {
|
||||
@split_by_transformed_move
|
||||
$vis enum $UnitMOpEnum<$DestReg: Type, $SrcRegWidth: Size, $TransformedMoveOp: Type> {
|
||||
$(
|
||||
$(#[transformed_move $($transformed_move)*])?
|
||||
$Unit($Op),
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl CpuConfig {
|
||||
|
@ -123,19 +143,105 @@ macro_rules! all_units {
|
|||
}
|
||||
}
|
||||
};
|
||||
(
|
||||
@split_by_transformed_move
|
||||
$vis:vis enum $UnitMOpEnum:ident<$DestReg:ident: Type, $SrcRegWidth:ident: Size, $TransformedMoveOp:ident: Type> {
|
||||
$($BeforeUnit:ident($BeforeOp:ty),)*
|
||||
#[transformed_move]
|
||||
$TransformedMove:ident($TransformedMoveOp2:ty),
|
||||
$($AfterUnit:ident($AfterOp:ty),)*
|
||||
}
|
||||
) => {
|
||||
impl<$DestReg: Type, $SrcRegWidth: Size, $TransformedMoveOp: Type> $UnitMOpEnum<$DestReg, $SrcRegWidth, $TransformedMoveOp> {
|
||||
#[hdl]
|
||||
$vis fn try_with_transformed_move_op<T>(
|
||||
this: impl ToExpr<Type = Self>,
|
||||
new_transformed_move_op_ty: T,
|
||||
connect_transformed_move_op: impl FnOnce(Expr<HdlOption<$UnitMOpEnum<$DestReg, $SrcRegWidth, T>>>, Expr<$TransformedMoveOp>),
|
||||
) -> Expr<HdlOption<$UnitMOpEnum<$DestReg, $SrcRegWidth, T>>>
|
||||
where
|
||||
T: MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
|
||||
$TransformedMoveOp: MOpTrait<DestReg = $DestReg, SrcRegWidth = $SrcRegWidth>,
|
||||
{
|
||||
let this = this.to_expr();
|
||||
let new_ty = Expr::ty(this).with_transformed_move_op_ty(new_transformed_move_op_ty);
|
||||
#[hdl]
|
||||
let with_transformed_move_op = wire(HdlOption[new_ty]);
|
||||
connect(with_transformed_move_op, Expr::ty(with_transformed_move_op).HdlNone());
|
||||
// workaround #[hdl] match expanding to a loop, so you can't move variables in it
|
||||
let mut connect_transformed_move_op = Some(connect_transformed_move_op);
|
||||
#[hdl]
|
||||
match this {
|
||||
$(Self::$BeforeUnit(unit) => connect(with_transformed_move_op, HdlSome(new_ty.$BeforeUnit(unit))),)*
|
||||
Self::$TransformedMove(unit) => connect_transformed_move_op.take().expect("only reached once")(with_transformed_move_op, unit),
|
||||
$(Self::$AfterUnit(unit) => connect(with_transformed_move_op, HdlSome(new_ty.$AfterUnit(unit))),)*
|
||||
}
|
||||
with_transformed_move_op
|
||||
}
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
#[hdl]
|
||||
type $DestReg = MOpDestReg;
|
||||
type $SrcRegWidth = ConstUsize<{ MOpRegNum::WIDTH }>;
|
||||
|
||||
$(impl MOpInto<MOp> for $BeforeOp {
|
||||
fn mop_into_ty(self) -> MOp {
|
||||
MOp
|
||||
}
|
||||
fn mop_into(this: Expr<Self>) -> Expr<MOp> {
|
||||
MOp.$BeforeUnit(this)
|
||||
}
|
||||
})*
|
||||
|
||||
$(impl MOpInto<MOp> for $AfterOp {
|
||||
fn mop_into_ty(self) -> MOp {
|
||||
MOp
|
||||
}
|
||||
fn mop_into(this: Expr<Self>) -> Expr<MOp> {
|
||||
MOp.$AfterUnit(this)
|
||||
}
|
||||
})*
|
||||
};
|
||||
|
||||
$(impl<$DestReg: Type, $SrcRegWidth: Size> MOpInto<RenamedMOp<$DestReg, $SrcRegWidth>> for $BeforeOp {
|
||||
fn mop_into_ty(self) -> RenamedMOp<$DestReg, $SrcRegWidth> {
|
||||
RenamedMOp[MOpTrait::dest_reg_ty(self)][MOpTrait::src_reg_width(self)]
|
||||
}
|
||||
fn mop_into(this: Expr<Self>) -> Expr<RenamedMOp<$DestReg, $SrcRegWidth>> {
|
||||
MOpInto::<RenamedMOp<$DestReg, $SrcRegWidth>>::mop_into_ty(Expr::ty(this)).$BeforeUnit(this)
|
||||
}
|
||||
})*
|
||||
|
||||
$(impl<$DestReg: Type, $SrcRegWidth: Size> MOpInto<RenamedMOp<$DestReg, $SrcRegWidth>> for $AfterOp {
|
||||
fn mop_into_ty(self) -> RenamedMOp<$DestReg, $SrcRegWidth> {
|
||||
RenamedMOp[MOpTrait::dest_reg_ty(self)][MOpTrait::src_reg_width(self)]
|
||||
}
|
||||
fn mop_into(this: Expr<Self>) -> Expr<RenamedMOp<$DestReg, $SrcRegWidth>> {
|
||||
MOpInto::<RenamedMOp<$DestReg, $SrcRegWidth>>::mop_into_ty(Expr::ty(this)).$AfterUnit(this)
|
||||
}
|
||||
})*
|
||||
};
|
||||
}
|
||||
|
||||
all_units! {
|
||||
#[hdl_unit_kind = HdlUnitKind]
|
||||
#[unit_kind = UnitKind]
|
||||
#[hdl]
|
||||
pub enum UnitMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||
pub enum UnitMOp<
|
||||
DestReg: Type,
|
||||
SrcRegWidth: Size,
|
||||
#[MOp(get_ty = |this: UnitMOp<DestReg, SrcRegWidth, TransformedMoveOp>, new_dest_reg, new_src_reg_width| {
|
||||
this.TransformedMove.mapped_ty(new_dest_reg, new_src_reg_width)
|
||||
})] TransformedMoveOp: Type
|
||||
> {
|
||||
#[create_dyn_unit_fn = |config, unit_index| alu_branch::AluBranch::new(config, unit_index).to_dyn()]
|
||||
#[extract = alu_branch_mop]
|
||||
AluBranch(AluBranchMOp<DestReg, SrcRegWidth>),
|
||||
#[transformed_move]
|
||||
#[create_dyn_unit_fn = |config, unit_index| todo!()]
|
||||
#[extract = l2_register_file_mop]
|
||||
L2RegisterFile(L2RegisterFileMOp<DestReg, SrcRegWidth>),
|
||||
#[extract = transformed_move_mop]
|
||||
TransformedMove(TransformedMoveOp),
|
||||
#[create_dyn_unit_fn = |config, unit_index| todo!()]
|
||||
#[extract = load_store_mop]
|
||||
LoadStore(LoadStoreMOp<DestReg, SrcRegWidth>),
|
||||
|
@ -208,7 +314,7 @@ pub trait UnitTrait:
|
|||
|
||||
fn extract_mop(
|
||||
&self,
|
||||
mop: Expr<UnitMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
) -> Expr<HdlOption<Self::MOp>>;
|
||||
|
||||
fn module(&self) -> Interned<Module<Self::Type>>;
|
||||
|
@ -266,7 +372,7 @@ impl UnitTrait for DynUnit {
|
|||
|
||||
fn extract_mop(
|
||||
&self,
|
||||
mop: Expr<UnitMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
) -> Expr<HdlOption<Self::MOp>> {
|
||||
self.unit.extract_mop(mop)
|
||||
}
|
||||
|
@ -321,7 +427,7 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T
|
|||
|
||||
fn extract_mop(
|
||||
&self,
|
||||
mop: Expr<UnitMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
) -> Expr<HdlOption<Self::MOp>> {
|
||||
Expr::from_enum(Expr::as_enum(self.0.extract_mop(mop)))
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
config::CpuConfig,
|
||||
instruction::{
|
||||
AddSubMOp, AluBranchMOp, AluCommonMOp, CommonMOp, LogicalMOp, MOpTrait, OutputIntegerMode,
|
||||
UnitOutRegNum, COMMON_MOP_SRC_LEN,
|
||||
RenamedMOp, UnitOutRegNum, COMMON_MOP_SRC_LEN,
|
||||
},
|
||||
register::{FlagsMode, PRegFlagsPowerISA, PRegFlagsX86, PRegValue},
|
||||
unit::{
|
||||
|
@ -381,7 +381,7 @@ impl UnitTrait for AluBranch {
|
|||
|
||||
fn extract_mop(
|
||||
&self,
|
||||
mop: Expr<UnitMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||
) -> Expr<HdlOption<Self::MOp>> {
|
||||
UnitMOp::alu_branch_mop(mop)
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue