Compare commits

..

2 commits

Author SHA1 Message Date
782a44858c
WIP: splitting reg_alloc
Some checks failed
/ deps (push) Successful in 15s
/ test (push) Failing after 2m2s
2025-03-10 19:57:52 -07:00
9fa959652e
update fayalite 2025-03-10 19:50:55 -07:00
11 changed files with 269 additions and 267 deletions

10
Cargo.lock generated
View file

@ -207,6 +207,8 @@ name = "cpu"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"fayalite", "fayalite",
"name_mangling_serde",
"serde",
] ]
[[package]] [[package]]
@ -300,7 +302,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#450e1004b6eef6fcdce74a94e3bded3e0268610d" source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#d453755bb2cd0b6f2340f3e49058d29a2ee279e8"
dependencies = [ dependencies = [
"bitvec", "bitvec",
"blake3", "blake3",
@ -325,7 +327,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#450e1004b6eef6fcdce74a94e3bded3e0268610d" source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#d453755bb2cd0b6f2340f3e49058d29a2ee279e8"
dependencies = [ dependencies = [
"fayalite-proc-macros-impl", "fayalite-proc-macros-impl",
] ]
@ -333,7 +335,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#450e1004b6eef6fcdce74a94e3bded3e0268610d" source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#d453755bb2cd0b6f2340f3e49058d29a2ee279e8"
dependencies = [ dependencies = [
"base16ct", "base16ct",
"num-bigint", "num-bigint",
@ -348,7 +350,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#450e1004b6eef6fcdce74a94e3bded3e0268610d" source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#d453755bb2cd0b6f2340f3e49058d29a2ee279e8"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"prettyplease", "prettyplease",

View file

@ -14,6 +14,7 @@ categories = []
rust-version = "1.82.0" rust-version = "1.82.0"
[workspace.dependencies] [workspace.dependencies]
name_mangling_serde = { version = "=0.1.0", path = "crates/name_mangling_serde" }
fayalite = { git = "https://git.libre-chip.org/libre-chip/fayalite.git", version = "0.3.0", branch = "master" } fayalite = { git = "https://git.libre-chip.org/libre-chip/fayalite.git", version = "0.3.0", branch = "master" }
serde = { version = "1.0.202", features = ["derive"] } serde = { version = "1.0.202", features = ["derive"] }
serde_json = { version = "1.0.117", features = ["preserve_order"] } serde_json = { version = "1.0.117", features = ["preserve_order"] }

View file

@ -16,6 +16,8 @@ version.workspace = true
[dependencies] [dependencies]
fayalite.workspace = true fayalite.workspace = true
serde.workspace = true
name_mangling_serde.workspace = true
[lints.rust] [lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(todo)'] } unexpected_cfgs = { level = "warn", check-cfg = ['cfg(todo)'] }

View file

@ -1,17 +1,17 @@
// 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, RenamedMOp, UnitNum, UnitOutRegNum, CONST_ZERO_UNIT_NUM}, instruction::{PRegNum, CONST_ZERO_UNIT_NUM},
unit::{ unit::UnitKind,
unit_base::{ExecuteEnd, ExecuteStart},
RenamedInsnData, RetireQueueIndex, UnitForwardingInfo, UnitKind, UnitOutputWrite,
UnitToRegAlloc,
},
}; };
use fayalite::prelude::*; use fayalite::{
intern::{Intern, Interned},
prelude::*,
};
use serde::{Deserialize, Serialize};
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
#[derive(Clone, Eq, PartialEq, Hash, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
#[non_exhaustive] #[non_exhaustive]
pub struct UnitConfig { pub struct UnitConfig {
pub kind: UnitKind, pub kind: UnitKind,
@ -28,10 +28,10 @@ impl UnitConfig {
} }
} }
#[derive(Clone, Eq, PartialEq, Hash, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
#[non_exhaustive] #[non_exhaustive]
pub struct CpuConfig { pub struct CpuConfig {
pub units: Vec<UnitConfig>, pub units: Interned<[UnitConfig]>,
pub out_reg_num_width: usize, pub out_reg_num_width: usize,
pub fetch_width: NonZeroUsize, pub fetch_width: NonZeroUsize,
/// default value for [`UnitConfig::max_in_flight`] /// default value for [`UnitConfig::max_in_flight`]
@ -52,7 +52,7 @@ impl CpuConfig {
}; };
v v
}; };
pub fn new(units: Vec<UnitConfig>) -> Self { pub fn new(units: Interned<[UnitConfig]>) -> Self {
Self { Self {
units, units,
out_reg_num_width: Self::DEFAULT_OUT_REG_NUM_WIDTH, out_reg_num_width: Self::DEFAULT_OUT_REG_NUM_WIDTH,
@ -66,70 +66,83 @@ impl CpuConfig {
pub fn unit_num_width(&self) -> usize { pub fn unit_num_width(&self) -> usize {
UInt::range(CONST_ZERO_UNIT_NUM..self.non_const_unit_nums().end).width() UInt::range(CONST_ZERO_UNIT_NUM..self.non_const_unit_nums().end).width()
} }
pub fn unit_num(&self) -> UnitNum<DynSize> {
UnitNum[self.unit_num_width()]
}
pub fn unit_out_reg_num(&self) -> UnitOutRegNum<DynSize> {
UnitOutRegNum[self.out_reg_num_width]
}
pub fn p_reg_num(&self) -> PRegNum<DynSize, DynSize> {
PRegNum[self.unit_num_width()][self.out_reg_num_width]
}
pub fn p_reg_num_width(&self) -> usize {
self.unit_num_width() + self.out_reg_num_width
}
pub fn renamed_mop(&self) -> RenamedMOp<DynSize> {
RenamedMOp[self.p_reg_num_width()]
}
pub fn unit_output_write(&self) -> UnitOutputWrite<DynSize> {
UnitOutputWrite[self.out_reg_num_width]
}
pub fn unit_output_writes(&self) -> Array<HdlOption<UnitOutputWrite<DynSize>>> {
Array[HdlOption[self.unit_output_write()]][self.non_const_unit_nums().len()]
}
pub fn unit_forwarding_info(&self) -> UnitForwardingInfo<DynSize, DynSize, DynSize> {
UnitForwardingInfo[self.unit_num_width()][self.out_reg_num_width]
[self.non_const_unit_nums().len()]
}
pub fn unit_max_in_flight(&self, unit_index: usize) -> NonZeroUsize { pub fn unit_max_in_flight(&self, unit_index: usize) -> NonZeroUsize {
self.units[unit_index] self.units[unit_index]
.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 = (), SrcRegWidth = DynSize>,
ExtraOut: Type,
>(
&self,
mop_ty: MOp,
extra_out_ty: ExtraOut,
) -> UnitToRegAlloc<MOp, ExtraOut, DynSize, DynSize, DynSize, DynSize> {
UnitToRegAlloc[mop_ty][extra_out_ty][self.unit_num_width()][self.out_reg_num_width]
[self.non_const_unit_nums().len()][self.retire_queue_index_width()]
}
pub fn retire_queue_index_width(&self) -> usize { pub fn retire_queue_index_width(&self) -> usize {
let max_in_flight: usize = (0..self.units.len()) let max_in_flight: usize = (0..self.units.len())
.map(|unit_index| self.unit_max_in_flight(unit_index).get()) .map(|unit_index| self.unit_max_in_flight(unit_index).get())
.sum(); .sum();
2 + max_in_flight.next_power_of_two().ilog2() as usize 2 + max_in_flight.next_power_of_two().ilog2() as usize
} }
pub fn retire_queue_index(&self) -> RetireQueueIndex<DynSize> { }
RetireQueueIndex[self.retire_queue_index_width()]
} mod sealed {
pub fn renamed_insn_data<MOp: Type, DestReg: Type>( pub trait Sealed {}
&self, }
mop: MOp,
dest: DestReg, impl sealed::Sealed for PhantomConst<CpuConfig> {}
) -> RenamedInsnData<MOp, DestReg, DynSize> {
RenamedInsnData[mop][dest][self.retire_queue_index_width()] pub trait CpuConfigType: Type + ToExpr<Type = Self> + sealed::Sealed {
} fn get(self) -> Interned<CpuConfig>;
pub fn execute_start<MOp: Type>(&self, mop: MOp) -> ExecuteStart<MOp, DynSize, DynSize> { }
ExecuteStart[mop][self.out_reg_num_width][self.retire_queue_index_width()]
} impl CpuConfigType for PhantomConst<CpuConfig> {
pub fn execute_end<ExtraOut: Type>( fn get(self) -> Interned<CpuConfig> {
&self, self.get()
extra_out_ty: ExtraOut,
) -> ExecuteEnd<DynSize, DynSize, ExtraOut> {
ExecuteEnd[self.out_reg_num_width][self.retire_queue_index_width()][extra_out_ty]
} }
} }
pub trait Identity<Arg: ?Sized> {
type SelfType: ?Sized;
type ArgType: ?Sized;
}
impl<T: ?Sized, Arg: ?Sized> Identity<Arg> for T {
type SelfType = T;
type ArgType = Arg;
}
macro_rules! impl_cpu_config_accessors {
(
$(
#[without_generics = $without_generics:ident]
$vis:vis type $ident:ident<$T:ident> = |$arg:ident| $expr:expr;
)*
) => {
$(
#[allow(non_camel_case_types)]
$vis struct $without_generics;
#[allow(non_upper_case_globals)]
$vis const $ident: $without_generics = $without_generics;
$vis type $ident<$T> = <DynSize as Identity<$T>>::SelfType;
impl<$T: CpuConfigType> std::ops::Index<$T> for $without_generics {
type Output = usize;
fn index(&self, $arg: $T) -> &Self::Output {
Interned::into_inner(Intern::intern_sized($expr))
}
}
)*
};
}
impl_cpu_config_accessors! {
#[without_generics = __UnitNumWidth_WithoutGenerics]
pub type UnitNumWidth<T> = |arg| arg.get().unit_num_width();
#[without_generics = __UnitOutRegNumWidth_WithoutGenerics]
pub type UnitOutRegNumWidth<T> = |arg| arg.get().out_reg_num_width;
#[without_generics = __PRegNumWidth_WithoutGenerics]
pub type PRegNumWidth<T> = |arg| PRegNum[arg].canonical().bit_width();
#[without_generics = __RetireQueueIndexWidth_WithoutGenerics]
pub type RetireQueueIndexWidth<T> = |arg| arg.get().retire_queue_index_width();
#[without_generics = __UnitCount_WithoutGenerics]
pub type UnitCount<T> = |arg| arg.get().non_const_unit_nums().len();
#[without_generics = __FetchWidth_WithoutGenerics]
pub type FetchWidth<T> = |arg| arg.get().fetch_width.get();
}

View file

@ -1,6 +1,10 @@
// 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::{
config::{CpuConfigType, UnitNumWidth, UnitOutRegNumWidth},
unit::UnitMOp,
util::range_u32_len,
};
use fayalite::{ use fayalite::{
expr::ops::{ArrayLiteral, ExprPartialEq}, expr::ops::{ArrayLiteral, ExprPartialEq},
intern::Interned, intern::Interned,
@ -805,19 +809,21 @@ common_mop_struct! {
} }
} }
#[hdl(cmp_eq)] #[hdl(cmp_eq, no_static)]
/// 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<C: Type + CpuConfigType> {
pub adj_value: UIntType<Width>, pub adj_value: UIntType<UnitNumWidth<C>>,
pub config: C,
} }
impl<Width: Size> UnitNum<Width> { impl<C: Type + CpuConfigType> UnitNum<C> {
#[hdl] #[hdl]
pub fn const_zero(self) -> Expr<Self> { pub fn const_zero(self) -> Expr<Self> {
#[hdl] #[hdl]
UnitNum { UnitNum {
adj_value: CONST_ZERO_UNIT_NUM.cast_to(self.adj_value), adj_value: CONST_ZERO_UNIT_NUM.cast_to(self.adj_value),
config: self.config,
} }
} }
#[hdl] #[hdl]
@ -825,6 +831,7 @@ impl<Width: Size> UnitNum<Width> {
#[hdl] #[hdl]
UnitNum { UnitNum {
adj_value: (index + 1).cast_to(self.adj_value), adj_value: (index + 1).cast_to(self.adj_value),
config: self.config,
} }
} }
pub fn is_index(expr: impl ToExpr<Type = Self>, index: usize) -> Expr<Bool> { pub fn is_index(expr: impl ToExpr<Type = Self>, index: usize) -> Expr<Bool> {
@ -835,7 +842,7 @@ impl<Width: Size> UnitNum<Width> {
.cmp_eq(expr.adj_value) .cmp_eq(expr.adj_value)
} }
#[hdl] #[hdl]
pub fn as_index(expr: impl ToExpr<Type = Self>) -> Expr<HdlOption<UIntType<Width>>> { pub fn as_index(expr: impl ToExpr<Type = Self>) -> Expr<HdlOption<UIntType<DynSize>>> {
let expr = expr.to_expr(); let expr = expr.to_expr();
#[hdl] #[hdl]
let unit_index = wire(HdlOption[Expr::ty(expr).adj_value]); let unit_index = wire(HdlOption[Expr::ty(expr).adj_value]);
@ -853,19 +860,20 @@ 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(cmp_eq, no_static)]
pub struct UnitOutRegNum<Width: Size> { pub struct UnitOutRegNum<C: Type + CpuConfigType> {
pub value: UIntType<Width>, pub value: UIntType<UnitOutRegNumWidth<C>>,
pub config: C,
} }
#[hdl(cmp_eq)] #[hdl(cmp_eq, no_static)]
/// 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<C: Type + CpuConfigType> {
pub unit_num: UnitNum<UnitNumWidth>, pub unit_num: UnitNum<C>,
pub unit_out_reg: UnitOutRegNum<OutRegNumWidth>, pub unit_out_reg: UnitOutRegNum<C>,
} }
impl<UnitNumWidth: Size, OutRegNumWidth: Size> PRegNum<UnitNumWidth, OutRegNumWidth> { impl<C: Type + CpuConfigType> PRegNum<C> {
#[hdl] #[hdl]
pub fn const_zero(self) -> Expr<Self> { pub fn const_zero(self) -> Expr<Self> {
#[hdl] #[hdl]
@ -874,6 +882,7 @@ impl<UnitNumWidth: Size, OutRegNumWidth: Size> PRegNum<UnitNumWidth, OutRegNumWi
unit_out_reg: #[hdl] unit_out_reg: #[hdl]
UnitOutRegNum { UnitOutRegNum {
value: 0u8.cast_to(self.unit_out_reg.value), value: 0u8.cast_to(self.unit_out_reg.value),
config: self.unit_out_reg.config,
}, },
} }
} }

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
config::CpuConfig, config::{CpuConfig, CpuConfigType, FetchWidth, PRegNumWidth},
instruction::{MOp, MOpDestReg, MOpRegNum, MOpTrait, MoveRegMOp, PRegNum, RenamedMOp}, instruction::{MOp, MOpDestReg, MOpRegNum, MOpTrait, MoveRegMOp, PRegNum, RenamedMOp},
rename_table::{rename_table, RenameTablePortConfig}, rename_table::{rename_table, RenameTablePortConfig},
unit::{RenamedInsnData, RetireQueueIndex, UnitMOp}, unit::{RenamedInsnData, RetireQueueIndex, UnitMOp},
@ -13,49 +13,47 @@ use fayalite::{
util::{prefix_sum::PrefixSumAlgorithm, ready_valid::ReadyValid}, util::{prefix_sum::PrefixSumAlgorithm, ready_valid::ReadyValid},
}; };
#[hdl] #[hdl(no_static)]
pub struct InstructionRenameInputInsn<UnitNumWidth: Size, OutRegNumWidth: Size> { pub struct InstructionRenameInputInsn<C: Type + CpuConfigType> {
pub mop: MOp, pub mop: MOp,
pub pc: UInt<64>, pub pc: UInt<64>,
pub renamed_dest: PRegNum<UnitNumWidth, OutRegNumWidth>, pub renamed_dest: PRegNum<C>,
} }
impl CpuConfig { #[hdl(no_static)]
pub fn instruction_rename_input_insn(&self) -> InstructionRenameInputInsn<DynSize, DynSize> { struct InsnsInPrefixSummary<C: Type + CpuConfigType> {
InstructionRenameInputInsn[self.unit_num_width()][self.out_reg_num_width] all_ready: Bool,
} ready_count: Length<FetchWidth<C>>,
retire_queue_used: Length<FetchWidth<C>>,
config: C,
} }
type C = PhantomConst<CpuConfig>;
#[hdl] #[hdl]
struct InsnsInPrefixSummary<FetchWidth: Size> { pub type InstructionRenameInsnsOut<C: Type + CpuConfigType> = ArrayType<
all_ready: Bool, ReadyValid<RenamedInsnData<C, RenamedMOp<PRegNumWidth<C>>, PRegNum<C>>>,
ready_count: Length<FetchWidth>, FetchWidth<C>,
retire_queue_used: Length<FetchWidth>, >;
}
#[hdl_module] #[hdl_module]
pub fn instruction_rename(config: &CpuConfig) { pub fn instruction_rename(config: PhantomConst<CpuConfig>) {
#[hdl] #[hdl]
let cd: ClockDomain = m.input(); let cd: ClockDomain = m.input();
#[hdl] #[hdl]
let insns_in: ReadyValidArray<InstructionRenameInputInsn<DynSize, DynSize>, DynSize> = let insns_in: ReadyValidArray<InstructionRenameInputInsn<C>, FetchWidth<C>> =
m.input(ReadyValidArray[config.instruction_rename_input_insn()][config.fetch_width.get()]); m.input(ReadyValidArray[InstructionRenameInputInsn[config]][FetchWidth[config]]);
#[hdl] #[hdl]
let start_retire_queue_index: RetireQueueIndex<DynSize> = m.input(config.retire_queue_index()); let start_retire_queue_index: RetireQueueIndex<C> = m.input(RetireQueueIndex[config]);
#[hdl] #[hdl]
let end_retire_queue_index: RetireQueueIndex<DynSize> = m.output(config.retire_queue_index()); let end_retire_queue_index: RetireQueueIndex<C> = m.output(RetireQueueIndex[config]);
#[hdl] #[hdl]
let insns_out: Array< let insns_out: InstructionRenameInsnsOut<C> = m.output(InstructionRenameInsnsOut[config]);
ReadyValid<RenamedInsnData<RenamedMOp<DynSize>, PRegNum<DynSize, DynSize>, DynSize>>,
> = m.output(
Array[ReadyValid[config.renamed_insn_data(config.renamed_mop(), config.p_reg_num())]]
[config.fetch_width.get()],
);
// TODO: handle resetting table after cancelling instructions // TODO: handle resetting table after cancelling instructions
#[hdl] #[hdl]
let insns_ready_or_move = wire(Array[Bool][config.fetch_width.get()]); let insns_ready_or_move = wire(ArrayType[Bool][FetchWidth[config]]);
for (insn_ready_or_move, insn_out) in insns_ready_or_move.into_iter().zip(insns_out) { for (insn_ready_or_move, insn_out) in insns_ready_or_move.into_iter().zip(insns_out) {
connect(insn_ready_or_move, insn_out.ready); connect(insn_ready_or_move, insn_out.ready);
@ -71,12 +69,11 @@ pub fn instruction_rename(config: &CpuConfig) {
} }
}); });
let insns_in_prefix_summary_ty = InsnsInPrefixSummary[config.fetch_width.get()]; let insns_in_prefix_summary_ty = InsnsInPrefixSummary[config];
#[hdl] #[hdl]
let insns_in_prefix_summaries = let insns_in_prefix_summaries = wire(ArrayType[insns_in_prefix_summary_ty][FetchWidth[config]]);
wire(Array[insns_in_prefix_summary_ty][config.fetch_width.get()]);
let insns_in_prefix_summaries_vec = PrefixSumAlgorithm::WorkEfficient.run( let insns_in_prefix_summaries_vec = PrefixSumAlgorithm::WorkEfficient.run(
(0..config.fetch_width.get()).map(|fetch_index| { (0..FetchWidth[config]).map(|fetch_index| {
#[hdl] #[hdl]
let insns_in_prefix_summary_in = wire(insns_in_prefix_summary_ty); let insns_in_prefix_summary_in = wire(insns_in_prefix_summary_ty);
#[hdl] #[hdl]
@ -84,6 +81,7 @@ pub fn instruction_rename(config: &CpuConfig) {
all_ready, all_ready,
ready_count, ready_count,
retire_queue_used, retire_queue_used,
config: _,
} = insns_in_prefix_summary_in; } = insns_in_prefix_summary_in;
connect(all_ready, insns_out[fetch_index].ready); connect(all_ready, insns_out[fetch_index].ready);
connect( connect(
@ -112,6 +110,7 @@ pub fn instruction_rename(config: &CpuConfig) {
all_ready, all_ready,
ready_count, ready_count,
retire_queue_used, retire_queue_used,
config: _,
} = insns_in_prefix_summary_merge; } = insns_in_prefix_summary_merge;
connect(all_ready, l.all_ready & r.all_ready); connect(all_ready, l.all_ready & r.all_ready);
#[hdl] #[hdl]
@ -143,16 +142,15 @@ pub fn instruction_rename(config: &CpuConfig) {
} }
connect( connect(
insns_in.ready, insns_in.ready,
insns_in_prefix_summaries[config.fetch_width.get() - 1].ready_count, insns_in_prefix_summaries[FetchWidth[config] - 1].ready_count,
); );
#[hdl] #[hdl]
let retire_queue_indexes = let retire_queue_indexes = wire(Array[RetireQueueIndex[config]][FetchWidth[config] + 1]);
wire(Array[config.retire_queue_index()][config.fetch_width.get() + 1]);
connect(retire_queue_indexes[0], start_retire_queue_index); connect(retire_queue_indexes[0], start_retire_queue_index);
connect( connect(
end_retire_queue_index, end_retire_queue_index,
retire_queue_indexes[config.fetch_width.get()], retire_queue_indexes[FetchWidth[config]],
); );
for (retire_queue_index, insns_in_prefix_summary) in retire_queue_indexes for (retire_queue_index, insns_in_prefix_summary) in retire_queue_indexes
.into_iter() .into_iter()
@ -171,7 +169,7 @@ pub fn instruction_rename(config: &CpuConfig) {
MOpTrait::for_each_src_reg(MOp.uninit(), &mut |_, src_index| { MOpTrait::for_each_src_reg(MOp.uninit(), &mut |_, src_index| {
src_reg_count = src_reg_count.max(src_index + 1); src_reg_count = src_reg_count.max(src_index + 1);
}); });
for _ in 0..config.fetch_width.get() { for _ in 0..FetchWidth[config] {
for _ in 0..src_reg_count { for _ in 0..src_reg_count {
port_configs.push(RenameTablePortConfig::Read { port_configs.push(RenameTablePortConfig::Read {
addr_range: MOpRegNum::NON_CONST_REG_NUMS, addr_range: MOpRegNum::NON_CONST_REG_NUMS,
@ -194,7 +192,7 @@ pub fn instruction_rename(config: &CpuConfig) {
} }
for write_port in rename_table.write_ports { for write_port in rename_table.write_ports {
connect_any(write_port.addr, 0_hdl_u0); connect_any(write_port.addr, 0_hdl_u0);
connect_any(write_port.data, config.p_reg_num().const_zero()); connect_any(write_port.data, PRegNum[config].const_zero());
} }
ArrayVec::for_each( ArrayVec::for_each(
@ -203,16 +201,13 @@ pub fn instruction_rename(config: &CpuConfig) {
let read_port_index = fetch_index * src_reg_count; let read_port_index = fetch_index * src_reg_count;
let write_port_index = fetch_index * MOpDestReg::REG_COUNT; let write_port_index = fetch_index * MOpDestReg::REG_COUNT;
#[hdl] #[hdl]
let InstructionRenameInputInsn::<_, _> { let InstructionRenameInputInsn::<_> {
mop, mop,
pc, pc,
renamed_dest, renamed_dest,
} = input_insn; } = input_insn;
let insn_out = MOpTrait::map_regs( let insn_out =
mop, MOpTrait::map_regs(mop, (), PRegNumWidth[config], &mut |src_reg, src_index| {
(),
config.p_reg_num_width(),
&mut |src_reg, src_index| {
connect( connect(
rename_table.read_ports[read_port_index + src_index].addr, rename_table.read_ports[read_port_index + src_index].addr,
src_reg.cast_bits_to(MOpRegNum), src_reg.cast_bits_to(MOpRegNum),
@ -220,8 +215,7 @@ pub fn instruction_rename(config: &CpuConfig) {
rename_table.read_ports[read_port_index + src_index] rename_table.read_ports[read_port_index + src_index]
.data .data
.cast_to_bits() .cast_to_bits()
}, });
);
for (i, dest_reg) in MOpDestReg::regs(MOpTrait::dest_reg(mop)) for (i, dest_reg) in MOpDestReg::regs(MOpTrait::dest_reg(mop))
.into_iter() .into_iter()
.enumerate() .enumerate()
@ -237,13 +231,13 @@ pub fn instruction_rename(config: &CpuConfig) {
} }
let insn_out = UnitMOp::try_with_transformed_move_op( let insn_out = UnitMOp::try_with_transformed_move_op(
insn_out, insn_out,
config.renamed_mop().TransformedMove, RenamedMOp[PRegNumWidth[config]].TransformedMove,
|insn_out: Expr<HdlOption<_>>, move_reg: Expr<MoveRegMOp<_, _>>| { |insn_out: Expr<HdlOption<_>>, move_reg: Expr<MoveRegMOp<_, _>>| {
for i in 0..MOpDestReg::REG_COUNT { for i in 0..MOpDestReg::REG_COUNT {
// execute move by using same PRegNum as src[0] for dest // execute move by using same PRegNum as src[0] for dest
connect( connect(
rename_table.write_ports[write_port_index + i].data, rename_table.write_ports[write_port_index + i].data,
move_reg.common.src[0].cast_bits_to(config.p_reg_num()), move_reg.common.src[0].cast_bits_to(PRegNum[config]),
); );
} }
// move already executed, so remove it // move already executed, so remove it

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
config::CpuConfig, config::{CpuConfig, CpuConfigType},
instruction::{MOpRegNum, PRegNum}, instruction::{MOpRegNum, PRegNum},
util::range_intersection, util::range_intersection,
}; };
@ -13,17 +13,17 @@ use fayalite::{
}; };
use std::{mem, ops::Range}; use std::{mem, ops::Range};
#[hdl] #[hdl(no_static)]
pub struct RenameTableReadPort<UnitNumWidth: Size, OutRegNumWidth: Size> { pub struct RenameTableReadPort<C: Type + CpuConfigType> {
pub addr: MOpRegNum, pub addr: MOpRegNum,
#[hdl(flip)] #[hdl(flip)]
pub data: PRegNum<UnitNumWidth, OutRegNumWidth>, pub data: PRegNum<C>,
} }
#[hdl] #[hdl(no_static)]
pub struct RenameTableWritePort<UnitNumWidth: Size, OutRegNumWidth: Size> { pub struct RenameTableWritePort<C: Type + CpuConfigType> {
pub addr: MOpRegNum, pub addr: MOpRegNum,
pub data: PRegNum<UnitNumWidth, OutRegNumWidth>, pub data: PRegNum<C>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -32,6 +32,8 @@ pub enum RenameTablePortConfig {
Write { addr_range: Range<u32> }, Write { addr_range: Range<u32> },
} }
type C = PhantomConst<CpuConfig>;
/// register rename table. /// register rename table.
/// all read/write operations are done in the order of `port_configs`. /// all read/write operations are done in the order of `port_configs`.
/// So if `port_configs[0]` is a write and `port_configs[1]` is a read, /// So if `port_configs[0]` is a write and `port_configs[1]` is a read,
@ -40,7 +42,7 @@ pub enum RenameTablePortConfig {
/// is a read and `port_configs[1]` is a write, then the read port will /// is a read and `port_configs[1]` is a write, then the read port will
/// not see the data written by the write port until the *next* clock cycle. /// not see the data written by the write port until the *next* clock cycle.
#[hdl_module] #[hdl_module]
pub fn rename_table(config: &CpuConfig, port_configs: &[RenameTablePortConfig]) { pub fn rename_table(config: PhantomConst<CpuConfig>, port_configs: &[RenameTablePortConfig]) {
let read_count = port_configs let read_count = port_configs
.iter() .iter()
.filter(|v| matches!(v, RenameTablePortConfig::Read { .. })) .filter(|v| matches!(v, RenameTablePortConfig::Read { .. }))
@ -53,16 +55,14 @@ pub fn rename_table(config: &CpuConfig, port_configs: &[RenameTablePortConfig])
#[hdl] #[hdl]
let cd: ClockDomain = m.input(); let cd: ClockDomain = m.input();
#[hdl] #[hdl]
let read_ports: Array<RenameTableReadPort<DynSize, DynSize>> = m.input( let read_ports: Array<RenameTableReadPort<C>> =
Array[RenameTableReadPort[config.unit_num_width()][config.out_reg_num_width]][read_count], m.input(Array[RenameTableReadPort[config]][read_count]);
);
#[hdl] #[hdl]
let write_ports: Array<RenameTableWritePort<DynSize, DynSize>> = m.input( let write_ports: Array<RenameTableWritePort<C>> =
Array[RenameTableWritePort[config.unit_num_width()][config.out_reg_num_width]][write_count], m.input(Array[RenameTableWritePort[config]][write_count]);
);
for read_port in read_ports { for read_port in read_ports {
connect(read_port.data, config.p_reg_num().const_zero()); connect(read_port.data, PRegNum[config].const_zero());
} }
let port_configs_and_indexes = port_configs.iter().scan( let port_configs_and_indexes = port_configs.iter().scan(
@ -103,7 +103,7 @@ pub fn rename_table(config: &CpuConfig, port_configs: &[RenameTablePortConfig])
} else { } else {
format!("mem_{:#x}_{:#x}", cur_addr_range.start, cur_addr_range.end) format!("mem_{:#x}_{:#x}", cur_addr_range.start, cur_addr_range.end)
}, },
config.p_reg_num(), PRegNum[config],
SourceLocation::caller(), SourceLocation::caller(),
); );
mem.depth(cur_addr_range.len()); mem.depth(cur_addr_range.len());

View file

@ -4,9 +4,13 @@
use crate::config::CpuConfig; use crate::config::CpuConfig;
use fayalite::prelude::*; use fayalite::prelude::*;
#[hdl]
pub struct RenameRetireInterface {}
#[hdl_module] #[hdl_module]
pub fn retire_queue(config: &CpuConfig) { pub fn retire_queue(config: &CpuConfig) {
#[hdl] #[hdl]
let cd: ClockDomain = m.input(); let cd: ClockDomain = m.input();
todo!(); todo!();
} }

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
config::CpuConfig, config::{CpuConfig, CpuConfigType, RetireQueueIndexWidth, UnitCount},
instruction::{ instruction::{
mop_enum, AluBranchMOp, LoadStoreMOp, MOp, MOpDestReg, MOpInto, MOpRegNum, MOpTrait, mop_enum, AluBranchMOp, LoadStoreMOp, MOp, MOpDestReg, MOpInto, MOpRegNum, MOpTrait,
RenamedMOp, UnitOutRegNum, RenamedMOp, UnitOutRegNum,
@ -16,7 +16,7 @@ use fayalite::{
prelude::*, prelude::*,
util::ready_valid::ReadyValid, util::ready_valid::ReadyValid,
}; };
use std::marker::PhantomData; use serde::{Deserialize, Serialize};
pub mod alu_branch; pub mod alu_branch;
pub mod unit_base; pub mod unit_base;
@ -38,7 +38,7 @@ macro_rules! all_units {
} }
) => { ) => {
$(#[$enum_meta])* $(#[$enum_meta])*
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)]
$vis enum $UnitKind { $vis enum $UnitKind {
$( $(
$(#[$variant_meta])* $(#[$variant_meta])*
@ -47,7 +47,7 @@ macro_rules! all_units {
} }
impl $UnitKind { impl $UnitKind {
pub fn unit(self, config: &CpuConfig, unit_index: usize) -> DynUnit { pub fn unit(self, config: PhantomConst<CpuConfig>, unit_index: usize) -> DynUnit {
match self { match self {
$($UnitKind::$Unit => $create_dyn_unit_fn(config, unit_index),)* $($UnitKind::$Unit => $create_dyn_unit_fn(config, unit_index),)*
} }
@ -261,20 +261,21 @@ pub struct GlobalState {
} }
/// index into the retire queue (the queue of instructions that haven't yet retired) /// index into the retire queue (the queue of instructions that haven't yet retired)
#[hdl(cmp_eq)] #[hdl(cmp_eq, no_static)]
pub struct RetireQueueIndex<Width: Size> { pub struct RetireQueueIndex<C: Type + CpuConfigType> {
/// increases by one for each instruction added to the retire queue. /// increases by one for each instruction added to the retire queue.
/// ///
/// this wraps around, so you must not compare it using `cmp_lt`/`cmp_gt` /// this wraps around, so you must not compare it using `cmp_lt`/`cmp_gt`
/// but instead must use [`Self::insns_until`] and compare the output with zero. /// but instead must use [`Self::insns_until`] and compare the output with zero.
pub index: UIntType<Width>, pub index: UIntType<RetireQueueIndexWidth<C>>,
pub config: C,
} }
impl<Width: Size> RetireQueueIndex<Width> { impl<C: Type + CpuConfigType> RetireQueueIndex<C> {
pub fn insns_until( pub fn insns_until(
this: impl ToExpr<Type = Self>, this: impl ToExpr<Type = Self>,
target: impl ToExpr<Type = Self>, target: impl ToExpr<Type = Self>,
) -> Expr<SIntType<Width>> { ) -> Expr<SIntType<RetireQueueIndexWidth<C>>> {
let this = this.to_expr(); let this = this.to_expr();
let target = target.to_expr(); let target = target.to_expr();
assert_eq!(Expr::ty(this), Expr::ty(target)); assert_eq!(Expr::ty(this), Expr::ty(target));
@ -282,50 +283,32 @@ impl<Width: Size> RetireQueueIndex<Width> {
} }
} }
#[hdl] #[hdl(no_static)]
pub struct RenamedInsnData<MOp, DestReg, RetireQueueIndexWidth: Size> { pub struct RenamedInsnData<C: Type + CpuConfigType, MOp, DestReg> {
pub retire_queue_index: RetireQueueIndex<RetireQueueIndexWidth>, pub retire_queue_index: RetireQueueIndex<C>,
pub pc: UInt<64>, pub pc: UInt<64>,
pub dest: DestReg, pub dest: DestReg,
pub mop: MOp, pub mop: MOp,
} }
#[hdl] #[hdl(no_static)]
pub struct UnitForwardingInfo<UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size> { pub struct UnitForwardingInfo<C: Type + CpuConfigType> {
pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<OutRegNumWidth>>, UnitCount>, pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<C>>, UnitCount<C>>,
pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<OutRegNumWidth>>, UnitCount>, pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<C>>, UnitCount<C>>,
pub _phantom: PhantomData<UnitNumWidth>,
} }
#[hdl] #[hdl(no_static)]
pub struct UnitToRegAlloc< pub struct UnitToRegAlloc<C: Type + CpuConfigType, MOp: Type, ExtraOut: Type> {
MOp: Type,
ExtraOut: Type,
UnitNumWidth: Size,
OutRegNumWidth: Size,
UnitCount: Size,
RetireQueueIndexWidth: Size,
> {
#[hdl(flip)] #[hdl(flip)]
pub unit_forwarding_info: UnitForwardingInfo<UnitNumWidth, OutRegNumWidth, UnitCount>, pub unit_forwarding_info: UnitForwardingInfo<C>,
#[hdl(flip)] #[hdl(flip)]
pub input: pub input: ReadyValid<RenamedInsnData<C, MOp, UnitOutRegNum<C>>>,
ReadyValid<RenamedInsnData<MOp, UnitOutRegNum<OutRegNumWidth>, RetireQueueIndexWidth>>,
#[hdl(flip)] #[hdl(flip)]
pub cancel_input: HdlOption<UnitCancelInput<OutRegNumWidth>>, pub cancel_input: HdlOption<UnitCancelInput<C>>,
pub output: HdlOption<UnitOutput<OutRegNumWidth, RetireQueueIndexWidth, ExtraOut>>, pub output: HdlOption<UnitOutput<C, ExtraOut>>,
} }
impl< impl<C: Type + CpuConfigType, MOp: Type, ExtraOut: Type> UnitToRegAlloc<C, MOp, ExtraOut> {
MOp: Type,
ExtraOut: Type,
UnitNumWidth: Size,
OutRegNumWidth: Size,
UnitCount: Size,
RetireQueueIndexWidth: Size,
>
UnitToRegAlloc<MOp, ExtraOut, UnitNumWidth, OutRegNumWidth, UnitCount, RetireQueueIndexWidth>
{
pub fn mop_ty(self) -> MOp { pub fn mop_ty(self) -> MOp {
self.input.data.HdlSome.mop self.input.data.HdlSome.mop
} }
@ -340,12 +323,16 @@ pub struct UnitResultCompleted<ExtraOut> {
pub extra_out: ExtraOut, pub extra_out: ExtraOut,
} }
#[hdl(cmp_eq)] #[hdl(cmp_eq, no_static)]
pub struct UnitOutputWrite<OutRegNumWidth: Size> { pub struct UnitOutputWrite<C: Type + CpuConfigType> {
pub dest: UnitOutRegNum<OutRegNumWidth>, pub dest: UnitOutRegNum<C>,
pub value: PRegValue, pub value: PRegValue,
} }
#[hdl]
pub type UnitOutputWrites<C: Type + CpuConfigType> =
ArrayType<HdlOption<UnitOutputWrite<C>>, UnitCount<C>>;
#[hdl(cmp_eq)] #[hdl(cmp_eq)]
pub struct TrapData { pub struct TrapData {
// TODO // TODO
@ -363,30 +350,28 @@ impl<ExtraOut: Type> UnitResult<ExtraOut> {
} }
} }
#[hdl] #[hdl(no_static)]
pub struct UnitOutput<OutRegNumWidth: Size, RetireQueueIndexWidth: Size, ExtraOut> { pub struct UnitOutput<C: Type + CpuConfigType, ExtraOut> {
pub dest: UnitOutRegNum<OutRegNumWidth>, pub dest: UnitOutRegNum<C>,
pub retire_queue_index: RetireQueueIndex<RetireQueueIndexWidth>, pub retire_queue_index: RetireQueueIndex<C>,
pub result: UnitResult<ExtraOut>, pub result: UnitResult<ExtraOut>,
} }
impl<OutRegNumWidth: Size, RetireQueueIndexWidth: Size, ExtraOut: Type> impl<C: Type + CpuConfigType, ExtraOut: Type> UnitOutput<C, ExtraOut> {
UnitOutput<OutRegNumWidth, RetireQueueIndexWidth, ExtraOut>
{
pub fn extra_out_ty(self) -> ExtraOut { pub fn extra_out_ty(self) -> ExtraOut {
self.result.extra_out_ty() self.result.extra_out_ty()
} }
} }
#[hdl(cmp_eq)] #[hdl(cmp_eq, no_static)]
pub struct UnitCancelInput<RetireQueueIndexWidth: Size> { pub struct UnitCancelInput<C: Type + CpuConfigType> {
pub target: RetireQueueIndex<RetireQueueIndexWidth>, pub target: RetireQueueIndex<C>,
} }
impl<RetireQueueIndexWidth: Size> UnitCancelInput<RetireQueueIndexWidth> { impl<C: Type + CpuConfigType> UnitCancelInput<C> {
pub fn is_canceled( pub fn is_canceled(
this: impl ToExpr<Type = Self>, this: impl ToExpr<Type = Self>,
insn_retire_queue_index: impl ToExpr<Type = RetireQueueIndex<RetireQueueIndexWidth>>, insn_retire_queue_index: impl ToExpr<Type = RetireQueueIndex<C>>,
) -> Expr<Bool> { ) -> Expr<Bool> {
RetireQueueIndex::insns_until(insn_retire_queue_index, this.to_expr().target).cmp_ge(0i8) RetireQueueIndex::insns_until(insn_retire_queue_index, this.to_expr().target).cmp_ge(0i8)
} }
@ -412,7 +397,7 @@ pub trait UnitTrait:
fn unit_to_reg_alloc( fn unit_to_reg_alloc(
&self, &self,
this: Expr<Self::Type>, this: Expr<Self::Type>,
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize, DynSize>>; ) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>>;
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain>; fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain>;
@ -471,7 +456,7 @@ impl UnitTrait for DynUnit {
fn unit_to_reg_alloc( fn unit_to_reg_alloc(
&self, &self,
this: Expr<Self::Type>, this: Expr<Self::Type>,
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize, DynSize>> { ) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
self.unit.unit_to_reg_alloc(this) self.unit.unit_to_reg_alloc(this)
} }
@ -523,7 +508,7 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T
fn unit_to_reg_alloc( fn unit_to_reg_alloc(
&self, &self,
this: Expr<Self::Type>, this: Expr<Self::Type>,
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize, DynSize>> { ) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
Expr::from_bundle(Expr::as_bundle( Expr::from_bundle(Expr::as_bundle(
self.0.unit_to_reg_alloc(Expr::from_bundle(this)), self.0.unit_to_reg_alloc(Expr::from_bundle(this)),
)) ))

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
config::CpuConfig, config::{CpuConfig, PRegNumWidth},
instruction::{ instruction::{
AddSubMOp, AluBranchMOp, AluCommonMOp, CommonMOp, LogicalMOp, OutputIntegerMode, AddSubMOp, AluBranchMOp, AluCommonMOp, CommonMOp, LogicalMOp, OutputIntegerMode,
RenamedMOp, COMMON_MOP_SRC_LEN, RenamedMOp, COMMON_MOP_SRC_LEN,
@ -15,10 +15,7 @@ use crate::{
}, },
}; };
use fayalite::{ use fayalite::{
intern::{Intern, Interned}, intern::Interned, module::wire_with_loc, prelude::*, util::ready_valid::ReadyValid,
module::wire_with_loc,
prelude::*,
util::ready_valid::ReadyValid,
}; };
use std::{collections::HashMap, ops::RangeTo}; use std::{collections::HashMap, ops::RangeTo};
@ -245,18 +242,15 @@ fn logical(
} }
#[hdl_module] #[hdl_module]
pub fn alu_branch(config: &CpuConfig, unit_index: usize) { pub fn alu_branch(config: PhantomConst<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 unit_to_reg_alloc: UnitToRegAlloc<
PhantomConst<CpuConfig>,
AluBranchMOp<(), DynSize>, AluBranchMOp<(), DynSize>,
(), (),
DynSize, > = m.output(UnitToRegAlloc[config][AluBranchMOp[()][PRegNumWidth[config]]][()]);
DynSize,
DynSize,
DynSize,
> = m.output(config.unit_to_reg_alloc(AluBranchMOp[()][config.p_reg_num_width()], ()));
#[hdl] #[hdl]
let global_state: GlobalState = m.input(); let global_state: GlobalState = m.input();
@ -277,16 +271,16 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
#[hdl] #[hdl]
if let HdlSome(execute_start) = ReadyValid::firing_data(unit_base.execute_start) { if let HdlSome(execute_start) = ReadyValid::firing_data(unit_base.execute_start) {
#[hdl] #[hdl]
let ExecuteStart::<_, _, _> { insn, src_values } = execute_start; let ExecuteStart::<_, _> { insn, src_values } = execute_start;
#[hdl] #[hdl]
match insn.mop { match insn.mop {
AluBranchMOp::<_, _>::AddSub(mop) => connect( AluBranchMOp::<_, _>::AddSub(mop) => connect(
unit_base.execute_end, unit_base.execute_end,
HdlSome( HdlSome(
#[hdl] #[hdl]
ExecuteEnd::<_, _, _> { ExecuteEnd::<_, _> {
unit_output: #[hdl] unit_output: #[hdl]
UnitOutput::<_, _, _> { UnitOutput::<_, _> {
dest: insn.dest, dest: insn.dest,
retire_queue_index: insn.retire_queue_index, retire_queue_index: insn.retire_queue_index,
result: UnitResult[()].Completed(add_sub( result: UnitResult[()].Completed(add_sub(
@ -303,9 +297,9 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
unit_base.execute_end, unit_base.execute_end,
HdlSome( HdlSome(
#[hdl] #[hdl]
ExecuteEnd::<_, _, _> { ExecuteEnd::<_, _> {
unit_output: #[hdl] unit_output: #[hdl]
UnitOutput::<_, _, _> { UnitOutput::<_, _> {
dest: insn.dest, dest: insn.dest,
retire_queue_index: insn.retire_queue_index, retire_queue_index: insn.retire_queue_index,
result: UnitResult[()].Completed(add_sub( result: UnitResult[()].Completed(add_sub(
@ -322,9 +316,9 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
unit_base.execute_end, unit_base.execute_end,
HdlSome( HdlSome(
#[hdl] #[hdl]
ExecuteEnd::<_, _, _> { ExecuteEnd::<_, _> {
unit_output: #[hdl] unit_output: #[hdl]
UnitOutput::<_, _, _> { UnitOutput::<_, _> {
dest: insn.dest, dest: insn.dest,
retire_queue_index: insn.retire_queue_index, retire_queue_index: insn.retire_queue_index,
result: UnitResult[()].Completed(logical( result: UnitResult[()].Completed(logical(
@ -342,14 +336,14 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct AluBranch { pub struct AluBranch {
config: Interned<CpuConfig>, config: PhantomConst<CpuConfig>,
module: Interned<Module<alu_branch>>, module: Interned<Module<alu_branch>>,
} }
impl AluBranch { impl AluBranch {
pub fn new(config: &CpuConfig, unit_index: usize) -> Self { pub fn new(config: PhantomConst<CpuConfig>, unit_index: usize) -> Self {
Self { Self {
config: config.intern(), config,
module: alu_branch(config, unit_index), module: alu_branch(config, unit_index),
} }
} }
@ -387,7 +381,7 @@ impl UnitTrait for AluBranch {
fn unit_to_reg_alloc( fn unit_to_reg_alloc(
&self, &self,
this: Expr<Self::Type>, this: Expr<Self::Type>,
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize, DynSize>> { ) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
this.unit_to_reg_alloc this.unit_to_reg_alloc
} }

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{ use crate::{
config::CpuConfig, config::{CpuConfig, CpuConfigType, UnitOutRegNumWidth},
instruction::{MOpTrait, PRegNum, UnitNum, UnitOutRegNum, COMMON_MOP_SRC_LEN}, instruction::{MOpTrait, PRegNum, UnitNum, UnitOutRegNum, COMMON_MOP_SRC_LEN},
register::PRegValue, register::PRegValue,
unit::{ unit::{
@ -18,15 +18,15 @@ use fayalite::{
util::{prefix_sum::reduce, ready_valid::ReadyValid}, util::{prefix_sum::reduce, ready_valid::ReadyValid},
}; };
#[hdl] #[hdl(no_static)]
pub struct ExecuteStart<MOp: Type, OutRegNumWidth: Size, RetireQueueIndexWidth: Size> { pub struct ExecuteStart<C: Type + CpuConfigType, MOp: Type> {
pub insn: RenamedInsnData<MOp, UnitOutRegNum<OutRegNumWidth>, RetireQueueIndexWidth>, pub insn: RenamedInsnData<C, MOp, UnitOutRegNum<C>>,
pub src_values: Array<PRegValue, { COMMON_MOP_SRC_LEN }>, pub src_values: Array<PRegValue, { COMMON_MOP_SRC_LEN }>,
} }
#[hdl] #[hdl(no_static)]
pub struct ExecuteEnd<OutRegNumWidth: Size, RetireQueueIndexWidth: Size, ExtraOut> { pub struct ExecuteEnd<C: Type + CpuConfigType, ExtraOut> {
pub unit_output: UnitOutput<OutRegNumWidth, RetireQueueIndexWidth, ExtraOut>, pub unit_output: UnitOutput<C, ExtraOut>,
} }
#[hdl] #[hdl]
@ -106,10 +106,10 @@ impl InFlightOpState {
} }
} }
#[hdl] #[hdl(no_static)]
struct InFlightOp<MOp: Type, OutRegNumWidth: Size, RetireQueueIndexWidth: Size> { struct InFlightOp<C: Type + CpuConfigType, MOp: Type> {
state: InFlightOpState, state: InFlightOpState,
insn: RenamedInsnData<MOp, UnitOutRegNum<OutRegNumWidth>, RetireQueueIndexWidth>, insn: RenamedInsnData<C, MOp, UnitOutRegNum<C>>,
src_ready_flags: Array<Bool, { COMMON_MOP_SRC_LEN }>, src_ready_flags: Array<Bool, { COMMON_MOP_SRC_LEN }>,
} }
@ -124,7 +124,7 @@ impl<OpIndexWidth: Size> InFlightOpsSummary<OpIndexWidth> {
fn new<MOp: Type>( fn new<MOp: Type>(
op_index: usize, op_index: usize,
op_index_ty: UIntType<OpIndexWidth>, op_index_ty: UIntType<OpIndexWidth>,
in_flight_op: impl ToExpr<Type = HdlOption<InFlightOp<MOp, DynSize, DynSize>>>, in_flight_op: impl ToExpr<Type = HdlOption<InFlightOp<PhantomConst<CpuConfig>, MOp>>>,
) -> Expr<Self> { ) -> Expr<Self> {
let empty_op_index = wire_with_loc( let empty_op_index = wire_with_loc(
&format!("empty_op_index_{op_index}"), &format!("empty_op_index_{op_index}"),
@ -141,7 +141,7 @@ impl<OpIndexWidth: Size> InFlightOpsSummary<OpIndexWidth> {
#[hdl] #[hdl]
if let HdlSome(in_flight_op) = in_flight_op { if let HdlSome(in_flight_op) = in_flight_op {
#[hdl] #[hdl]
let InFlightOp::<_, _, _> { let InFlightOp::<_, _> {
state, state,
insn: _, insn: _,
src_ready_flags, src_ready_flags,
@ -182,7 +182,7 @@ impl<OpIndexWidth: Size> InFlightOpsSummary<OpIndexWidth> {
impl InFlightOpsSummary<DynSize> { impl InFlightOpsSummary<DynSize> {
fn summarize<MOp: Type, MaxInFlight: Size>( fn summarize<MOp: Type, MaxInFlight: Size>(
in_flight_ops: impl ToExpr< in_flight_ops: impl ToExpr<
Type = ArrayType<HdlOption<InFlightOp<MOp, DynSize, DynSize>>, MaxInFlight>, Type = ArrayType<HdlOption<InFlightOp<PhantomConst<CpuConfig>, MOp>>, MaxInFlight>,
>, >,
) -> Expr<Self> { ) -> Expr<Self> {
let in_flight_ops = in_flight_ops.to_expr(); let in_flight_ops = in_flight_ops.to_expr();
@ -199,7 +199,7 @@ impl InFlightOpsSummary<DynSize> {
#[hdl_module] #[hdl_module]
pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, ExtraOut: Type>( pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, ExtraOut: Type>(
config: &CpuConfig, config: PhantomConst<CpuConfig>,
unit_index: usize, unit_index: usize,
mop_ty: MOp, mop_ty: MOp,
extra_out_ty: ExtraOut, extra_out_ty: ExtraOut,
@ -207,20 +207,19 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
#[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, DynSize> = let unit_to_reg_alloc: UnitToRegAlloc<PhantomConst<CpuConfig>, MOp, ExtraOut> =
m.output(config.unit_to_reg_alloc(mop_ty, extra_out_ty)); m.output(UnitToRegAlloc[config][mop_ty][extra_out_ty]);
#[hdl] #[hdl]
let execute_start: ReadyValid<ExecuteStart<MOp, DynSize, DynSize>> = let execute_start: ReadyValid<ExecuteStart<PhantomConst<CpuConfig>, MOp>> =
m.output(ReadyValid[config.execute_start(mop_ty)]); m.output(ReadyValid[ExecuteStart[config][mop_ty]]);
#[hdl] #[hdl]
let execute_end: HdlOption<ExecuteEnd<DynSize, DynSize, ExtraOut>> = let execute_end: HdlOption<ExecuteEnd<PhantomConst<CpuConfig>, ExtraOut>> =
m.input(HdlOption[config.execute_end(extra_out_ty)]); m.input(HdlOption[ExecuteEnd[config][extra_out_ty]]);
connect(execute_start.data, Expr::ty(execute_start).data.HdlNone()); connect(execute_start.data, Expr::ty(execute_start).data.HdlNone());
let max_in_flight = config.unit_max_in_flight(unit_index).get(); let max_in_flight = config.get().unit_max_in_flight(unit_index).get();
let in_flight_op_ty = let in_flight_op_ty = InFlightOp[config][mop_ty];
InFlightOp[mop_ty][config.out_reg_num_width][config.retire_queue_index_width()];
#[hdl] #[hdl]
let in_flight_ops = reg_builder() let in_flight_ops = reg_builder()
.clock_domain(cd) .clock_domain(cd)
@ -237,16 +236,15 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
); );
#[hdl] #[hdl]
let UnitForwardingInfo::<_, _, _> { let UnitForwardingInfo::<_> {
unit_output_writes, unit_output_writes,
unit_reg_frees, unit_reg_frees,
_phantom: _,
} = unit_to_reg_alloc.unit_forwarding_info; } = unit_to_reg_alloc.unit_forwarding_info;
#[hdl] #[hdl]
let read_src_regs = wire(mop_ty.src_regs_ty()); let read_src_regs = wire(mop_ty.src_regs_ty());
connect( connect(
read_src_regs, read_src_regs,
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize), repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
); );
#[hdl] #[hdl]
let read_src_values = wire(); let read_src_values = wire();
@ -255,7 +253,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
let input_src_regs = wire(mop_ty.src_regs_ty()); let input_src_regs = wire(mop_ty.src_regs_ty());
connect( connect(
input_src_regs, input_src_regs,
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize), repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
); );
#[hdl] #[hdl]
let input_src_regs_valid = wire(); let input_src_regs_valid = wire();
@ -267,7 +265,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
Bool, Bool,
SourceLocation::caller(), SourceLocation::caller(),
); );
mem.depth(1 << config.out_reg_num_width); mem.depth(1 << UnitOutRegNumWidth[config]);
mem mem
}) })
.collect(); .collect();
@ -277,11 +275,11 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
PRegValue, PRegValue,
SourceLocation::caller(), SourceLocation::caller(),
); );
unit_output_regs.depth(1 << config.out_reg_num_width); unit_output_regs.depth(1 << UnitOutRegNumWidth[config]);
for src_index in 0..COMMON_MOP_SRC_LEN { for src_index in 0..COMMON_MOP_SRC_LEN {
let read_port = unit_output_regs.new_read_port(); let read_port = unit_output_regs.new_read_port();
let p_reg_num = read_src_regs[src_index].cast_bits_to(config.p_reg_num()); let p_reg_num = read_src_regs[src_index].cast_bits_to(PRegNum[config]);
connect_any(read_port.addr, p_reg_num.unit_out_reg.value); connect_any(read_port.addr, p_reg_num.unit_out_reg.value);
connect(read_port.en, false); connect(read_port.en, false);
connect(read_port.clk, cd.clk); connect(read_port.clk, cd.clk);
@ -294,7 +292,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
for src_index in 0..COMMON_MOP_SRC_LEN { for src_index in 0..COMMON_MOP_SRC_LEN {
let read_port = unit_output_regs_valid[unit_index].new_read_port(); let read_port = unit_output_regs_valid[unit_index].new_read_port();
let p_reg_num = input_src_regs[src_index].cast_bits_to(config.p_reg_num()); let p_reg_num = input_src_regs[src_index].cast_bits_to(PRegNum[config]);
connect_any(read_port.addr, p_reg_num.unit_out_reg.value); connect_any(read_port.addr, p_reg_num.unit_out_reg.value);
connect(read_port.en, false); connect(read_port.en, false);
connect(read_port.clk, cd.clk); connect(read_port.clk, cd.clk);
@ -325,8 +323,8 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
connect_any(ready_write_port.addr, unit_output_write.dest.value); connect_any(ready_write_port.addr, unit_output_write.dest.value);
connect(ready_write_port.en, true); connect(ready_write_port.en, true);
let p_reg_num = #[hdl] let p_reg_num = #[hdl]
PRegNum::<_, _> { PRegNum::<_> {
unit_num: config.unit_num().from_index(unit_index), unit_num: UnitNum[config].from_index(unit_index),
unit_out_reg: unit_output_write.dest, unit_out_reg: unit_output_write.dest,
}; };
for src_index in 0..COMMON_MOP_SRC_LEN { for src_index in 0..COMMON_MOP_SRC_LEN {
@ -357,7 +355,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
execute_start.data, execute_start.data,
HdlSome( HdlSome(
#[hdl] #[hdl]
ExecuteStart::<_, _, _> { ExecuteStart::<_, _> {
insn: in_flight_op.insn, insn: in_flight_op.insn,
src_values: read_src_values, src_values: read_src_values,
}, },
@ -387,7 +385,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
let input_mop_src_regs = wire(mop_ty.src_regs_ty()); let input_mop_src_regs = wire(mop_ty.src_regs_ty());
connect( connect(
input_mop_src_regs, input_mop_src_regs,
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize), repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
); );
MOp::connect_src_regs(mop, input_mop_src_regs); MOp::connect_src_regs(mop, input_mop_src_regs);
let src_ready_flags = wire_with_loc( let src_ready_flags = wire_with_loc(
@ -413,7 +411,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
input_in_flight_op, input_in_flight_op,
HdlSome( HdlSome(
#[hdl] #[hdl]
InFlightOp::<_, _, _> { InFlightOp::<_, _> {
state: InFlightOpState.Ready(), state: InFlightOpState.Ready(),
insn: input, insn: input,
src_ready_flags, src_ready_flags,
@ -449,7 +447,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
#[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::<_, _, _> { let InFlightOp::<_, _> {
state, state,
insn, insn,
src_ready_flags, src_ready_flags,
@ -461,7 +459,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
); );
connect( connect(
src_regs, src_regs,
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize), repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
); );
MOp::connect_src_regs(insn.mop, src_regs); MOp::connect_src_regs(insn.mop, src_regs);
@ -485,8 +483,8 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
value: _, value: _,
} = unit_output_write; } = unit_output_write;
let p_reg_num = #[hdl] let p_reg_num = #[hdl]
PRegNum::<_, _> { PRegNum::<_> {
unit_num: config.unit_num().from_index(unit_index), unit_num: UnitNum[config].from_index(unit_index),
unit_out_reg, unit_out_reg,
}; };
for src_index in 0..COMMON_MOP_SRC_LEN { for src_index in 0..COMMON_MOP_SRC_LEN {
@ -513,7 +511,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
#[hdl] #[hdl]
if let HdlSome(execute_end) = execute_end { if let HdlSome(execute_end) = execute_end {
#[hdl] #[hdl]
let ExecuteEnd::<_, _, _> { unit_output } = execute_end; let ExecuteEnd::<_, _> { unit_output } = execute_end;
#[hdl] #[hdl]
if insn.dest.cmp_eq(unit_output.dest) { if insn.dest.cmp_eq(unit_output.dest) {
connect(in_flight_op_execute_ending[in_flight_op_index], true); connect(in_flight_op_execute_ending[in_flight_op_index], true);
@ -559,7 +557,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr
in_flight_ops[in_flight_op_index], in_flight_ops[in_flight_op_index],
HdlSome( HdlSome(
#[hdl] #[hdl]
InFlightOp::<_, _, _> { InFlightOp::<_, _> {
state, state,
insn, insn,
src_ready_flags: in_flight_op_next_src_ready_flags[in_flight_op_index], src_ready_flags: in_flight_op_next_src_ready_flags[in_flight_op_index],