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

View file

@ -14,6 +14,7 @@ categories = []
rust-version = "1.82.0"
[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" }
serde = { version = "1.0.202", features = ["derive"] }
serde_json = { version = "1.0.117", features = ["preserve_order"] }

View file

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

View file

@ -1,17 +1,17 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{
instruction::{MOpTrait, PRegNum, RenamedMOp, UnitNum, UnitOutRegNum, CONST_ZERO_UNIT_NUM},
unit::{
unit_base::{ExecuteEnd, ExecuteStart},
RenamedInsnData, RetireQueueIndex, UnitForwardingInfo, UnitKind, UnitOutputWrite,
UnitToRegAlloc,
},
instruction::{PRegNum, CONST_ZERO_UNIT_NUM},
unit::UnitKind,
};
use fayalite::prelude::*;
use fayalite::{
intern::{Intern, Interned},
prelude::*,
};
use serde::{Deserialize, Serialize};
use std::num::NonZeroUsize;
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub struct UnitConfig {
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]
pub struct CpuConfig {
pub units: Vec<UnitConfig>,
pub units: Interned<[UnitConfig]>,
pub out_reg_num_width: usize,
pub fetch_width: NonZeroUsize,
/// default value for [`UnitConfig::max_in_flight`]
@ -52,7 +52,7 @@ impl CpuConfig {
};
v
};
pub fn new(units: Vec<UnitConfig>) -> Self {
pub fn new(units: Interned<[UnitConfig]>) -> Self {
Self {
units,
out_reg_num_width: Self::DEFAULT_OUT_REG_NUM_WIDTH,
@ -66,70 +66,83 @@ impl CpuConfig {
pub fn unit_num_width(&self) -> usize {
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 {
self.units[unit_index]
.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 {
let max_in_flight: usize = (0..self.units.len())
.map(|unit_index| self.unit_max_in_flight(unit_index).get())
.sum();
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()]
}
pub fn renamed_insn_data<MOp: Type, DestReg: Type>(
&self,
mop: MOp,
dest: DestReg,
) -> RenamedInsnData<MOp, DestReg, DynSize> {
RenamedInsnData[mop][dest][self.retire_queue_index_width()]
}
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()]
}
pub fn execute_end<ExtraOut: Type>(
&self,
extra_out_ty: ExtraOut,
) -> ExecuteEnd<DynSize, DynSize, ExtraOut> {
ExecuteEnd[self.out_reg_num_width][self.retire_queue_index_width()][extra_out_ty]
}
mod sealed {
pub trait Sealed {}
}
impl sealed::Sealed for PhantomConst<CpuConfig> {}
pub trait CpuConfigType: Type + ToExpr<Type = Self> + sealed::Sealed {
fn get(self) -> Interned<CpuConfig>;
}
impl CpuConfigType for PhantomConst<CpuConfig> {
fn get(self) -> Interned<CpuConfig> {
self.get()
}
}
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
// 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::{
expr::ops::{ArrayLiteral, ExprPartialEq},
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.
/// zero is used for built-in constants, such as the zero register
pub struct UnitNum<Width: Size> {
pub adj_value: UIntType<Width>,
pub struct UnitNum<C: Type + CpuConfigType> {
pub adj_value: UIntType<UnitNumWidth<C>>,
pub config: C,
}
impl<Width: Size> UnitNum<Width> {
impl<C: Type + CpuConfigType> UnitNum<C> {
#[hdl]
pub fn const_zero(self) -> Expr<Self> {
#[hdl]
UnitNum {
adj_value: CONST_ZERO_UNIT_NUM.cast_to(self.adj_value),
config: self.config,
}
}
#[hdl]
@ -825,6 +831,7 @@ impl<Width: Size> UnitNum<Width> {
#[hdl]
UnitNum {
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> {
@ -835,7 +842,7 @@ impl<Width: Size> UnitNum<Width> {
.cmp_eq(expr.adj_value)
}
#[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();
#[hdl]
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;
#[hdl(cmp_eq)]
pub struct UnitOutRegNum<Width: Size> {
pub value: UIntType<Width>,
#[hdl(cmp_eq, no_static)]
pub struct UnitOutRegNum<C: Type + CpuConfigType> {
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
pub struct PRegNum<UnitNumWidth: Size, OutRegNumWidth: Size> {
pub unit_num: UnitNum<UnitNumWidth>,
pub unit_out_reg: UnitOutRegNum<OutRegNumWidth>,
pub struct PRegNum<C: Type + CpuConfigType> {
pub unit_num: UnitNum<C>,
pub unit_out_reg: UnitOutRegNum<C>,
}
impl<UnitNumWidth: Size, OutRegNumWidth: Size> PRegNum<UnitNumWidth, OutRegNumWidth> {
impl<C: Type + CpuConfigType> PRegNum<C> {
#[hdl]
pub fn const_zero(self) -> Expr<Self> {
#[hdl]
@ -874,6 +882,7 @@ impl<UnitNumWidth: Size, OutRegNumWidth: Size> PRegNum<UnitNumWidth, OutRegNumWi
unit_out_reg: #[hdl]
UnitOutRegNum {
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
use crate::{
config::CpuConfig,
config::{CpuConfig, CpuConfigType, FetchWidth, PRegNumWidth},
instruction::{MOp, MOpDestReg, MOpRegNum, MOpTrait, MoveRegMOp, PRegNum, RenamedMOp},
rename_table::{rename_table, RenameTablePortConfig},
unit::{RenamedInsnData, RetireQueueIndex, UnitMOp},
@ -13,49 +13,47 @@ use fayalite::{
util::{prefix_sum::PrefixSumAlgorithm, ready_valid::ReadyValid},
};
#[hdl]
pub struct InstructionRenameInputInsn<UnitNumWidth: Size, OutRegNumWidth: Size> {
#[hdl(no_static)]
pub struct InstructionRenameInputInsn<C: Type + CpuConfigType> {
pub mop: MOp,
pub pc: UInt<64>,
pub renamed_dest: PRegNum<UnitNumWidth, OutRegNumWidth>,
pub renamed_dest: PRegNum<C>,
}
impl CpuConfig {
pub fn instruction_rename_input_insn(&self) -> InstructionRenameInputInsn<DynSize, DynSize> {
InstructionRenameInputInsn[self.unit_num_width()][self.out_reg_num_width]
}
#[hdl(no_static)]
struct InsnsInPrefixSummary<C: Type + CpuConfigType> {
all_ready: Bool,
ready_count: Length<FetchWidth<C>>,
retire_queue_used: Length<FetchWidth<C>>,
config: C,
}
type C = PhantomConst<CpuConfig>;
#[hdl]
struct InsnsInPrefixSummary<FetchWidth: Size> {
all_ready: Bool,
ready_count: Length<FetchWidth>,
retire_queue_used: Length<FetchWidth>,
}
pub type InstructionRenameInsnsOut<C: Type + CpuConfigType> = ArrayType<
ReadyValid<RenamedInsnData<C, RenamedMOp<PRegNumWidth<C>>, PRegNum<C>>>,
FetchWidth<C>,
>;
#[hdl_module]
pub fn instruction_rename(config: &CpuConfig) {
pub fn instruction_rename(config: PhantomConst<CpuConfig>) {
#[hdl]
let cd: ClockDomain = m.input();
#[hdl]
let insns_in: ReadyValidArray<InstructionRenameInputInsn<DynSize, DynSize>, DynSize> =
m.input(ReadyValidArray[config.instruction_rename_input_insn()][config.fetch_width.get()]);
let insns_in: ReadyValidArray<InstructionRenameInputInsn<C>, FetchWidth<C>> =
m.input(ReadyValidArray[InstructionRenameInputInsn[config]][FetchWidth[config]]);
#[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]
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]
let insns_out: Array<
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()],
);
let insns_out: InstructionRenameInsnsOut<C> = m.output(InstructionRenameInsnsOut[config]);
// TODO: handle resetting table after cancelling instructions
#[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) {
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]
let insns_in_prefix_summaries =
wire(Array[insns_in_prefix_summary_ty][config.fetch_width.get()]);
let insns_in_prefix_summaries = wire(ArrayType[insns_in_prefix_summary_ty][FetchWidth[config]]);
let insns_in_prefix_summaries_vec = PrefixSumAlgorithm::WorkEfficient.run(
(0..config.fetch_width.get()).map(|fetch_index| {
(0..FetchWidth[config]).map(|fetch_index| {
#[hdl]
let insns_in_prefix_summary_in = wire(insns_in_prefix_summary_ty);
#[hdl]
@ -84,6 +81,7 @@ pub fn instruction_rename(config: &CpuConfig) {
all_ready,
ready_count,
retire_queue_used,
config: _,
} = insns_in_prefix_summary_in;
connect(all_ready, insns_out[fetch_index].ready);
connect(
@ -112,6 +110,7 @@ pub fn instruction_rename(config: &CpuConfig) {
all_ready,
ready_count,
retire_queue_used,
config: _,
} = insns_in_prefix_summary_merge;
connect(all_ready, l.all_ready & r.all_ready);
#[hdl]
@ -143,16 +142,15 @@ pub fn instruction_rename(config: &CpuConfig) {
}
connect(
insns_in.ready,
insns_in_prefix_summaries[config.fetch_width.get() - 1].ready_count,
insns_in_prefix_summaries[FetchWidth[config] - 1].ready_count,
);
#[hdl]
let retire_queue_indexes =
wire(Array[config.retire_queue_index()][config.fetch_width.get() + 1]);
let retire_queue_indexes = wire(Array[RetireQueueIndex[config]][FetchWidth[config] + 1]);
connect(retire_queue_indexes[0], start_retire_queue_index);
connect(
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
.into_iter()
@ -171,7 +169,7 @@ pub fn instruction_rename(config: &CpuConfig) {
MOpTrait::for_each_src_reg(MOp.uninit(), &mut |_, src_index| {
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 {
port_configs.push(RenameTablePortConfig::Read {
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 {
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(
@ -203,16 +201,13 @@ pub fn instruction_rename(config: &CpuConfig) {
let read_port_index = fetch_index * src_reg_count;
let write_port_index = fetch_index * MOpDestReg::REG_COUNT;
#[hdl]
let InstructionRenameInputInsn::<_, _> {
let InstructionRenameInputInsn::<_> {
mop,
pc,
renamed_dest,
} = input_insn;
let insn_out = MOpTrait::map_regs(
mop,
(),
config.p_reg_num_width(),
&mut |src_reg, src_index| {
let insn_out =
MOpTrait::map_regs(mop, (), PRegNumWidth[config], &mut |src_reg, src_index| {
connect(
rename_table.read_ports[read_port_index + src_index].addr,
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]
.data
.cast_to_bits()
},
);
});
for (i, dest_reg) in MOpDestReg::regs(MOpTrait::dest_reg(mop))
.into_iter()
.enumerate()
@ -237,13 +231,13 @@ pub fn instruction_rename(config: &CpuConfig) {
}
let insn_out = UnitMOp::try_with_transformed_move_op(
insn_out,
config.renamed_mop().TransformedMove,
RenamedMOp[PRegNumWidth[config]].TransformedMove,
|insn_out: Expr<HdlOption<_>>, move_reg: Expr<MoveRegMOp<_, _>>| {
for i in 0..MOpDestReg::REG_COUNT {
// execute move by using same PRegNum as src[0] for dest
connect(
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

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information
use crate::{
config::CpuConfig,
config::{CpuConfig, CpuConfigType},
instruction::{MOpRegNum, PRegNum},
util::range_intersection,
};
@ -13,17 +13,17 @@ use fayalite::{
};
use std::{mem, ops::Range};
#[hdl]
pub struct RenameTableReadPort<UnitNumWidth: Size, OutRegNumWidth: Size> {
#[hdl(no_static)]
pub struct RenameTableReadPort<C: Type + CpuConfigType> {
pub addr: MOpRegNum,
#[hdl(flip)]
pub data: PRegNum<UnitNumWidth, OutRegNumWidth>,
pub data: PRegNum<C>,
}
#[hdl]
pub struct RenameTableWritePort<UnitNumWidth: Size, OutRegNumWidth: Size> {
#[hdl(no_static)]
pub struct RenameTableWritePort<C: Type + CpuConfigType> {
pub addr: MOpRegNum,
pub data: PRegNum<UnitNumWidth, OutRegNumWidth>,
pub data: PRegNum<C>,
}
#[derive(Clone, Debug)]
@ -32,6 +32,8 @@ pub enum RenameTablePortConfig {
Write { addr_range: Range<u32> },
}
type C = PhantomConst<CpuConfig>;
/// register rename table.
/// 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,
@ -40,7 +42,7 @@ pub enum RenameTablePortConfig {
/// 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.
#[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
.iter()
.filter(|v| matches!(v, RenameTablePortConfig::Read { .. }))
@ -53,16 +55,14 @@ pub fn rename_table(config: &CpuConfig, port_configs: &[RenameTablePortConfig])
#[hdl]
let cd: ClockDomain = m.input();
#[hdl]
let read_ports: Array<RenameTableReadPort<DynSize, DynSize>> = m.input(
Array[RenameTableReadPort[config.unit_num_width()][config.out_reg_num_width]][read_count],
);
let read_ports: Array<RenameTableReadPort<C>> =
m.input(Array[RenameTableReadPort[config]][read_count]);
#[hdl]
let write_ports: Array<RenameTableWritePort<DynSize, DynSize>> = m.input(
Array[RenameTableWritePort[config.unit_num_width()][config.out_reg_num_width]][write_count],
);
let write_ports: Array<RenameTableWritePort<C>> =
m.input(Array[RenameTableWritePort[config]][write_count]);
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(
@ -103,7 +103,7 @@ pub fn rename_table(config: &CpuConfig, port_configs: &[RenameTablePortConfig])
} else {
format!("mem_{:#x}_{:#x}", cur_addr_range.start, cur_addr_range.end)
},
config.p_reg_num(),
PRegNum[config],
SourceLocation::caller(),
);
mem.depth(cur_addr_range.len());

View file

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

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information
use crate::{
config::CpuConfig,
config::{CpuConfig, CpuConfigType, RetireQueueIndexWidth, UnitCount},
instruction::{
mop_enum, AluBranchMOp, LoadStoreMOp, MOp, MOpDestReg, MOpInto, MOpRegNum, MOpTrait,
RenamedMOp, UnitOutRegNum,
@ -16,7 +16,7 @@ use fayalite::{
prelude::*,
util::ready_valid::ReadyValid,
};
use std::marker::PhantomData;
use serde::{Deserialize, Serialize};
pub mod alu_branch;
pub mod unit_base;
@ -38,7 +38,7 @@ macro_rules! all_units {
}
) => {
$(#[$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 {
$(
$(#[$variant_meta])*
@ -47,7 +47,7 @@ macro_rules! all_units {
}
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 {
$($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)
#[hdl(cmp_eq)]
pub struct RetireQueueIndex<Width: Size> {
#[hdl(cmp_eq, no_static)]
pub struct RetireQueueIndex<C: Type + CpuConfigType> {
/// 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`
/// 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(
this: impl ToExpr<Type = Self>,
target: impl ToExpr<Type = Self>,
) -> Expr<SIntType<Width>> {
) -> Expr<SIntType<RetireQueueIndexWidth<C>>> {
let this = this.to_expr();
let target = target.to_expr();
assert_eq!(Expr::ty(this), Expr::ty(target));
@ -282,50 +283,32 @@ impl<Width: Size> RetireQueueIndex<Width> {
}
}
#[hdl]
pub struct RenamedInsnData<MOp, DestReg, RetireQueueIndexWidth: Size> {
pub retire_queue_index: RetireQueueIndex<RetireQueueIndexWidth>,
#[hdl(no_static)]
pub struct RenamedInsnData<C: Type + CpuConfigType, MOp, DestReg> {
pub retire_queue_index: RetireQueueIndex<C>,
pub pc: UInt<64>,
pub dest: DestReg,
pub mop: MOp,
}
#[hdl]
pub struct UnitForwardingInfo<UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size> {
pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<OutRegNumWidth>>, UnitCount>,
pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<OutRegNumWidth>>, UnitCount>,
pub _phantom: PhantomData<UnitNumWidth>,
#[hdl(no_static)]
pub struct UnitForwardingInfo<C: Type + CpuConfigType> {
pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<C>>, UnitCount<C>>,
pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<C>>, UnitCount<C>>,
}
#[hdl]
pub struct UnitToRegAlloc<
MOp: Type,
ExtraOut: Type,
UnitNumWidth: Size,
OutRegNumWidth: Size,
UnitCount: Size,
RetireQueueIndexWidth: Size,
> {
#[hdl(no_static)]
pub struct UnitToRegAlloc<C: Type + CpuConfigType, MOp: Type, ExtraOut: Type> {
#[hdl(flip)]
pub unit_forwarding_info: UnitForwardingInfo<UnitNumWidth, OutRegNumWidth, UnitCount>,
pub unit_forwarding_info: UnitForwardingInfo<C>,
#[hdl(flip)]
pub input:
ReadyValid<RenamedInsnData<MOp, UnitOutRegNum<OutRegNumWidth>, RetireQueueIndexWidth>>,
pub input: ReadyValid<RenamedInsnData<C, MOp, UnitOutRegNum<C>>>,
#[hdl(flip)]
pub cancel_input: HdlOption<UnitCancelInput<OutRegNumWidth>>,
pub output: HdlOption<UnitOutput<OutRegNumWidth, RetireQueueIndexWidth, ExtraOut>>,
pub cancel_input: HdlOption<UnitCancelInput<C>>,
pub output: HdlOption<UnitOutput<C, ExtraOut>>,
}
impl<
MOp: Type,
ExtraOut: Type,
UnitNumWidth: Size,
OutRegNumWidth: Size,
UnitCount: Size,
RetireQueueIndexWidth: Size,
>
UnitToRegAlloc<MOp, ExtraOut, UnitNumWidth, OutRegNumWidth, UnitCount, RetireQueueIndexWidth>
{
impl<C: Type + CpuConfigType, MOp: Type, ExtraOut: Type> UnitToRegAlloc<C, MOp, ExtraOut> {
pub fn mop_ty(self) -> MOp {
self.input.data.HdlSome.mop
}
@ -340,12 +323,16 @@ pub struct UnitResultCompleted<ExtraOut> {
pub extra_out: ExtraOut,
}
#[hdl(cmp_eq)]
pub struct UnitOutputWrite<OutRegNumWidth: Size> {
pub dest: UnitOutRegNum<OutRegNumWidth>,
#[hdl(cmp_eq, no_static)]
pub struct UnitOutputWrite<C: Type + CpuConfigType> {
pub dest: UnitOutRegNum<C>,
pub value: PRegValue,
}
#[hdl]
pub type UnitOutputWrites<C: Type + CpuConfigType> =
ArrayType<HdlOption<UnitOutputWrite<C>>, UnitCount<C>>;
#[hdl(cmp_eq)]
pub struct TrapData {
// TODO
@ -363,30 +350,28 @@ impl<ExtraOut: Type> UnitResult<ExtraOut> {
}
}
#[hdl]
pub struct UnitOutput<OutRegNumWidth: Size, RetireQueueIndexWidth: Size, ExtraOut> {
pub dest: UnitOutRegNum<OutRegNumWidth>,
pub retire_queue_index: RetireQueueIndex<RetireQueueIndexWidth>,
#[hdl(no_static)]
pub struct UnitOutput<C: Type + CpuConfigType, ExtraOut> {
pub dest: UnitOutRegNum<C>,
pub retire_queue_index: RetireQueueIndex<C>,
pub result: UnitResult<ExtraOut>,
}
impl<OutRegNumWidth: Size, RetireQueueIndexWidth: Size, ExtraOut: Type>
UnitOutput<OutRegNumWidth, RetireQueueIndexWidth, ExtraOut>
{
impl<C: Type + CpuConfigType, ExtraOut: Type> UnitOutput<C, ExtraOut> {
pub fn extra_out_ty(self) -> ExtraOut {
self.result.extra_out_ty()
}
}
#[hdl(cmp_eq)]
pub struct UnitCancelInput<RetireQueueIndexWidth: Size> {
pub target: RetireQueueIndex<RetireQueueIndexWidth>,
#[hdl(cmp_eq, no_static)]
pub struct UnitCancelInput<C: Type + CpuConfigType> {
pub target: RetireQueueIndex<C>,
}
impl<RetireQueueIndexWidth: Size> UnitCancelInput<RetireQueueIndexWidth> {
impl<C: Type + CpuConfigType> UnitCancelInput<C> {
pub fn is_canceled(
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> {
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(
&self,
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>;
@ -471,7 +456,7 @@ impl UnitTrait for DynUnit {
fn unit_to_reg_alloc(
&self,
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)
}
@ -523,7 +508,7 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T
fn unit_to_reg_alloc(
&self,
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(
self.0.unit_to_reg_alloc(Expr::from_bundle(this)),
))

View file

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

View file

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