Compare commits
2 commits
3a649c8997
...
782a44858c
| Author | SHA1 | Date | |
|---|---|---|---|
| 782a44858c | |||
| 9fa959652e |
11 changed files with 269 additions and 267 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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"] }
|
||||
|
|
|
|||
|
|
@ -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)'] }
|
||||
|
|
|
|||
|
|
@ -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()]
|
||||
|
||||
mod sealed {
|
||||
pub trait Sealed {}
|
||||
}
|
||||
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 sealed::Sealed for PhantomConst<CpuConfig> {}
|
||||
|
||||
pub trait CpuConfigType: Type + ToExpr<Type = Self> + sealed::Sealed {
|
||||
fn get(self) -> Interned<CpuConfig>;
|
||||
}
|
||||
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]
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue