Compare commits
No commits in common. "3f6e5cc6004e888405f17386a877bd3ded47a4b7" and "2b7e7e4946c0de8fee10b7daf2d637b00a662d62" have entirely different histories.
3f6e5cc600
...
2b7e7e4946
11 changed files with 8534 additions and 18337 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -300,7 +300,7 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fayalite"
|
name = "fayalite"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#3458c21f442652713f2f531f02d747d43550562c"
|
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#cdd84953d076cd9a83db50e9d11a63b6181b0976"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitvec",
|
"bitvec",
|
||||||
"blake3",
|
"blake3",
|
||||||
|
|
@ -325,7 +325,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fayalite-proc-macros"
|
name = "fayalite-proc-macros"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#3458c21f442652713f2f531f02d747d43550562c"
|
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#cdd84953d076cd9a83db50e9d11a63b6181b0976"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fayalite-proc-macros-impl",
|
"fayalite-proc-macros-impl",
|
||||||
]
|
]
|
||||||
|
|
@ -333,7 +333,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fayalite-proc-macros-impl"
|
name = "fayalite-proc-macros-impl"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#3458c21f442652713f2f531f02d747d43550562c"
|
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#cdd84953d076cd9a83db50e9d11a63b6181b0976"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base16ct",
|
"base16ct",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
|
|
@ -348,7 +348,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fayalite-visit-gen"
|
name = "fayalite-visit-gen"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#3458c21f442652713f2f531f02d747d43550562c"
|
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#cdd84953d076cd9a83db50e9d11a63b6181b0976"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"prettyplease",
|
"prettyplease",
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
use crate::{
|
use crate::{
|
||||||
instruction::{MOpTrait, PRegNum, UnitNum, UnitOutRegNum, CONST_ZERO_UNIT_NUM},
|
instruction::{PRegNum, UnitNum, UnitOutRegNum, CONST_ZERO_UNIT_NUM},
|
||||||
unit::{
|
unit::{unit_base::UnitForwardingInfo, UnitCancelInput, UnitKind, UnitMOp, UnitOutputWrite},
|
||||||
unit_base::{UnitForwardingInfo, UnitToRegAlloc},
|
|
||||||
UnitCancelInput, UnitKind, UnitMOp, UnitOutputWrite,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use fayalite::prelude::*;
|
use fayalite::prelude::*;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
|
|
@ -98,20 +95,4 @@ impl CpuConfig {
|
||||||
.max_in_flight
|
.max_in_flight
|
||||||
.unwrap_or(self.default_unit_max_in_flight)
|
.unwrap_or(self.default_unit_max_in_flight)
|
||||||
}
|
}
|
||||||
pub fn unit_to_reg_alloc<
|
|
||||||
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>, SrcRegWidth = DynSize>,
|
|
||||||
ExtraOut: Type,
|
|
||||||
>(
|
|
||||||
&self,
|
|
||||||
mop_ty: MOp,
|
|
||||||
extra_out_ty: ExtraOut,
|
|
||||||
) -> UnitToRegAlloc<MOp, ExtraOut, DynSize, DynSize, DynSize> {
|
|
||||||
assert_eq!(
|
|
||||||
mop_ty.dest_reg_ty(),
|
|
||||||
self.unit_out_reg_num(),
|
|
||||||
"inconsistent types",
|
|
||||||
);
|
|
||||||
UnitToRegAlloc[mop_ty][extra_out_ty][self.unit_num_width()][self.out_reg_num_width]
|
|
||||||
[self.non_const_unit_nums().len()]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,7 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
use crate::{unit::UnitMOp, util::range_u32_len};
|
use crate::{unit::UnitMOp, util::range_u32_len};
|
||||||
use fayalite::{
|
use fayalite::{expr::ops::ArrayLiteral, intern::Interned, prelude::*};
|
||||||
expr::ops::{ArrayLiteral, ExprPartialEq},
|
|
||||||
intern::Interned,
|
|
||||||
prelude::*,
|
|
||||||
};
|
|
||||||
use std::{fmt, marker::PhantomData, ops::Range};
|
use std::{fmt, marker::PhantomData, ops::Range};
|
||||||
|
|
||||||
pub mod power_isa;
|
pub mod power_isa;
|
||||||
|
|
@ -16,26 +12,10 @@ pub trait MOpTrait: Type {
|
||||||
type SrcRegWidth: Size;
|
type SrcRegWidth: Size;
|
||||||
fn dest_reg_ty(self) -> Self::DestReg;
|
fn dest_reg_ty(self) -> Self::DestReg;
|
||||||
fn dest_reg(input: impl ToExpr<Type = Self>) -> Expr<Self::DestReg>;
|
fn dest_reg(input: impl ToExpr<Type = Self>) -> Expr<Self::DestReg>;
|
||||||
fn src_reg_width(self) -> <Self::SrcRegWidth as Size>::SizeType;
|
|
||||||
fn src_reg_ty(self) -> UIntType<Self::SrcRegWidth> {
|
|
||||||
UInt[self.src_reg_width()]
|
|
||||||
}
|
|
||||||
fn src_regs_ty(self) -> Array<UIntType<Self::SrcRegWidth>, { COMMON_MOP_SRC_LEN }> {
|
|
||||||
Array[self.src_reg_ty()][ConstUsize::<{ COMMON_MOP_SRC_LEN }>]
|
|
||||||
}
|
|
||||||
fn for_each_src_reg(
|
fn for_each_src_reg(
|
||||||
input: impl ToExpr<Type = Self>,
|
input: impl ToExpr<Type = Self>,
|
||||||
f: &mut impl FnMut(Expr<UIntType<Self::SrcRegWidth>>, usize),
|
f: &mut impl FnMut(Expr<UIntType<Self::SrcRegWidth>>, usize),
|
||||||
);
|
);
|
||||||
fn connect_src_regs(
|
|
||||||
input: impl ToExpr<Type = Self>,
|
|
||||||
src_regs: impl ToExpr<Type = Array<UIntType<Self::SrcRegWidth>, { COMMON_MOP_SRC_LEN }>>,
|
|
||||||
) {
|
|
||||||
let src_regs = src_regs.to_expr();
|
|
||||||
Self::for_each_src_reg(input.to_expr(), &mut |src_reg, index| {
|
|
||||||
connect(src_regs[index], src_reg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
fn mapped_ty<NewDestReg: Type, NewSrcRegWidth: Size>(
|
fn mapped_ty<NewDestReg: Type, NewSrcRegWidth: Size>(
|
||||||
self,
|
self,
|
||||||
new_dest_reg: NewDestReg,
|
new_dest_reg: NewDestReg,
|
||||||
|
|
@ -87,9 +67,6 @@ impl<T: CommonMOpTrait> MOpTrait for T {
|
||||||
fn dest_reg(input: impl ToExpr<Type = Self>) -> Expr<Self::DestReg> {
|
fn dest_reg(input: impl ToExpr<Type = Self>) -> Expr<Self::DestReg> {
|
||||||
T::common_mop(input).dest
|
T::common_mop(input).dest
|
||||||
}
|
}
|
||||||
fn src_reg_width(self) -> <Self::SrcRegWidth as Size>::SizeType {
|
|
||||||
self.common_mop_ty().src.element().width
|
|
||||||
}
|
|
||||||
fn for_each_src_reg(
|
fn for_each_src_reg(
|
||||||
input: impl ToExpr<Type = Self>,
|
input: impl ToExpr<Type = Self>,
|
||||||
f: &mut impl FnMut(Expr<UIntType<Self::SrcRegWidth>>, usize),
|
f: &mut impl FnMut(Expr<UIntType<Self::SrcRegWidth>>, usize),
|
||||||
|
|
@ -152,23 +129,13 @@ pub enum OutputIntegerMode {
|
||||||
SignExt8,
|
SignExt8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExprPartialEq<Self> for OutputIntegerMode {
|
|
||||||
fn cmp_eq(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
|
|
||||||
lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cmp_ne(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
|
|
||||||
lhs.cast_to_bits().cmp_ne(rhs.cast_to_bits())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const MOP_IMM_WIDTH: usize = 34;
|
pub const MOP_IMM_WIDTH: usize = 34;
|
||||||
pub const MOP_MIN_REG_WIDTH: usize = 8;
|
pub const MOP_MIN_REG_WIDTH: usize = 8;
|
||||||
pub const COMMON_MOP_SRC_LEN: usize = 3;
|
pub const COMMON_MOP_SRC_LEN: usize = 3;
|
||||||
pub const COMMON_MOP_MIN_SRC_LEN_WITH_FULL_IMM: usize = 2;
|
pub const COMMON_MOP_MIN_SRC_LEN_WITH_FULL_IMM: usize = 2;
|
||||||
pub const COMMON_MOP_IMM_LOW_WIDTH: usize = CommonMOpWithMaxSrcCount::IMM_WIDTH - 1;
|
pub const COMMON_MOP_IMM_LOW_WIDTH: usize = CommonMOpWithMaxSrcCount::IMM_WIDTH - 1;
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct CommonMOp<PrefixPad: KnownSize, DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
pub struct CommonMOp<PrefixPad: KnownSize, DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||||
pub prefix_pad: UIntType<PrefixPad>,
|
pub prefix_pad: UIntType<PrefixPad>,
|
||||||
pub dest: DestReg,
|
pub dest: DestReg,
|
||||||
|
|
@ -214,7 +181,7 @@ impl<PrefixPad: KnownSize, DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct CommonMOpImmParts<ImmInSrcCount: Size> {
|
pub struct CommonMOpImmParts<ImmInSrcCount: Size> {
|
||||||
// fields must be in this exact order
|
// fields must be in this exact order
|
||||||
pub imm_low: UInt<{ COMMON_MOP_IMM_LOW_WIDTH }>,
|
pub imm_low: UInt<{ COMMON_MOP_IMM_LOW_WIDTH }>,
|
||||||
|
|
@ -443,9 +410,6 @@ macro_rules! mop_enum {
|
||||||
}
|
}
|
||||||
dest_reg
|
dest_reg
|
||||||
}
|
}
|
||||||
fn src_reg_width(self) -> <Self::SrcRegWidth as Size>::SizeType {
|
|
||||||
self.$FirstVariant.src_reg_width()
|
|
||||||
}
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn for_each_src_reg(
|
fn for_each_src_reg(
|
||||||
input: impl ToExpr<Type = Self>,
|
input: impl ToExpr<Type = Self>,
|
||||||
|
|
@ -494,7 +458,7 @@ pub(crate) use mop_enum;
|
||||||
|
|
||||||
common_mop_struct! {
|
common_mop_struct! {
|
||||||
#[mapped(<NewDestReg, NewSrcRegWidth> AluCommonMOp<NewDestReg, NewSrcRegWidth, SrcCount>)]
|
#[mapped(<NewDestReg, NewSrcRegWidth> AluCommonMOp<NewDestReg, NewSrcRegWidth, SrcCount>)]
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct AluCommonMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
pub struct AluCommonMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||||
#[common]
|
#[common]
|
||||||
pub common: CommonMOp<ConstUsize<0>, DestReg, SrcRegWidth, SrcCount>,
|
pub common: CommonMOp<ConstUsize<0>, DestReg, SrcRegWidth, SrcCount>,
|
||||||
|
|
@ -504,7 +468,7 @@ common_mop_struct! {
|
||||||
|
|
||||||
common_mop_struct! {
|
common_mop_struct! {
|
||||||
#[mapped(<NewDestReg, NewSrcRegWidth> AddSubMOp<NewDestReg, NewSrcRegWidth, SrcCount>)]
|
#[mapped(<NewDestReg, NewSrcRegWidth> AddSubMOp<NewDestReg, NewSrcRegWidth, SrcCount>)]
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct AddSubMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
pub struct AddSubMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||||
#[common]
|
#[common]
|
||||||
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, SrcCount>,
|
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, SrcCount>,
|
||||||
|
|
@ -517,7 +481,7 @@ common_mop_struct! {
|
||||||
|
|
||||||
common_mop_struct! {
|
common_mop_struct! {
|
||||||
#[mapped(<NewDestReg, NewSrcRegWidth> LogicalMOp<NewDestReg, NewSrcRegWidth>)]
|
#[mapped(<NewDestReg, NewSrcRegWidth> LogicalMOp<NewDestReg, NewSrcRegWidth>)]
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct LogicalMOp<DestReg: Type, SrcRegWidth: Size> {
|
pub struct LogicalMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||||
#[common]
|
#[common]
|
||||||
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, ConstUsize<2>>,
|
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, ConstUsize<2>>,
|
||||||
|
|
@ -527,7 +491,7 @@ common_mop_struct! {
|
||||||
|
|
||||||
common_mop_struct! {
|
common_mop_struct! {
|
||||||
#[mapped(<NewDestReg, NewSrcRegWidth> BranchMOp<NewDestReg, NewSrcRegWidth>)]
|
#[mapped(<NewDestReg, NewSrcRegWidth> BranchMOp<NewDestReg, NewSrcRegWidth>)]
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct BranchMOp<DestReg: Type, SrcRegWidth: Size> {
|
pub struct BranchMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||||
#[common]
|
#[common]
|
||||||
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, ConstUsize<2>>,
|
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, ConstUsize<2>>,
|
||||||
|
|
@ -546,7 +510,7 @@ mop_enum! {
|
||||||
|
|
||||||
common_mop_struct! {
|
common_mop_struct! {
|
||||||
#[mapped(<NewDestReg, NewSrcRegWidth> ReadL2RegMOp<NewDestReg, NewSrcRegWidth>)]
|
#[mapped(<NewDestReg, NewSrcRegWidth> ReadL2RegMOp<NewDestReg, NewSrcRegWidth>)]
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct ReadL2RegMOp<DestReg: Type, SrcRegWidth: Size> {
|
pub struct ReadL2RegMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||||
#[common]
|
#[common]
|
||||||
pub common: CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, ConstUsize<0>>,
|
pub common: CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, ConstUsize<0>>,
|
||||||
|
|
@ -555,7 +519,7 @@ common_mop_struct! {
|
||||||
|
|
||||||
common_mop_struct! {
|
common_mop_struct! {
|
||||||
#[mapped(<NewDestReg, NewSrcRegWidth> WriteL2RegMOp<NewDestReg, NewSrcRegWidth>)]
|
#[mapped(<NewDestReg, NewSrcRegWidth> WriteL2RegMOp<NewDestReg, NewSrcRegWidth>)]
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct WriteL2RegMOp<DestReg: Type, SrcRegWidth: Size> {
|
pub struct WriteL2RegMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||||
#[common]
|
#[common]
|
||||||
pub common: CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, ConstUsize<1>>,
|
pub common: CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, ConstUsize<1>>,
|
||||||
|
|
@ -572,7 +536,7 @@ mop_enum! {
|
||||||
|
|
||||||
common_mop_struct! {
|
common_mop_struct! {
|
||||||
#[mapped(<NewDestReg, NewSrcRegWidth> LoadStoreCommonMOp<NewDestReg, NewSrcRegWidth, SrcCount>)]
|
#[mapped(<NewDestReg, NewSrcRegWidth> LoadStoreCommonMOp<NewDestReg, NewSrcRegWidth, SrcCount>)]
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct LoadStoreCommonMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
pub struct LoadStoreCommonMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||||
#[common]
|
#[common]
|
||||||
pub common: CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, SrcCount>,
|
pub common: CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, SrcCount>,
|
||||||
|
|
@ -581,7 +545,7 @@ common_mop_struct! {
|
||||||
|
|
||||||
common_mop_struct! {
|
common_mop_struct! {
|
||||||
#[mapped(<NewDestReg, NewSrcRegWidth> LoadMOp<NewDestReg, NewSrcRegWidth>)]
|
#[mapped(<NewDestReg, NewSrcRegWidth> LoadMOp<NewDestReg, NewSrcRegWidth>)]
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct LoadMOp<DestReg: Type, SrcRegWidth: Size> {
|
pub struct LoadMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||||
#[common]
|
#[common]
|
||||||
pub load_store_common: LoadStoreCommonMOp<DestReg, SrcRegWidth, ConstUsize<1>>,
|
pub load_store_common: LoadStoreCommonMOp<DestReg, SrcRegWidth, ConstUsize<1>>,
|
||||||
|
|
@ -590,7 +554,7 @@ common_mop_struct! {
|
||||||
|
|
||||||
common_mop_struct! {
|
common_mop_struct! {
|
||||||
#[mapped(<NewDestReg, NewSrcRegWidth> StoreMOp<NewDestReg, NewSrcRegWidth>)]
|
#[mapped(<NewDestReg, NewSrcRegWidth> StoreMOp<NewDestReg, NewSrcRegWidth>)]
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct StoreMOp<DestReg: Type, SrcRegWidth: Size> {
|
pub struct StoreMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||||
#[common]
|
#[common]
|
||||||
pub load_store_common: LoadStoreCommonMOp<DestReg, SrcRegWidth, ConstUsize<2>>,
|
pub load_store_common: LoadStoreCommonMOp<DestReg, SrcRegWidth, ConstUsize<2>>,
|
||||||
|
|
@ -605,7 +569,7 @@ mop_enum! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
/// there may be more than one unit of a given kind, so UnitNum is not the same as UnitKind.
|
/// 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
|
/// zero is used for built-in constants, such as the zero register
|
||||||
pub struct UnitNum<Width: Size> {
|
pub struct UnitNum<Width: Size> {
|
||||||
|
|
@ -653,12 +617,12 @@ impl<Width: Size> UnitNum<Width> {
|
||||||
|
|
||||||
pub const CONST_ZERO_UNIT_NUM: usize = 0;
|
pub const CONST_ZERO_UNIT_NUM: usize = 0;
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct UnitOutRegNum<Width: Size> {
|
pub struct UnitOutRegNum<Width: Size> {
|
||||||
pub value: UIntType<Width>,
|
pub value: UIntType<Width>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
/// Physical Register Number -- registers in the CPU's backend
|
/// Physical Register Number -- registers in the CPU's backend
|
||||||
pub struct PRegNum<UnitNumWidth: Size, OutRegNumWidth: Size> {
|
pub struct PRegNum<UnitNumWidth: Size, OutRegNumWidth: Size> {
|
||||||
pub unit_num: UnitNum<UnitNumWidth>,
|
pub unit_num: UnitNum<UnitNumWidth>,
|
||||||
|
|
@ -679,7 +643,7 @@ impl<UnitNumWidth: Size, OutRegNumWidth: Size> PRegNum<UnitNumWidth, OutRegNumWi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
/// µOp Register Number -- register in a micro-operation before register renaming
|
/// µOp Register Number -- register in a micro-operation before register renaming
|
||||||
#[doc(alias = "UOpRegNum")] // help you find it in the docs if you mis-spell it
|
#[doc(alias = "UOpRegNum")] // help you find it in the docs if you mis-spell it
|
||||||
#[doc(alias = "\u{B5}OpRegNum")] // micro sign
|
#[doc(alias = "\u{B5}OpRegNum")] // micro sign
|
||||||
|
|
@ -717,7 +681,7 @@ impl MOpRegNum {
|
||||||
Self::CONST_ZERO_REG_NUM + 1..Self::SPECIAL_REG_NUMS.start;
|
Self::CONST_ZERO_REG_NUM + 1..Self::SPECIAL_REG_NUMS.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
/// all the registers this instruction will write to, they are all renamed to the same physical register.
|
/// all the registers this instruction will write to, they are all renamed to the same physical register.
|
||||||
pub struct MOpDestReg {
|
pub struct MOpDestReg {
|
||||||
/// some instructions have multiple destination registers, e.g. x86 div
|
/// some instructions have multiple destination registers, e.g. x86 div
|
||||||
|
|
|
||||||
|
|
@ -4,22 +4,22 @@ use crate::{instruction::MOpRegNum, util::range_u32_nth_or_panic};
|
||||||
use fayalite::prelude::*;
|
use fayalite::prelude::*;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct PowerIsaRegNum {
|
pub struct PowerIsaRegNum {
|
||||||
pub value: UInt<5>,
|
pub value: UInt<5>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct PowerIsaFRegNum {
|
pub struct PowerIsaFRegNum {
|
||||||
pub value: UInt<5>,
|
pub value: UInt<5>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct PowerIsaCrFieldNum {
|
pub struct PowerIsaCrFieldNum {
|
||||||
pub value: UInt<3>,
|
pub value: UInt<3>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct PowerIsaCrBitNum {
|
pub struct PowerIsaCrBitNum {
|
||||||
pub cr_field: PowerIsaCrFieldNum,
|
pub cr_field: PowerIsaCrFieldNum,
|
||||||
pub bit_in_field: UInt<2>,
|
pub bit_in_field: UInt<2>,
|
||||||
|
|
|
||||||
|
|
@ -311,7 +311,7 @@ pub fn reg_alloc(config: &CpuConfig) {
|
||||||
SourceLocation::caller(),
|
SourceLocation::caller(),
|
||||||
);
|
);
|
||||||
connect(dyn_unit.cd(unit), cd);
|
connect(dyn_unit.cd(unit), cd);
|
||||||
let unit_to_reg_alloc = dyn_unit.unit_to_reg_alloc(unit);
|
let unit_input_insn = dyn_unit.input_insn(unit);
|
||||||
// TODO: handle assigning multiple instructions to a unit at a time
|
// TODO: handle assigning multiple instructions to a unit at a time
|
||||||
let assign_to_unit_at_once = NonZeroUsize::new(1).unwrap();
|
let assign_to_unit_at_once = NonZeroUsize::new(1).unwrap();
|
||||||
// TODO: handle retiring multiple instructions from a unit at a time
|
// TODO: handle retiring multiple instructions from a unit at a time
|
||||||
|
|
@ -333,8 +333,8 @@ pub fn reg_alloc(config: &CpuConfig) {
|
||||||
);
|
);
|
||||||
connect(unit_free_regs_tracker.alloc_out[0].ready, false);
|
connect(unit_free_regs_tracker.alloc_out[0].ready, false);
|
||||||
connect(
|
connect(
|
||||||
unit_to_reg_alloc.input_insn.data,
|
unit_input_insn.data,
|
||||||
Expr::ty(unit_to_reg_alloc.input_insn).data.HdlNone(),
|
Expr::ty(unit_input_insn).data.HdlNone(),
|
||||||
);
|
);
|
||||||
for fetch_index in 0..config.fetch_width.get() {
|
for fetch_index in 0..config.fetch_width.get() {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -343,7 +343,7 @@ pub fn reg_alloc(config: &CpuConfig) {
|
||||||
connect(available_units[fetch_index][unit_index], false);
|
connect(available_units[fetch_index][unit_index], false);
|
||||||
}
|
}
|
||||||
#[hdl]
|
#[hdl]
|
||||||
if !unit_to_reg_alloc.input_insn.ready {
|
if !unit_input_insn.ready {
|
||||||
// must come after to override connects in loops above
|
// must come after to override connects in loops above
|
||||||
connect(available_units[fetch_index][unit_index], false);
|
connect(available_units[fetch_index][unit_index], false);
|
||||||
}
|
}
|
||||||
|
|
@ -356,11 +356,11 @@ pub fn reg_alloc(config: &CpuConfig) {
|
||||||
if let HdlSome(renamed_mop) =
|
if let HdlSome(renamed_mop) =
|
||||||
HdlOption::and_then(renamed_mops[fetch_index], |v| dyn_unit.extract_mop(v))
|
HdlOption::and_then(renamed_mops[fetch_index], |v| dyn_unit.extract_mop(v))
|
||||||
{
|
{
|
||||||
connect(unit_to_reg_alloc.input_insn.data, HdlSome(renamed_mop));
|
connect(unit_input_insn.data, HdlSome(renamed_mop));
|
||||||
} else {
|
} else {
|
||||||
connect(
|
connect(
|
||||||
unit_to_reg_alloc.input_insn.data,
|
unit_input_insn.data,
|
||||||
HdlSome(Expr::ty(unit_to_reg_alloc.input_insn).data.HdlSome.uninit()),
|
HdlSome(Expr::ty(unit_input_insn).data.HdlSome.uninit()),
|
||||||
);
|
);
|
||||||
// FIXME: add hdl_assert(cd.clk, false.to_expr(), "");
|
// FIXME: add hdl_assert(cd.clk, false.to_expr(), "");
|
||||||
}
|
}
|
||||||
|
|
@ -387,7 +387,7 @@ pub fn reg_alloc(config: &CpuConfig) {
|
||||||
}
|
}
|
||||||
// TODO: connect outputs to other units
|
// TODO: connect outputs to other units
|
||||||
connect(
|
connect(
|
||||||
unit_to_reg_alloc.unit_forwarding_info,
|
dyn_unit.unit_forwarding_info(unit),
|
||||||
#[hdl]
|
#[hdl]
|
||||||
UnitForwardingInfo::<_, _, _> {
|
UnitForwardingInfo::<_, _, _> {
|
||||||
unit_output_writes: repeat(
|
unit_output_writes: repeat(
|
||||||
|
|
@ -397,9 +397,10 @@ pub fn reg_alloc(config: &CpuConfig) {
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
connect(dyn_unit.output(unit).ready, false);
|
||||||
// TODO: handle cancellation
|
// TODO: handle cancellation
|
||||||
connect(
|
connect(
|
||||||
unit_to_reg_alloc.cancel_input,
|
dyn_unit.cancel_input(unit).data,
|
||||||
HdlOption[config.unit_cancel_input()].HdlNone(),
|
HdlOption[config.unit_cancel_input()].HdlNone(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ pub enum FlagsMode {
|
||||||
X86(PRegFlagsX86),
|
X86(PRegFlagsX86),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct PRegFlagsPowerISA {}
|
pub struct PRegFlagsPowerISA {}
|
||||||
|
|
||||||
impl PRegFlagsPowerISA {
|
impl PRegFlagsPowerISA {
|
||||||
|
|
@ -56,7 +56,7 @@ impl PRegFlagsPowerISA {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct PRegFlagsX86 {}
|
pub struct PRegFlagsX86 {}
|
||||||
|
|
||||||
impl PRegFlagsX86 {
|
impl PRegFlagsX86 {
|
||||||
|
|
@ -100,7 +100,7 @@ impl PRegFlagsX86 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
/// this is *not* the same as any particular ISA's flags register,
|
/// this is *not* the same as any particular ISA's flags register,
|
||||||
/// on PowerISA it is a combination of some bits from XER with a single 4-bit CR field.
|
/// on PowerISA it is a combination of some bits from XER with a single 4-bit CR field.
|
||||||
///
|
///
|
||||||
|
|
@ -138,7 +138,7 @@ impl PRegFlags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
/// Unit output register's value -- a combination of an integer/fp register
|
/// Unit output register's value -- a combination of an integer/fp register
|
||||||
/// and flags register and CR field.
|
/// and flags register and CR field.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,13 @@ use crate::{
|
||||||
mop_enum, AluBranchMOp, L2RegisterFileMOp, LoadStoreMOp, MOpTrait, UnitOutRegNum,
|
mop_enum, AluBranchMOp, L2RegisterFileMOp, LoadStoreMOp, MOpTrait, UnitOutRegNum,
|
||||||
},
|
},
|
||||||
register::PRegValue,
|
register::PRegValue,
|
||||||
unit::unit_base::UnitToRegAlloc,
|
unit::unit_base::UnitForwardingInfo,
|
||||||
};
|
};
|
||||||
use fayalite::{
|
use fayalite::{
|
||||||
bundle::{Bundle, BundleType},
|
bundle::{Bundle, BundleType},
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
util::ready_valid::ReadyValid,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod alu_branch;
|
pub mod alu_branch;
|
||||||
|
|
@ -142,19 +143,19 @@ all_units! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct UnitResultCompleted<ExtraOut> {
|
pub struct UnitResultCompleted<ExtraOut> {
|
||||||
pub value: PRegValue,
|
pub value: PRegValue,
|
||||||
pub extra_out: ExtraOut,
|
pub extra_out: ExtraOut,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct UnitOutputWrite<OutRegNumWidth: Size> {
|
pub struct UnitOutputWrite<OutRegNumWidth: Size> {
|
||||||
pub which: UnitOutRegNum<OutRegNumWidth>,
|
pub which: UnitOutRegNum<OutRegNumWidth>,
|
||||||
pub value: PRegValue,
|
pub value: PRegValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl]
|
||||||
pub struct TrapData {
|
pub struct TrapData {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
@ -165,25 +166,13 @@ pub enum UnitResult<ExtraOut> {
|
||||||
Trap(TrapData),
|
Trap(TrapData),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ExtraOut: Type> UnitResult<ExtraOut> {
|
|
||||||
pub fn extra_out_ty(self) -> ExtraOut {
|
|
||||||
self.Completed.extra_out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
pub struct UnitOutput<OutRegNumWidth: Size, ExtraOut> {
|
pub struct UnitOutput<OutRegNumWidth: Size, ExtraOut> {
|
||||||
pub which: UnitOutRegNum<OutRegNumWidth>,
|
pub which: UnitOutRegNum<OutRegNumWidth>,
|
||||||
pub result: UnitResult<ExtraOut>,
|
pub result: UnitResult<ExtraOut>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<OutRegNumWidth: Size, ExtraOut: Type> UnitOutput<OutRegNumWidth, ExtraOut> {
|
#[hdl]
|
||||||
pub fn extra_out_ty(self) -> ExtraOut {
|
|
||||||
self.result.extra_out_ty()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
|
||||||
pub struct UnitCancelInput<OutRegNumWidth: Size> {
|
pub struct UnitCancelInput<OutRegNumWidth: Size> {
|
||||||
pub which: UnitOutRegNum<OutRegNumWidth>,
|
pub which: UnitOutRegNum<OutRegNumWidth>,
|
||||||
}
|
}
|
||||||
|
|
@ -208,10 +197,19 @@ pub trait UnitTrait:
|
||||||
|
|
||||||
fn module(&self) -> Interned<Module<Self::Type>>;
|
fn module(&self) -> Interned<Module<Self::Type>>;
|
||||||
|
|
||||||
fn unit_to_reg_alloc(
|
fn input_insn(&self, this: Expr<Self::Type>) -> Expr<ReadyValid<Self::MOp>>;
|
||||||
|
|
||||||
|
fn cancel_input(&self, this: Expr<Self::Type>) -> Expr<ReadyValid<UnitCancelInput<DynSize>>>;
|
||||||
|
|
||||||
|
fn unit_forwarding_info(
|
||||||
&self,
|
&self,
|
||||||
this: Expr<Self::Type>,
|
this: Expr<Self::Type>,
|
||||||
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>>;
|
) -> Expr<UnitForwardingInfo<DynSize, DynSize, DynSize>>;
|
||||||
|
|
||||||
|
fn output(
|
||||||
|
&self,
|
||||||
|
this: Expr<Self::Type>,
|
||||||
|
) -> Expr<ReadyValid<UnitOutput<DynSize, Self::ExtraOut>>>;
|
||||||
|
|
||||||
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain>;
|
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain>;
|
||||||
|
|
||||||
|
|
@ -268,11 +266,26 @@ impl UnitTrait for DynUnit {
|
||||||
self.unit.module()
|
self.unit.module()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unit_to_reg_alloc(
|
fn input_insn(&self, this: Expr<Self::Type>) -> Expr<ReadyValid<Self::MOp>> {
|
||||||
|
self.unit.input_insn(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cancel_input(&self, this: Expr<Self::Type>) -> Expr<ReadyValid<UnitCancelInput<DynSize>>> {
|
||||||
|
self.unit.cancel_input(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unit_forwarding_info(
|
||||||
&self,
|
&self,
|
||||||
this: Expr<Self::Type>,
|
this: Expr<Self::Type>,
|
||||||
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
|
) -> Expr<UnitForwardingInfo<DynSize, DynSize, DynSize>> {
|
||||||
self.unit.unit_to_reg_alloc(this)
|
self.unit.unit_forwarding_info(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output(
|
||||||
|
&self,
|
||||||
|
this: Expr<Self::Type>,
|
||||||
|
) -> Expr<ReadyValid<UnitOutput<DynSize, Self::ExtraOut>>> {
|
||||||
|
self.unit.output(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain> {
|
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain> {
|
||||||
|
|
@ -319,13 +332,26 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T
|
||||||
self.0.module().canonical().intern_sized()
|
self.0.module().canonical().intern_sized()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unit_to_reg_alloc(
|
fn input_insn(&self, this: Expr<Self::Type>) -> Expr<ReadyValid<Self::MOp>> {
|
||||||
|
Expr::from_bundle(Expr::as_bundle(self.0.input_insn(Expr::from_bundle(this))))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cancel_input(&self, this: Expr<Self::Type>) -> Expr<ReadyValid<UnitCancelInput<DynSize>>> {
|
||||||
|
self.0.cancel_input(Expr::from_bundle(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unit_forwarding_info(
|
||||||
&self,
|
&self,
|
||||||
this: Expr<Self::Type>,
|
this: Expr<Self::Type>,
|
||||||
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
|
) -> Expr<UnitForwardingInfo<DynSize, DynSize, DynSize>> {
|
||||||
Expr::from_bundle(Expr::as_bundle(
|
self.0.unit_forwarding_info(Expr::from_bundle(this))
|
||||||
self.0.unit_to_reg_alloc(Expr::from_bundle(this)),
|
}
|
||||||
))
|
|
||||||
|
fn output(
|
||||||
|
&self,
|
||||||
|
this: Expr<Self::Type>,
|
||||||
|
) -> Expr<ReadyValid<UnitOutput<DynSize, Self::ExtraOut>>> {
|
||||||
|
Expr::from_bundle(Expr::as_bundle(self.0.output(Expr::from_bundle(this))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain> {
|
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain> {
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,14 @@ use crate::{
|
||||||
config::CpuConfig,
|
config::CpuConfig,
|
||||||
instruction::{AluBranchMOp, UnitOutRegNum},
|
instruction::{AluBranchMOp, UnitOutRegNum},
|
||||||
unit::{
|
unit::{
|
||||||
unit_base::{unit_base, UnitToRegAlloc},
|
unit_base::{unit_base, UnitForwardingInfo},
|
||||||
DynUnit, DynUnitWrapper, UnitKind, UnitMOp, UnitTrait,
|
DynUnit, DynUnitWrapper, UnitCancelInput, UnitKind, UnitMOp, UnitOutput, UnitTrait,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use fayalite::{
|
use fayalite::{
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
util::ready_valid::ReadyValid,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[hdl_module]
|
#[hdl_module]
|
||||||
|
|
@ -19,30 +20,30 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let cd: ClockDomain = m.input();
|
let cd: ClockDomain = m.input();
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let unit_to_reg_alloc: UnitToRegAlloc<
|
let input_insn: ReadyValid<AluBranchMOp<UnitOutRegNum<DynSize>, DynSize>> =
|
||||||
AluBranchMOp<UnitOutRegNum<DynSize>, DynSize>,
|
m.input(ReadyValid[AluBranchMOp[config.unit_out_reg_num()][config.p_reg_num_width()]]);
|
||||||
(),
|
#[hdl]
|
||||||
DynSize,
|
let unit_forwarding_info: UnitForwardingInfo<DynSize, DynSize, DynSize> =
|
||||||
DynSize,
|
m.input(config.unit_forwarding_info());
|
||||||
DynSize,
|
#[hdl]
|
||||||
> = m.output(config.unit_to_reg_alloc(
|
let cancel_input: ReadyValid<UnitCancelInput<DynSize>> =
|
||||||
AluBranchMOp[config.unit_out_reg_num()][config.p_reg_num_width()],
|
m.input(ReadyValid[config.unit_cancel_input()]);
|
||||||
(),
|
#[hdl]
|
||||||
));
|
let output: ReadyValid<UnitOutput<DynSize, ()>> =
|
||||||
|
m.output(ReadyValid[UnitOutput[config.out_reg_num_width][()]]);
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let unit_base = instance(unit_base(
|
let unit_base = instance(unit_base(
|
||||||
config,
|
config,
|
||||||
unit_index,
|
unit_index,
|
||||||
Expr::ty(unit_to_reg_alloc).input_insn.data.HdlSome,
|
Expr::ty(input_insn).data.HdlSome,
|
||||||
(),
|
|
||||||
));
|
));
|
||||||
connect(unit_to_reg_alloc, unit_base.unit_to_reg_alloc);
|
connect(unit_base.input_insn, input_insn);
|
||||||
connect(unit_base.cd, cd);
|
connect(unit_base.cd, cd);
|
||||||
connect(unit_base.execute_start.ready, true); // TODO: finish
|
connect(unit_base.unit_forwarding_info, unit_forwarding_info);
|
||||||
connect(
|
connect(unit_base.cancel_input, cancel_input);
|
||||||
unit_base.execute_end,
|
// TODO: finish
|
||||||
Expr::ty(unit_base.execute_end).HdlNone(),
|
connect(unit_base.ready_mop.ready, true);
|
||||||
); // TODO: finish
|
connect(output.data, Expr::ty(output.data).HdlNone());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
|
@ -74,7 +75,7 @@ impl UnitTrait for AluBranch {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mop_ty(&self) -> Self::MOp {
|
fn mop_ty(&self) -> Self::MOp {
|
||||||
self.module.io_ty().unit_to_reg_alloc.mop_ty()
|
self.module.io_ty().input_insn.data.HdlSome
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unit_kind(&self) -> UnitKind {
|
fn unit_kind(&self) -> UnitKind {
|
||||||
|
|
@ -92,11 +93,26 @@ impl UnitTrait for AluBranch {
|
||||||
self.module
|
self.module
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unit_to_reg_alloc(
|
fn input_insn(&self, this: Expr<Self::Type>) -> Expr<ReadyValid<Self::MOp>> {
|
||||||
|
this.input_insn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cancel_input(&self, this: Expr<Self::Type>) -> Expr<ReadyValid<UnitCancelInput<DynSize>>> {
|
||||||
|
this.cancel_input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unit_forwarding_info(
|
||||||
&self,
|
&self,
|
||||||
this: Expr<Self::Type>,
|
this: Expr<Self::Type>,
|
||||||
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
|
) -> Expr<UnitForwardingInfo<DynSize, DynSize, DynSize>> {
|
||||||
this.unit_to_reg_alloc
|
this.unit_forwarding_info
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output(
|
||||||
|
&self,
|
||||||
|
this: Expr<Self::Type>,
|
||||||
|
) -> Expr<ReadyValid<UnitOutput<DynSize, Self::ExtraOut>>> {
|
||||||
|
this.output
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain> {
|
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain> {
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::CpuConfig,
|
config::CpuConfig,
|
||||||
instruction::{MOpTrait, PRegNum, UnitOutRegNum, COMMON_MOP_SRC_LEN},
|
instruction::{MOpTrait, UnitOutRegNum, COMMON_MOP_SRC_LEN},
|
||||||
register::PRegValue,
|
register::PRegValue,
|
||||||
unit::{UnitCancelInput, UnitOutput, UnitOutputWrite},
|
unit::{UnitCancelInput, UnitOutputWrite},
|
||||||
util::tree_reduce::tree_reduce,
|
util::tree_reduce::tree_reduce,
|
||||||
};
|
};
|
||||||
use fayalite::{module::wire_with_loc, prelude::*, ty::StaticType, util::ready_valid::ReadyValid};
|
use fayalite::{module::wire_with_loc, prelude::*, ty::StaticType, util::ready_valid::ReadyValid};
|
||||||
|
|
@ -18,439 +18,113 @@ pub struct UnitForwardingInfo<UnitNumWidth: Size, OutRegNumWidth: Size, UnitCoun
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
pub struct UnitToRegAlloc<
|
pub struct ReadyMOp<MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>>> {
|
||||||
MOp: Type,
|
|
||||||
ExtraOut: Type,
|
|
||||||
UnitNumWidth: Size,
|
|
||||||
OutRegNumWidth: Size,
|
|
||||||
UnitCount: Size,
|
|
||||||
> {
|
|
||||||
#[hdl(flip)]
|
|
||||||
pub unit_forwarding_info: UnitForwardingInfo<UnitNumWidth, OutRegNumWidth, UnitCount>,
|
|
||||||
#[hdl(flip)]
|
|
||||||
pub input_insn: ReadyValid<MOp>,
|
|
||||||
#[hdl(flip)]
|
|
||||||
pub cancel_input: HdlOption<UnitCancelInput<OutRegNumWidth>>,
|
|
||||||
pub output: HdlOption<UnitOutput<OutRegNumWidth, ExtraOut>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<MOp: Type, ExtraOut: Type, UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size>
|
|
||||||
UnitToRegAlloc<MOp, ExtraOut, UnitNumWidth, OutRegNumWidth, UnitCount>
|
|
||||||
{
|
|
||||||
pub fn mop_ty(self) -> MOp {
|
|
||||||
self.input_insn.data.HdlSome
|
|
||||||
}
|
|
||||||
pub fn extra_out_ty(self) -> ExtraOut {
|
|
||||||
self.output.HdlSome.extra_out_ty()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl]
|
|
||||||
pub struct ExecuteStart<MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>>> {
|
|
||||||
pub mop: MOp,
|
pub mop: MOp,
|
||||||
pub src_values: Array<PRegValue, { COMMON_MOP_SRC_LEN }>,
|
pub src_values: Array<PRegValue, { COMMON_MOP_SRC_LEN }>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
pub struct ExecuteEnd<OutRegNumWidth: Size, ExtraOut> {
|
struct InFlightOp<MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>>> {
|
||||||
pub unit_output: UnitOutput<OutRegNumWidth, ExtraOut>,
|
pub mop: MOp,
|
||||||
}
|
pub src_values: Array<HdlOption<PRegValue>, { COMMON_MOP_SRC_LEN }>,
|
||||||
|
|
||||||
#[hdl]
|
|
||||||
enum InFlightOpState {
|
|
||||||
Ready,
|
|
||||||
Running,
|
|
||||||
CanceledAndRunning,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InFlightOpState {
|
|
||||||
fn ready_next_state(canceling: bool, starting: bool, ending: bool) -> Expr<HdlOption<Self>> {
|
|
||||||
match (canceling, starting, ending) {
|
|
||||||
(false, false, _) => HdlSome(InFlightOpState.Ready()),
|
|
||||||
(false, true, false) => HdlSome(InFlightOpState.Running()),
|
|
||||||
(false, true, true) => HdlNone(),
|
|
||||||
(true, false, _) => HdlNone(),
|
|
||||||
(true, true, false) => HdlSome(InFlightOpState.CanceledAndRunning()),
|
|
||||||
(true, true, true) => HdlNone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn running_next_state(canceling: bool, _starting: bool, ending: bool) -> Expr<HdlOption<Self>> {
|
|
||||||
match (canceling, ending) {
|
|
||||||
(false, false) => HdlSome(InFlightOpState.Running()),
|
|
||||||
(false, true) => HdlNone(),
|
|
||||||
(true, false) => HdlSome(InFlightOpState.CanceledAndRunning()),
|
|
||||||
(true, true) => HdlNone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn canceled_and_running_next_state(
|
|
||||||
_canceling: bool,
|
|
||||||
_starting: bool,
|
|
||||||
ending: bool,
|
|
||||||
) -> Expr<HdlOption<Self>> {
|
|
||||||
if ending {
|
|
||||||
HdlNone()
|
|
||||||
} else {
|
|
||||||
HdlSome(InFlightOpState.CanceledAndRunning())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// FIXME: this is working around #[hdl] match not supporting matching values inside structs yet
|
|
||||||
#[hdl]
|
|
||||||
fn connect_next_state(
|
|
||||||
canceling: Expr<Bool>,
|
|
||||||
starting: Expr<Bool>,
|
|
||||||
ending: Expr<Bool>,
|
|
||||||
next_state_fn: fn(canceling: bool, starting: bool, ending: bool) -> Expr<HdlOption<Self>>,
|
|
||||||
next_state: Expr<HdlOption<Self>>,
|
|
||||||
) {
|
|
||||||
#[hdl]
|
|
||||||
fn recurse<const N: usize>(
|
|
||||||
exprs: &[Expr<Bool>; N],
|
|
||||||
bools: &mut [bool; N],
|
|
||||||
f: &mut impl FnMut(&[bool; N]),
|
|
||||||
arg_index: usize,
|
|
||||||
) {
|
|
||||||
if arg_index < N {
|
|
||||||
#[hdl]
|
|
||||||
if exprs[arg_index] {
|
|
||||||
bools[arg_index] = true;
|
|
||||||
recurse(exprs, bools, f, arg_index + 1);
|
|
||||||
} else {
|
|
||||||
bools[arg_index] = false;
|
|
||||||
recurse(exprs, bools, f, arg_index + 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
f(bools);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
recurse(
|
|
||||||
&[canceling, starting, ending],
|
|
||||||
&mut [false; 3],
|
|
||||||
&mut |&[canceling, starting, ending]| {
|
|
||||||
connect(next_state, next_state_fn(canceling, starting, ending))
|
|
||||||
},
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl]
|
|
||||||
struct InFlightOp<MOp: Type> {
|
|
||||||
state: InFlightOpState,
|
|
||||||
mop: MOp,
|
|
||||||
src_ready_flags: Array<Bool, { COMMON_MOP_SRC_LEN }>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl]
|
|
||||||
struct InFlightOpsSummary<OpIndexWidth: Size> {
|
|
||||||
empty_op_index: HdlOption<UIntType<OpIndexWidth>>,
|
|
||||||
ready_op_index: HdlOption<UIntType<OpIndexWidth>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<OpIndexWidth: Size> InFlightOpsSummary<OpIndexWidth> {
|
|
||||||
#[hdl]
|
|
||||||
fn new<MOp: Type>(
|
|
||||||
op_index: usize,
|
|
||||||
op_index_ty: UIntType<OpIndexWidth>,
|
|
||||||
in_flight_op: impl ToExpr<Type = HdlOption<InFlightOp<MOp>>>,
|
|
||||||
) -> Expr<Self> {
|
|
||||||
let empty_op_index = wire_with_loc(
|
|
||||||
&format!("empty_op_index_{op_index}"),
|
|
||||||
SourceLocation::caller(),
|
|
||||||
HdlOption[op_index_ty],
|
|
||||||
);
|
|
||||||
connect(empty_op_index, HdlOption[op_index_ty].HdlNone());
|
|
||||||
let ready_op_index = wire_with_loc(
|
|
||||||
&format!("ready_op_index_{op_index}"),
|
|
||||||
SourceLocation::caller(),
|
|
||||||
HdlOption[op_index_ty],
|
|
||||||
);
|
|
||||||
connect(ready_op_index, HdlOption[op_index_ty].HdlNone());
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(in_flight_op) = in_flight_op {
|
|
||||||
#[hdl]
|
|
||||||
let InFlightOp::<_> {
|
|
||||||
state,
|
|
||||||
mop: _,
|
|
||||||
src_ready_flags,
|
|
||||||
} = in_flight_op;
|
|
||||||
connect(ready_op_index, HdlOption[op_index_ty].HdlNone());
|
|
||||||
#[hdl]
|
|
||||||
match state {
|
|
||||||
InFlightOpState::Ready =>
|
|
||||||
{
|
|
||||||
#[hdl]
|
|
||||||
if src_ready_flags.cmp_eq([true; COMMON_MOP_SRC_LEN]) {
|
|
||||||
connect(ready_op_index, HdlSome(op_index.cast_to(op_index_ty)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InFlightOpState::CanceledAndRunning | InFlightOpState::Running => {}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
connect(empty_op_index, HdlSome(op_index.cast_to(op_index_ty)));
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
InFlightOpsSummary::<_> {
|
|
||||||
empty_op_index,
|
|
||||||
ready_op_index,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
fn combine(l: impl ToExpr<Type = Self>, r: impl ToExpr<Type = Self>) -> Expr<Self> {
|
|
||||||
let l = l.to_expr();
|
|
||||||
let r = r.to_expr();
|
|
||||||
#[hdl]
|
|
||||||
InFlightOpsSummary::<_> {
|
|
||||||
empty_op_index: HdlOption::or(l.empty_op_index, r.empty_op_index),
|
|
||||||
ready_op_index: HdlOption::or(l.ready_op_index, r.ready_op_index),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InFlightOpsSummary<DynSize> {
|
|
||||||
fn summarize<MOp: Type, MaxInFlight: Size>(
|
|
||||||
in_flight_ops: impl ToExpr<Type = ArrayType<HdlOption<InFlightOp<MOp>>, MaxInFlight>>,
|
|
||||||
) -> Expr<Self> {
|
|
||||||
let in_flight_ops = in_flight_ops.to_expr();
|
|
||||||
let max_in_flight = Expr::ty(in_flight_ops).len();
|
|
||||||
let index_range = 0..max_in_flight;
|
|
||||||
let index_ty = UInt::range(index_range.clone());
|
|
||||||
tree_reduce(
|
|
||||||
index_range.map(|i| Self::new(i, index_ty, in_flight_ops[i])),
|
|
||||||
Self::combine,
|
|
||||||
)
|
|
||||||
.expect("in_flight_ops is known to have len > 0")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl_module]
|
#[hdl_module]
|
||||||
pub fn unit_base<
|
pub fn unit_base<MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>>>(
|
||||||
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>, SrcRegWidth = DynSize>,
|
|
||||||
ExtraOut: Type,
|
|
||||||
>(
|
|
||||||
config: &CpuConfig,
|
config: &CpuConfig,
|
||||||
unit_index: usize,
|
unit_index: usize,
|
||||||
mop_ty: MOp,
|
mop_ty: MOp,
|
||||||
extra_out_ty: ExtraOut,
|
|
||||||
) {
|
) {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let cd: ClockDomain = m.input();
|
let cd: ClockDomain = m.input();
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let unit_to_reg_alloc: UnitToRegAlloc<MOp, ExtraOut, DynSize, DynSize, DynSize> =
|
let unit_forwarding_info: UnitForwardingInfo<DynSize, DynSize, DynSize> =
|
||||||
m.output(config.unit_to_reg_alloc(mop_ty, extra_out_ty));
|
m.input(config.unit_forwarding_info());
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let execute_start: ReadyValid<ExecuteStart<MOp>> = m.output(ReadyValid[ExecuteStart[mop_ty]]);
|
let input_insn: ReadyValid<MOp> = m.input(ReadyValid[mop_ty]);
|
||||||
|
connect(input_insn.ready, false);
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let execute_end: HdlOption<ExecuteEnd<DynSize, ExtraOut>> =
|
let cancel_input: ReadyValid<UnitCancelInput<DynSize>> =
|
||||||
m.input(HdlOption[ExecuteEnd[config.out_reg_num_width][extra_out_ty]]);
|
m.input(ReadyValid[config.unit_cancel_input()]);
|
||||||
|
connect(cancel_input.ready, true);
|
||||||
connect(execute_start.data, Expr::ty(execute_start).data.HdlNone());
|
#[hdl]
|
||||||
|
let ready_mop: ReadyValid<ReadyMOp<MOp>> = m.output(ReadyValid[ReadyMOp[mop_ty]]);
|
||||||
|
connect(ready_mop.data, Expr::ty(ready_mop.data).HdlNone());
|
||||||
let max_in_flight = config.unit_max_in_flight(unit_index).get();
|
let max_in_flight = config.unit_max_in_flight(unit_index).get();
|
||||||
let in_flight_op_ty = InFlightOp[mop_ty];
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let in_flight_ops = reg_builder()
|
let in_flight_ops = reg_builder().clock_domain(cd).reset(repeat(
|
||||||
.clock_domain(cd)
|
HdlOption[InFlightOp[mop_ty]].HdlNone(),
|
||||||
.reset(repeat(HdlOption[in_flight_op_ty].HdlNone(), max_in_flight));
|
max_in_flight,
|
||||||
|
));
|
||||||
let in_flight_ops_summary_value = InFlightOpsSummary::summarize(in_flight_ops);
|
let in_flight_op_index_ty = UInt::range(0..max_in_flight);
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let in_flight_ops_summary = wire(Expr::ty(in_flight_ops_summary_value));
|
let input_index = wire(HdlOption[in_flight_op_index_ty]);
|
||||||
connect(in_flight_ops_summary, in_flight_ops_summary_value);
|
|
||||||
|
|
||||||
connect(
|
connect(
|
||||||
unit_to_reg_alloc.input_insn.ready,
|
input_index,
|
||||||
HdlOption::is_some(in_flight_ops_summary.empty_op_index),
|
tree_reduce(
|
||||||
|
(0..max_in_flight).map(|i| -> Expr<HdlOption<UInt>> {
|
||||||
|
HdlOption::map(in_flight_ops[i], |_| i.cast_to(in_flight_op_index_ty))
|
||||||
|
}),
|
||||||
|
HdlOption::or,
|
||||||
|
)
|
||||||
|
.expect("max_in_flight is known to be non-zero"),
|
||||||
);
|
);
|
||||||
// TODO: connect(execute_start.data, <read_regs>(in_flight_ops_summary.ready_op_index));
|
|
||||||
|
|
||||||
connect(
|
|
||||||
unit_to_reg_alloc.output,
|
|
||||||
Expr::ty(unit_to_reg_alloc.output).HdlNone(),
|
|
||||||
); // TODO: finish
|
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let input_in_flight_op = wire(HdlOption[in_flight_op_ty]);
|
let input_in_flight_op = wire(HdlOption[InFlightOp[mop_ty]]);
|
||||||
connect(input_in_flight_op, HdlOption[in_flight_op_ty].HdlNone());
|
connect(input_in_flight_op, Expr::ty(input_in_flight_op).HdlNone());
|
||||||
#[hdl]
|
#[hdl]
|
||||||
if let HdlSome(mop) = ReadyValid::firing_data(unit_to_reg_alloc.input_insn) {
|
if let HdlSome(mop) = ReadyValid::firing_data(input_insn) {
|
||||||
#[hdl]
|
let src_values = wire_with_loc(
|
||||||
let input_mop_src_regs = wire(mop_ty.src_regs_ty());
|
"input_in_flight_op_src_values",
|
||||||
connect(
|
|
||||||
input_mop_src_regs,
|
|
||||||
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
|
|
||||||
);
|
|
||||||
MOp::connect_src_regs(mop, input_mop_src_regs);
|
|
||||||
let src_ready_flags = wire_with_loc(
|
|
||||||
"input_in_flight_op_src_ready_flags",
|
|
||||||
SourceLocation::caller(),
|
SourceLocation::caller(),
|
||||||
StaticType::TYPE,
|
StaticType::TYPE,
|
||||||
);
|
);
|
||||||
for src_index in 0..COMMON_MOP_SRC_LEN {
|
|
||||||
connect(
|
|
||||||
src_ready_flags[src_index],
|
|
||||||
config
|
|
||||||
.p_reg_num()
|
|
||||||
.const_zero()
|
|
||||||
.cast_to_bits()
|
|
||||||
.cmp_eq(input_mop_src_regs[src_index]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
if unit_to_reg_alloc.cancel_input.cmp_ne(HdlSome(
|
|
||||||
#[hdl]
|
|
||||||
UnitCancelInput::<_> {
|
|
||||||
which: MOp::dest_reg(mop),
|
|
||||||
},
|
|
||||||
)) {
|
|
||||||
connect(
|
|
||||||
input_in_flight_op,
|
|
||||||
HdlSome(
|
|
||||||
#[hdl]
|
|
||||||
InFlightOp::<_> {
|
|
||||||
state: InFlightOpState.Ready(),
|
|
||||||
mop,
|
|
||||||
src_ready_flags,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(empty_op_index) = in_flight_ops_summary.empty_op_index {
|
|
||||||
connect(in_flight_ops[empty_op_index], input_in_flight_op);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl]
|
|
||||||
let in_flight_op_next_state = wire(Array[HdlOption[InFlightOpState]][max_in_flight]);
|
|
||||||
#[hdl]
|
|
||||||
let in_flight_op_next_src_ready_flags =
|
|
||||||
wire(Array[in_flight_op_ty.src_ready_flags][max_in_flight]);
|
|
||||||
#[hdl]
|
|
||||||
let in_flight_op_canceling = wire(Array[Bool][max_in_flight]);
|
|
||||||
#[hdl]
|
|
||||||
let in_flight_op_execute_starting = wire(Array[Bool][max_in_flight]);
|
|
||||||
#[hdl]
|
|
||||||
let in_flight_op_execute_ending = wire(Array[Bool][max_in_flight]);
|
|
||||||
for in_flight_op_index in 0..max_in_flight {
|
|
||||||
connect(
|
connect(
|
||||||
in_flight_op_next_src_ready_flags[in_flight_op_index],
|
src_values,
|
||||||
[false; COMMON_MOP_SRC_LEN],
|
[HdlSome(PRegValue::zeroed()); COMMON_MOP_SRC_LEN],
|
||||||
);
|
);
|
||||||
connect(in_flight_op_canceling[in_flight_op_index], false);
|
MOp::for_each_src_reg(mop, &mut |src_reg, src_index| {
|
||||||
connect(in_flight_op_execute_starting[in_flight_op_index], false);
|
#[hdl]
|
||||||
connect(in_flight_op_execute_ending[in_flight_op_index], false);
|
if config
|
||||||
|
.p_reg_num()
|
||||||
|
.const_zero()
|
||||||
|
.cast_to_bits()
|
||||||
|
.cmp_ne(src_reg)
|
||||||
|
{
|
||||||
|
connect(src_values[src_index], HdlNone());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(
|
||||||
|
input_in_flight_op,
|
||||||
|
HdlSome(
|
||||||
|
#[hdl]
|
||||||
|
InFlightOp::<_> { mop, src_values },
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for in_flight_op_index in 0..max_in_flight {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
if let HdlSome(in_flight_op) = in_flight_ops[in_flight_op_index] {
|
if let HdlSome(in_flight_op) = in_flight_ops[in_flight_op_index] {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let InFlightOp::<_> {
|
if let HdlSome(cancel_input) = ReadyValid::firing_data(cancel_input) {
|
||||||
state,
|
|
||||||
mop,
|
|
||||||
src_ready_flags,
|
|
||||||
} = in_flight_op;
|
|
||||||
let which = MOp::dest_reg(mop);
|
|
||||||
let src_regs = wire_with_loc(
|
|
||||||
&format!("in_flight_op_src_regs_{in_flight_op_index}"),
|
|
||||||
SourceLocation::caller(),
|
|
||||||
mop_ty.src_regs_ty(),
|
|
||||||
);
|
|
||||||
connect(
|
|
||||||
src_regs,
|
|
||||||
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
|
|
||||||
);
|
|
||||||
MOp::connect_src_regs(mop, src_regs);
|
|
||||||
|
|
||||||
connect(
|
|
||||||
in_flight_op_next_src_ready_flags[in_flight_op_index],
|
|
||||||
src_ready_flags,
|
|
||||||
);
|
|
||||||
let unit_output_writes = unit_to_reg_alloc.unit_forwarding_info.unit_output_writes;
|
|
||||||
for unit_index in 0..Expr::ty(unit_output_writes).len() {
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
if let HdlSome(unit_output_write) = unit_output_writes[unit_index] {
|
let UnitCancelInput::<_> { which } = cancel_input;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let UnitOutputWrite::<_> {
|
if which.value.cmp_eq(MOp::dest_reg(in_flight_op.mop).value) {
|
||||||
which: unit_out_reg,
|
// TODO: if it needs extra time to cancel (e.g. still in pipeline), handle that here
|
||||||
value: _,
|
connect(
|
||||||
} = unit_output_write;
|
in_flight_ops[in_flight_op_index],
|
||||||
let p_reg_num = #[hdl]
|
HdlOption[InFlightOp[mop_ty]].HdlNone(),
|
||||||
PRegNum::<_, _> {
|
);
|
||||||
unit_num: config.unit_num().from_index(unit_index),
|
|
||||||
unit_out_reg,
|
|
||||||
};
|
|
||||||
for src_index in 0..COMMON_MOP_SRC_LEN {
|
|
||||||
#[hdl]
|
|
||||||
if p_reg_num.cast_to_bits().cmp_eq(src_regs[src_index]) {
|
|
||||||
connect(
|
|
||||||
in_flight_op_next_src_ready_flags[in_flight_op_index][src_index],
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: finish
|
||||||
connect(
|
} else if let HdlSome(input_index) = input_index {
|
||||||
in_flight_op_canceling[in_flight_op_index],
|
connect(input_insn.ready, true);
|
||||||
unit_to_reg_alloc.cancel_input.cmp_eq(HdlSome(
|
|
||||||
#[hdl]
|
|
||||||
UnitCancelInput::<_> { which },
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
if let HdlSome(execute_end) = execute_end {
|
if input_index.cmp_eq(in_flight_op_index) {
|
||||||
#[hdl]
|
connect(in_flight_ops[in_flight_op_index], input_in_flight_op);
|
||||||
let ExecuteEnd::<_, _> { unit_output } = execute_end;
|
|
||||||
#[hdl]
|
|
||||||
if which.cmp_eq(unit_output.which) {
|
|
||||||
connect(in_flight_op_execute_ending[in_flight_op_index], true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(execute_start) = ReadyValid::firing_data(execute_start) {
|
|
||||||
#[hdl]
|
|
||||||
if which.cmp_eq(MOp::dest_reg(execute_start.mop)) {
|
|
||||||
connect(in_flight_op_execute_starting[in_flight_op_index], true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let connect_next_state = |f| {
|
|
||||||
InFlightOpState::connect_next_state(
|
|
||||||
in_flight_op_canceling[in_flight_op_index],
|
|
||||||
in_flight_op_execute_starting[in_flight_op_index],
|
|
||||||
in_flight_op_execute_ending[in_flight_op_index],
|
|
||||||
f,
|
|
||||||
in_flight_op_next_state[in_flight_op_index],
|
|
||||||
);
|
|
||||||
};
|
|
||||||
#[hdl]
|
|
||||||
match state {
|
|
||||||
InFlightOpState::Ready => connect_next_state(InFlightOpState::ready_next_state),
|
|
||||||
InFlightOpState::Running => connect_next_state(InFlightOpState::running_next_state),
|
|
||||||
InFlightOpState::CanceledAndRunning => {
|
|
||||||
connect_next_state(InFlightOpState::canceled_and_running_next_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
if let HdlSome(state) = in_flight_op_next_state[in_flight_op_index] {
|
|
||||||
connect(
|
|
||||||
in_flight_ops[in_flight_op_index],
|
|
||||||
HdlSome(
|
|
||||||
#[hdl]
|
|
||||||
InFlightOp::<_> {
|
|
||||||
state,
|
|
||||||
mop,
|
|
||||||
src_ready_flags,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
connect(
|
|
||||||
in_flight_ops[in_flight_op_index],
|
|
||||||
HdlOption[in_flight_op_ty].HdlNone(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
connect(in_flight_op_next_state[in_flight_op_index], HdlNone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
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