forked from libre-chip/cpu
Compare commits
No commits in common. "rename-execute-retire" and "master" have entirely different histories.
rename-exe
...
master
8 changed files with 156 additions and 420 deletions
|
|
@ -33,6 +33,3 @@ hex-literal.workspace = true
|
||||||
regex = "1.12.2"
|
regex = "1.12.2"
|
||||||
sha2.workspace = true
|
sha2.workspace = true
|
||||||
which.workspace = true
|
which.workspace = true
|
||||||
|
|
||||||
[lints.rust]
|
|
||||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(todo)'] }
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
// 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::{instruction::CONST_ZERO_UNIT_NUM, unit::UnitKind};
|
use crate::{
|
||||||
|
instruction::{CONST_ZERO_UNIT_NUM, MOpTrait, PRegNum, RenamedMOp, UnitNum, UnitOutRegNum},
|
||||||
|
unit::{
|
||||||
|
UnitCancelInput, UnitKind, UnitOutputWrite,
|
||||||
|
unit_base::{UnitForwardingInfo, UnitToRegAlloc},
|
||||||
|
},
|
||||||
|
};
|
||||||
use fayalite::prelude::*;
|
use fayalite::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
|
|
@ -95,14 +101,55 @@ 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 {
|
pub fn p_reg_num_width(&self) -> usize {
|
||||||
self.unit_num_width() + self.out_reg_num_width
|
self.unit_num_width() + self.out_reg_num_width
|
||||||
}
|
}
|
||||||
|
pub fn renamed_mop_in_unit(&self) -> RenamedMOp<UnitOutRegNum<DynSize>, DynSize> {
|
||||||
|
RenamedMOp[self.unit_out_reg_num()][self.p_reg_num_width()]
|
||||||
|
}
|
||||||
|
pub fn unit_output_write(&self) -> UnitOutputWrite<DynSize> {
|
||||||
|
UnitOutputWrite[self.out_reg_num_width]
|
||||||
|
}
|
||||||
|
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_cancel_input(&self) -> UnitCancelInput<DynSize> {
|
||||||
|
UnitCancelInput[self.out_reg_num_width]
|
||||||
|
}
|
||||||
|
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 = UnitOutRegNum<DynSize>, SrcRegWidth = DynSize>,
|
||||||
|
ExtraOut: Type,
|
||||||
|
>(
|
||||||
|
&self,
|
||||||
|
mop_ty: MOp,
|
||||||
|
extra_out_ty: ExtraOut,
|
||||||
|
) -> UnitToRegAlloc<MOp, ExtraOut, DynSize, DynSize, DynSize> {
|
||||||
|
assert_eq!(
|
||||||
|
mop_ty.dest_reg_ty(),
|
||||||
|
self.unit_out_reg_num(),
|
||||||
|
"inconsistent types",
|
||||||
|
);
|
||||||
|
UnitToRegAlloc[mop_ty][extra_out_ty][self.unit_num_width()][self.out_reg_num_width]
|
||||||
|
[self.non_const_unit_nums().len()]
|
||||||
|
}
|
||||||
pub fn fetch_width_in_bytes(&self) -> usize {
|
pub fn fetch_width_in_bytes(&self) -> usize {
|
||||||
1usize
|
1usize
|
||||||
.checked_shl(self.log2_fetch_width_in_bytes.into())
|
.checked_shl(self.log2_fetch_width_in_bytes.into())
|
||||||
|
|
@ -141,18 +188,6 @@ impl CpuConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(get(|c| c.out_reg_num_width))]
|
|
||||||
pub type CpuConfigOutRegNumWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
|
|
||||||
|
|
||||||
#[hdl(get(|c| c.unit_num_width()))]
|
|
||||||
pub type CpuConfigUnitNumWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
|
|
||||||
|
|
||||||
#[hdl(get(|c| c.p_reg_num_width()))]
|
|
||||||
pub type CpuConfigPRegNumWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
|
|
||||||
|
|
||||||
#[hdl(get(|c| c.non_const_unit_nums().len()))]
|
|
||||||
pub type CpuConfigUnitCount<C: PhantomConstGet<CpuConfig>> = DynSize;
|
|
||||||
|
|
||||||
#[hdl(get(|c| c.fetch_width.get()))]
|
#[hdl(get(|c| c.fetch_width.get()))]
|
||||||
pub type CpuConfigFetchWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
|
pub type CpuConfigFetchWidth<C: PhantomConstGet<CpuConfig>> = DynSize;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// 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::{
|
||||||
config::{CpuConfig, CpuConfigOutRegNumWidth, CpuConfigUnitNumWidth, PhantomConstCpuConfig},
|
|
||||||
register::{PRegFlags, PRegFlagsViewTrait, PRegValue, ViewUnused},
|
register::{PRegFlags, PRegFlagsViewTrait, PRegValue, ViewUnused},
|
||||||
unit::UnitMOp,
|
unit::UnitMOp,
|
||||||
util::{Rotate, range_u32_len},
|
util::{Rotate, range_u32_len},
|
||||||
|
|
@ -2596,21 +2595,19 @@ impl<DestReg: Type, SrcRegWidth: Size> MoveRegMOp<DestReg, SrcRegWidth> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq, no_static)]
|
#[hdl(cmp_eq)]
|
||||||
/// 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<C: PhantomConstGet<CpuConfig>> {
|
pub struct UnitNum<Width: Size> {
|
||||||
pub adj_value: UIntType<CpuConfigUnitNumWidth<C>>,
|
pub adj_value: UIntType<Width>,
|
||||||
pub config: C,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: PhantomConstCpuConfig> UnitNum<C> {
|
impl<Width: Size> UnitNum<Width> {
|
||||||
#[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]
|
||||||
|
|
@ -2618,7 +2615,6 @@ impl<C: PhantomConstCpuConfig> UnitNum<C> {
|
||||||
#[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> {
|
||||||
|
|
@ -2626,9 +2622,7 @@ impl<C: PhantomConstCpuConfig> UnitNum<C> {
|
||||||
expr.ty().from_index(index).adj_value.cmp_eq(expr.adj_value)
|
expr.ty().from_index(index).adj_value.cmp_eq(expr.adj_value)
|
||||||
}
|
}
|
||||||
#[hdl]
|
#[hdl]
|
||||||
pub fn as_index(
|
pub fn as_index(expr: impl ToExpr<Type = Self>) -> Expr<HdlOption<UIntType<Width>>> {
|
||||||
expr: impl ToExpr<Type = Self>,
|
|
||||||
) -> Expr<HdlOption<UIntType<CpuConfigUnitNumWidth<C>>>> {
|
|
||||||
let expr = expr.to_expr();
|
let expr = expr.to_expr();
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let unit_index = wire(HdlOption[expr.ty().adj_value]);
|
let unit_index = wire(HdlOption[expr.ty().adj_value]);
|
||||||
|
|
@ -2646,20 +2640,19 @@ impl<C: PhantomConstCpuConfig> UnitNum<C> {
|
||||||
|
|
||||||
pub const CONST_ZERO_UNIT_NUM: usize = 0;
|
pub const CONST_ZERO_UNIT_NUM: usize = 0;
|
||||||
|
|
||||||
#[hdl(cmp_eq, no_static)]
|
#[hdl(cmp_eq)]
|
||||||
pub struct UnitOutRegNum<C: PhantomConstGet<CpuConfig>> {
|
pub struct UnitOutRegNum<Width: Size> {
|
||||||
pub value: UIntType<CpuConfigOutRegNumWidth<C>>,
|
pub value: UIntType<Width>,
|
||||||
pub config: C,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq, no_static)]
|
#[hdl(cmp_eq)]
|
||||||
/// Physical Register Number -- registers in the CPU's backend
|
/// Physical Register Number -- registers in the CPU's backend
|
||||||
pub struct PRegNum<C: PhantomConstGet<CpuConfig>> {
|
pub struct PRegNum<UnitNumWidth: Size, OutRegNumWidth: Size> {
|
||||||
pub unit_num: UnitNum<C>,
|
pub unit_num: UnitNum<UnitNumWidth>,
|
||||||
pub unit_out_reg: UnitOutRegNum<C>,
|
pub unit_out_reg: UnitOutRegNum<OutRegNumWidth>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: PhantomConstCpuConfig> PRegNum<C> {
|
impl<UnitNumWidth: Size, OutRegNumWidth: Size> PRegNum<UnitNumWidth, OutRegNumWidth> {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
pub fn const_zero(self) -> Expr<Self> {
|
pub fn const_zero(self) -> Expr<Self> {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -2668,7 +2661,6 @@ impl<C: PhantomConstCpuConfig> PRegNum<C> {
|
||||||
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,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,7 @@ pub mod instruction;
|
||||||
pub mod main_memory_and_io;
|
pub mod main_memory_and_io;
|
||||||
pub mod next_pc;
|
pub mod next_pc;
|
||||||
pub mod powerisa_instructions_xml;
|
pub mod powerisa_instructions_xml;
|
||||||
#[cfg(todo)]
|
|
||||||
pub mod reg_alloc;
|
pub mod reg_alloc;
|
||||||
pub mod register;
|
pub mod register;
|
||||||
pub mod rename_execute_retire;
|
|
||||||
pub mod unit;
|
pub mod unit;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
|
||||||
|
|
@ -1,295 +0,0 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
||||||
// See Notices.txt for copyright information
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
config::{
|
|
||||||
CpuConfig, CpuConfigFetchWidth, CpuConfigPRegNumWidth, CpuConfigRobSize,
|
|
||||||
PhantomConstCpuConfig,
|
|
||||||
},
|
|
||||||
instruction::{MOp, MOpRegNum, PRegNum, RenamedMOp},
|
|
||||||
next_pc::{RetireToNextPcInterfaceInner, SimValueDefault},
|
|
||||||
util::array_vec::ArrayVec,
|
|
||||||
};
|
|
||||||
use fayalite::{
|
|
||||||
int::UIntInRangeInclusiveType, prelude::*, ty::OpaqueSimValue, util::ready_valid::ReadyValid,
|
|
||||||
};
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
|
|
||||||
#[hdl]
|
|
||||||
/// A µOp along with the state needed for this instance of the µOp.
|
|
||||||
pub struct MOpInstance<MOp> {
|
|
||||||
pub fetch_block_id: UInt<8>,
|
|
||||||
pub id: UInt<12>,
|
|
||||||
pub pc: UInt<64>,
|
|
||||||
/// initialized to 0 by decoder, overwritten by `next_pc()`
|
|
||||||
pub predicted_next_pc: UInt<64>,
|
|
||||||
pub size_in_bytes: UInt<4>,
|
|
||||||
/// `true` if this µOp is the first µOp in the ISA-level instruction.
|
|
||||||
/// In general, a single µOp can't be cancelled by itself,
|
|
||||||
/// it needs to be cancelled along with all other µOps that
|
|
||||||
/// come from the same ISA-level instruction.
|
|
||||||
pub is_first_mop_in_insn: Bool,
|
|
||||||
pub mop: MOp,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl(no_static)]
|
|
||||||
/// TODO: merge with [`crate::next_pc::PostDecodeOutputInterface`]
|
|
||||||
pub struct PostDecodeOutputInterface<C: PhantomConstGet<CpuConfig>> {
|
|
||||||
pub insns: ArrayVec<MOpInstance<MOp>, CpuConfigFetchWidth<C>>,
|
|
||||||
#[hdl(flip)]
|
|
||||||
pub ready: UIntInRangeInclusiveType<ConstUsize<0>, CpuConfigFetchWidth<C>>,
|
|
||||||
/// tells the rename/execute/retire circuit to cancel all non-retired instructions
|
|
||||||
pub cancel: ReadyValid<()>,
|
|
||||||
pub config: C,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl(no_static)]
|
|
||||||
/// handles updating speculative branch predictor state (e.g. branch histories)
|
|
||||||
/// when instructions retire, as well as updating state when a
|
|
||||||
/// branch instruction is mis-speculated.
|
|
||||||
pub struct RetireToNextPcInterface<C: PhantomConstGet<CpuConfig>> {
|
|
||||||
pub inner: ReadyValid<RetireToNextPcInterfaceInner<C>>,
|
|
||||||
/// only for debugging
|
|
||||||
pub next_insns: HdlOption<ArrayVec<MOpInstance<MOp>, CpuConfigRobSize<C>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn zeroed<T: Type>(ty: T) -> SimValue<T> {
|
|
||||||
SimValue::from_opaque(
|
|
||||||
ty,
|
|
||||||
OpaqueSimValue::from_bits(UInt::new(ty.canonical().bit_width()).zero()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C: PhantomConstCpuConfig> SimValueDefault for RenameExecuteRetireDebugState<C> {
|
|
||||||
fn sim_value_default(self) -> SimValue<Self> {
|
|
||||||
zeroed(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct RenameTable<C: PhantomConstCpuConfig> {
|
|
||||||
entries: Box<[SimValue<PRegNum<C>>; 1 << MOpRegNum::WIDTH]>,
|
|
||||||
config: C,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C: PhantomConstCpuConfig> RenameTable<C> {
|
|
||||||
fn new(config: C) -> Self {
|
|
||||||
Self {
|
|
||||||
entries: vec![PRegNum[config].const_zero().into_sim_value(); 1 << MOpRegNum::WIDTH]
|
|
||||||
.try_into()
|
|
||||||
.expect("size is known to match"),
|
|
||||||
config,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn to_debug_state(&self) -> SimValue<Array<PRegNum<C>, { 1 << MOpRegNum::WIDTH }>> {
|
|
||||||
self.entries
|
|
||||||
.to_sim_value_with_type(Array[PRegNum[self.config]][ConstUsize])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl(no_static)]
|
|
||||||
struct RobEntryDebugState<C: PhantomConstGet<CpuConfig>> {
|
|
||||||
mop: MOpInstance<RenamedMOp<PRegNum<C>, CpuConfigPRegNumWidth<C>>>,
|
|
||||||
config: C,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C: PhantomConstCpuConfig> SimValueDefault for RobEntryDebugState<C> {
|
|
||||||
fn sim_value_default(self) -> SimValue<Self> {
|
|
||||||
zeroed(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct RobEntry<C: PhantomConstCpuConfig> {
|
|
||||||
mop: SimValue<MOpInstance<RenamedMOp<PRegNum<C>, CpuConfigPRegNumWidth<C>>>>,
|
|
||||||
config: C,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl]
|
|
||||||
struct OrigMOpQueueEntryDebugState {
|
|
||||||
mop: MOpInstance<MOp>,
|
|
||||||
/// number of renamed µOps that this non-renamed µOp corresponds to
|
|
||||||
renamed_mop_count: UInt<8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct OrigMOpQueueEntry {
|
|
||||||
mop: SimValue<MOpInstance<MOp>>,
|
|
||||||
/// number of renamed µOps that this non-renamed µOp corresponds to
|
|
||||||
renamed_mop_count: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl(no_static)]
|
|
||||||
pub struct RenameExecuteRetireDebugState<C: PhantomConstGet<CpuConfig>> {
|
|
||||||
rename_table: Array<PRegNum<C>, { 1 << MOpRegNum::WIDTH }>,
|
|
||||||
retire_rename_table: Array<PRegNum<C>, { 1 << MOpRegNum::WIDTH }>,
|
|
||||||
rob: ArrayVec<RobEntryDebugState<C>, CpuConfigRobSize<C>>,
|
|
||||||
orig_mop_queue: ArrayVec<OrigMOpQueueEntryDebugState, CpuConfigRobSize<C>>,
|
|
||||||
cancelling: Bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct RenameExecuteRetireState<C: PhantomConstCpuConfig> {
|
|
||||||
rename_table: RenameTable<C>,
|
|
||||||
retire_rename_table: RenameTable<C>,
|
|
||||||
rob: VecDeque<RobEntry<C>>,
|
|
||||||
orig_mop_queue: VecDeque<OrigMOpQueueEntry>,
|
|
||||||
cancelling: bool,
|
|
||||||
config: C,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C: PhantomConstCpuConfig> RenameExecuteRetireState<C> {
|
|
||||||
fn new(config: C) -> Self {
|
|
||||||
let rename_table = RenameTable::new(config);
|
|
||||||
Self {
|
|
||||||
rename_table: rename_table.clone(),
|
|
||||||
retire_rename_table: rename_table,
|
|
||||||
rob: VecDeque::with_capacity(CpuConfigRobSize[config]),
|
|
||||||
orig_mop_queue: VecDeque::with_capacity(CpuConfigRobSize[config]),
|
|
||||||
cancelling: false,
|
|
||||||
config,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
async fn write_for_debug(
|
|
||||||
&self,
|
|
||||||
sim: &mut ExternModuleSimulationState,
|
|
||||||
state_for_debug: Expr<RenameExecuteRetireDebugState<C>>,
|
|
||||||
) {
|
|
||||||
let Self {
|
|
||||||
ref rename_table,
|
|
||||||
ref retire_rename_table,
|
|
||||||
ref rob,
|
|
||||||
ref orig_mop_queue,
|
|
||||||
cancelling,
|
|
||||||
config,
|
|
||||||
} = *self;
|
|
||||||
sim.write(
|
|
||||||
state_for_debug,
|
|
||||||
#[hdl(sim)]
|
|
||||||
RenameExecuteRetireDebugState::<_> {
|
|
||||||
rename_table: rename_table.to_debug_state(),
|
|
||||||
retire_rename_table: retire_rename_table.to_debug_state(),
|
|
||||||
rob: state_for_debug
|
|
||||||
.ty()
|
|
||||||
.rob
|
|
||||||
.from_iter_sim(
|
|
||||||
zeroed(RobEntryDebugState[config]),
|
|
||||||
rob.iter().map(|entry| {
|
|
||||||
let RobEntry { mop, config: _ } = entry;
|
|
||||||
#[hdl(sim)]
|
|
||||||
RobEntryDebugState::<_> { mop, config }
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.expect("known to fit"),
|
|
||||||
orig_mop_queue: state_for_debug
|
|
||||||
.ty()
|
|
||||||
.orig_mop_queue
|
|
||||||
.from_iter_sim(
|
|
||||||
zeroed(OrigMOpQueueEntryDebugState),
|
|
||||||
orig_mop_queue.iter().map(|entry| {
|
|
||||||
let OrigMOpQueueEntry {
|
|
||||||
mop,
|
|
||||||
renamed_mop_count,
|
|
||||||
} = entry;
|
|
||||||
#[hdl(sim)]
|
|
||||||
OrigMOpQueueEntryDebugState {
|
|
||||||
mop,
|
|
||||||
renamed_mop_count,
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.expect("known to fit"),
|
|
||||||
cancelling,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
#[hdl]
|
|
||||||
async fn write_to_next_pc_next_insns(
|
|
||||||
&self,
|
|
||||||
sim: &mut ExternModuleSimulationState,
|
|
||||||
next_insns: Expr<HdlOption<ArrayVec<MOpInstance<MOp>, CpuConfigRobSize<C>>>>,
|
|
||||||
) {
|
|
||||||
sim.write(
|
|
||||||
next_insns,
|
|
||||||
#[hdl(sim)]
|
|
||||||
(next_insns.ty()).HdlSome(
|
|
||||||
next_insns
|
|
||||||
.ty()
|
|
||||||
.HdlSome
|
|
||||||
.from_iter_sim(
|
|
||||||
zeroed(MOpInstance[MOp]),
|
|
||||||
self.orig_mop_queue.iter().map(|entry| &entry.mop),
|
|
||||||
)
|
|
||||||
.expect("known to fit"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl]
|
|
||||||
async fn rename_execute_retire_run(
|
|
||||||
mut sim: ExternModuleSimulationState,
|
|
||||||
cd: Expr<ClockDomain>,
|
|
||||||
from_post_decode: Expr<PostDecodeOutputInterface<PhantomConst<CpuConfig>>>,
|
|
||||||
to_next_pc: Expr<RetireToNextPcInterface<PhantomConst<CpuConfig>>>,
|
|
||||||
state_for_debug: Expr<RenameExecuteRetireDebugState<PhantomConst<CpuConfig>>>,
|
|
||||||
config: PhantomConst<CpuConfig>,
|
|
||||||
) {
|
|
||||||
let mut state = RenameExecuteRetireState::new(config);
|
|
||||||
loop {
|
|
||||||
state
|
|
||||||
.write_to_next_pc_next_insns(&mut sim, to_next_pc.next_insns)
|
|
||||||
.await;
|
|
||||||
state.write_for_debug(&mut sim, state_for_debug).await;
|
|
||||||
sim.wait_for_clock_edge(cd.clk).await;
|
|
||||||
todo!("step state based on I/O");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[hdl_module(extern)]
|
|
||||||
pub fn rename_execute_retire(config: PhantomConst<CpuConfig>) {
|
|
||||||
#[hdl]
|
|
||||||
let cd: ClockDomain = m.input();
|
|
||||||
#[hdl]
|
|
||||||
let from_post_decode: PostDecodeOutputInterface<PhantomConst<CpuConfig>> =
|
|
||||||
m.input(PostDecodeOutputInterface[config]);
|
|
||||||
#[hdl]
|
|
||||||
let to_next_pc: RetireToNextPcInterface<PhantomConst<CpuConfig>> =
|
|
||||||
m.output(RetireToNextPcInterface[config]);
|
|
||||||
#[hdl]
|
|
||||||
let state_for_debug: RenameExecuteRetireDebugState<PhantomConst<CpuConfig>> =
|
|
||||||
m.output(RenameExecuteRetireDebugState[config]);
|
|
||||||
m.register_clock_for_past(cd.clk);
|
|
||||||
m.extern_module_simulation_fn(
|
|
||||||
(cd, from_post_decode, to_next_pc, state_for_debug, config),
|
|
||||||
|(cd, from_post_decode, to_next_pc, state_for_debug, config), mut sim| async move {
|
|
||||||
sim.write(state_for_debug, state_for_debug.ty().sim_value_default())
|
|
||||||
.await;
|
|
||||||
sim.resettable(
|
|
||||||
cd,
|
|
||||||
|mut sim: ExternModuleSimulationState| async move {
|
|
||||||
sim.write(from_post_decode.ready, 0usize).await;
|
|
||||||
sim.write(from_post_decode.cancel.ready, false).await;
|
|
||||||
sim.write(to_next_pc.inner.data, to_next_pc.ty().inner.data.HdlNone())
|
|
||||||
.await;
|
|
||||||
sim.write(to_next_pc.next_insns, to_next_pc.ty().next_insns.HdlNone())
|
|
||||||
.await;
|
|
||||||
},
|
|
||||||
|sim, ()| {
|
|
||||||
rename_execute_retire_run(
|
|
||||||
sim,
|
|
||||||
cd,
|
|
||||||
from_post_decode,
|
|
||||||
to_next_pc,
|
|
||||||
state_for_debug,
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{CpuConfig, PhantomConstCpuConfig},
|
config::CpuConfig,
|
||||||
instruction::{
|
instruction::{
|
||||||
AluBranchMOp, LoadStoreMOp, MOp, MOpDestReg, MOpInto, MOpRegNum, MOpTrait,
|
AluBranchMOp, LoadStoreMOp, MOp, MOpDestReg, MOpInto, MOpRegNum, MOpTrait,
|
||||||
MOpVariantVisitOps, MOpVariantVisitor, MOpVisitVariants, RenamedMOp, UnitOutRegNum,
|
MOpVariantVisitOps, MOpVariantVisitor, MOpVisitVariants, RenamedMOp, UnitOutRegNum,
|
||||||
|
|
@ -48,7 +48,7 @@ macro_rules! all_units {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $UnitKind {
|
impl $UnitKind {
|
||||||
pub fn unit(self, config: PhantomConst<CpuConfig>, unit_index: usize) -> DynUnit {
|
pub fn unit(self, config: &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),)*
|
||||||
}
|
}
|
||||||
|
|
@ -277,9 +277,9 @@ pub struct UnitResultCompleted<ExtraOut> {
|
||||||
pub extra_out: ExtraOut,
|
pub extra_out: ExtraOut,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(cmp_eq, no_static)]
|
#[hdl(cmp_eq)]
|
||||||
pub struct UnitOutputWrite<C: PhantomConstGet<CpuConfig>> {
|
pub struct UnitOutputWrite<OutRegNumWidth: Size> {
|
||||||
pub which: UnitOutRegNum<C>,
|
pub which: UnitOutRegNum<OutRegNumWidth>,
|
||||||
pub value: PRegValue,
|
pub value: PRegValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -300,21 +300,21 @@ impl<ExtraOut: Type> UnitResult<ExtraOut> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(no_static)]
|
#[hdl]
|
||||||
pub struct UnitOutput<C: PhantomConstGet<CpuConfig>, ExtraOut> {
|
pub struct UnitOutput<OutRegNumWidth: Size, ExtraOut> {
|
||||||
pub which: UnitOutRegNum<C>,
|
pub which: UnitOutRegNum<OutRegNumWidth>,
|
||||||
pub result: UnitResult<ExtraOut>,
|
pub result: UnitResult<ExtraOut>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: PhantomConstCpuConfig, ExtraOut: Type> UnitOutput<C, ExtraOut> {
|
impl<OutRegNumWidth: Size, ExtraOut: Type> UnitOutput<OutRegNumWidth, 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, no_static)]
|
#[hdl(cmp_eq)]
|
||||||
pub struct UnitCancelInput<C: PhantomConstGet<CpuConfig>> {
|
pub struct UnitCancelInput<OutRegNumWidth: Size> {
|
||||||
pub which: UnitOutRegNum<C>,
|
pub which: UnitOutRegNum<OutRegNumWidth>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait UnitTrait:
|
pub trait UnitTrait:
|
||||||
|
|
@ -332,7 +332,7 @@ pub trait UnitTrait:
|
||||||
|
|
||||||
fn extract_mop(
|
fn extract_mop(
|
||||||
&self,
|
&self,
|
||||||
mop: Expr<RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||||
) -> Expr<HdlOption<Self::MOp>>;
|
) -> Expr<HdlOption<Self::MOp>>;
|
||||||
|
|
||||||
fn module(&self) -> Interned<Module<Self::Type>>;
|
fn module(&self) -> Interned<Module<Self::Type>>;
|
||||||
|
|
@ -340,7 +340,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<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>>;
|
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>>;
|
||||||
|
|
||||||
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain>;
|
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain>;
|
||||||
|
|
||||||
|
|
@ -390,7 +390,7 @@ impl UnitTrait for DynUnit {
|
||||||
|
|
||||||
fn extract_mop(
|
fn extract_mop(
|
||||||
&self,
|
&self,
|
||||||
mop: Expr<RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||||
) -> Expr<HdlOption<Self::MOp>> {
|
) -> Expr<HdlOption<Self::MOp>> {
|
||||||
self.unit.extract_mop(mop)
|
self.unit.extract_mop(mop)
|
||||||
}
|
}
|
||||||
|
|
@ -402,7 +402,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<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
|
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
|
||||||
self.unit.unit_to_reg_alloc(this)
|
self.unit.unit_to_reg_alloc(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -445,7 +445,7 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T
|
||||||
|
|
||||||
fn extract_mop(
|
fn extract_mop(
|
||||||
&self,
|
&self,
|
||||||
mop: Expr<RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||||
) -> Expr<HdlOption<Self::MOp>> {
|
) -> Expr<HdlOption<Self::MOp>> {
|
||||||
Expr::from_enum(Expr::as_enum(self.0.extract_mop(mop)))
|
Expr::from_enum(Expr::as_enum(self.0.extract_mop(mop)))
|
||||||
}
|
}
|
||||||
|
|
@ -457,7 +457,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<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
|
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
|
||||||
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)),
|
||||||
))
|
))
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,16 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use fayalite::{
|
use fayalite::{
|
||||||
intern::Interned, module::wire_with_loc, prelude::*, util::ready_valid::ReadyValid,
|
intern::{Intern, Interned},
|
||||||
|
module::wire_with_loc,
|
||||||
|
prelude::*,
|
||||||
|
util::ready_valid::ReadyValid,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, ops::RangeTo};
|
use std::{collections::HashMap, ops::RangeTo};
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn add_sub<SrcCount: KnownSize>(
|
fn add_sub<SrcCount: KnownSize>(
|
||||||
mop: Expr<AddSubMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, SrcCount>>,
|
mop: Expr<AddSubMOp<UnitOutRegNum<DynSize>, DynSize, SrcCount>>,
|
||||||
pc: Expr<UInt<64>>,
|
pc: Expr<UInt<64>>,
|
||||||
flags_mode: Expr<FlagsMode>,
|
flags_mode: Expr<FlagsMode>,
|
||||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||||
|
|
@ -242,7 +245,7 @@ fn add_sub<SrcCount: KnownSize>(
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn logical_flags(
|
fn logical_flags(
|
||||||
mop: Expr<LogicalFlagsMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
mop: Expr<LogicalFlagsMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||||
flags_mode: Expr<FlagsMode>,
|
flags_mode: Expr<FlagsMode>,
|
||||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||||
) -> Expr<UnitResultCompleted<()>> {
|
) -> Expr<UnitResultCompleted<()>> {
|
||||||
|
|
@ -256,7 +259,7 @@ fn logical_flags(
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn logical(
|
fn logical(
|
||||||
mop: Expr<LogicalMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, ConstUsize<2>>>,
|
mop: Expr<LogicalMOp<UnitOutRegNum<DynSize>, DynSize, ConstUsize<2>>>,
|
||||||
flags_mode: Expr<FlagsMode>,
|
flags_mode: Expr<FlagsMode>,
|
||||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||||
) -> Expr<UnitResultCompleted<()>> {
|
) -> Expr<UnitResultCompleted<()>> {
|
||||||
|
|
@ -270,7 +273,7 @@ fn logical(
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn logical_i(
|
fn logical_i(
|
||||||
mop: Expr<LogicalMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, ConstUsize<1>>>,
|
mop: Expr<LogicalMOp<UnitOutRegNum<DynSize>, DynSize, ConstUsize<1>>>,
|
||||||
flags_mode: Expr<FlagsMode>,
|
flags_mode: Expr<FlagsMode>,
|
||||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||||
) -> Expr<UnitResultCompleted<()>> {
|
) -> Expr<UnitResultCompleted<()>> {
|
||||||
|
|
@ -284,7 +287,7 @@ fn logical_i(
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn shift_rotate(
|
fn shift_rotate(
|
||||||
mop: Expr<ShiftRotateMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
mop: Expr<ShiftRotateMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||||
flags_mode: Expr<FlagsMode>,
|
flags_mode: Expr<FlagsMode>,
|
||||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||||
) -> Expr<UnitResultCompleted<()>> {
|
) -> Expr<UnitResultCompleted<()>> {
|
||||||
|
|
@ -298,7 +301,7 @@ fn shift_rotate(
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn compare<SrcCount: KnownSize>(
|
fn compare<SrcCount: KnownSize>(
|
||||||
mop: Expr<CompareMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, SrcCount>>,
|
mop: Expr<CompareMOp<UnitOutRegNum<DynSize>, DynSize, SrcCount>>,
|
||||||
flags_mode: Expr<FlagsMode>,
|
flags_mode: Expr<FlagsMode>,
|
||||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||||
) -> Expr<UnitResultCompleted<()>> {
|
) -> Expr<UnitResultCompleted<()>> {
|
||||||
|
|
@ -312,7 +315,7 @@ fn compare<SrcCount: KnownSize>(
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn branch<SrcCount: KnownSize>(
|
fn branch<SrcCount: KnownSize>(
|
||||||
mop: Expr<BranchMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize, SrcCount>>,
|
mop: Expr<BranchMOp<UnitOutRegNum<DynSize>, DynSize, SrcCount>>,
|
||||||
pc: Expr<UInt<64>>,
|
pc: Expr<UInt<64>>,
|
||||||
flags_mode: Expr<FlagsMode>,
|
flags_mode: Expr<FlagsMode>,
|
||||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||||
|
|
@ -327,7 +330,7 @@ fn branch<SrcCount: KnownSize>(
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn read_special(
|
fn read_special(
|
||||||
mop: Expr<ReadSpecialMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
mop: Expr<ReadSpecialMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||||
pc: Expr<UInt<64>>,
|
pc: Expr<UInt<64>>,
|
||||||
flags_mode: Expr<FlagsMode>,
|
flags_mode: Expr<FlagsMode>,
|
||||||
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||||
|
|
@ -341,18 +344,20 @@ fn read_special(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl_module]
|
#[hdl_module]
|
||||||
pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) {
|
pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let cd: ClockDomain = m.input();
|
let cd: ClockDomain = m.input();
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let unit_to_reg_alloc: UnitToRegAlloc<
|
let unit_to_reg_alloc: UnitToRegAlloc<
|
||||||
PhantomConst<CpuConfig>,
|
AluBranchMOp<UnitOutRegNum<DynSize>, DynSize>,
|
||||||
AluBranchMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>,
|
|
||||||
(),
|
(),
|
||||||
> = m.output(
|
DynSize,
|
||||||
UnitToRegAlloc[config][AluBranchMOp[UnitOutRegNum[config]][config.get().p_reg_num_width()]]
|
DynSize,
|
||||||
[()],
|
DynSize,
|
||||||
);
|
> = m.output(config.unit_to_reg_alloc(
|
||||||
|
AluBranchMOp[config.unit_out_reg_num()][config.p_reg_num_width()],
|
||||||
|
(),
|
||||||
|
));
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let global_state: GlobalState = m.input();
|
let global_state: GlobalState = m.input();
|
||||||
|
|
||||||
|
|
@ -370,11 +375,10 @@ pub fn alu_branch(config: PhantomConst<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::<_, _> {
|
let ExecuteStart::<_> {
|
||||||
mop,
|
mop,
|
||||||
pc,
|
pc,
|
||||||
src_values,
|
src_values,
|
||||||
config: _,
|
|
||||||
} = execute_start;
|
} = execute_start;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
match mop {
|
match mop {
|
||||||
|
|
@ -576,14 +580,14 @@ pub fn alu_branch(config: PhantomConst<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: PhantomConst<CpuConfig>,
|
config: Interned<CpuConfig>,
|
||||||
module: Interned<Module<alu_branch>>,
|
module: Interned<Module<alu_branch>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AluBranch {
|
impl AluBranch {
|
||||||
pub fn new(config: PhantomConst<CpuConfig>, unit_index: usize) -> Self {
|
pub fn new(config: &CpuConfig, unit_index: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
config,
|
config: config.intern(),
|
||||||
module: alu_branch(config, unit_index),
|
module: alu_branch(config, unit_index),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -592,7 +596,7 @@ impl AluBranch {
|
||||||
impl UnitTrait for AluBranch {
|
impl UnitTrait for AluBranch {
|
||||||
type Type = alu_branch;
|
type Type = alu_branch;
|
||||||
type ExtraOut = ();
|
type ExtraOut = ();
|
||||||
type MOp = AluBranchMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>;
|
type MOp = AluBranchMOp<UnitOutRegNum<DynSize>, DynSize>;
|
||||||
|
|
||||||
fn ty(&self) -> Self::Type {
|
fn ty(&self) -> Self::Type {
|
||||||
self.module.io_ty()
|
self.module.io_ty()
|
||||||
|
|
@ -612,7 +616,7 @@ impl UnitTrait for AluBranch {
|
||||||
|
|
||||||
fn extract_mop(
|
fn extract_mop(
|
||||||
&self,
|
&self,
|
||||||
mop: Expr<RenamedMOp<UnitOutRegNum<PhantomConst<CpuConfig>>, DynSize>>,
|
mop: Expr<RenamedMOp<UnitOutRegNum<DynSize>, DynSize>>,
|
||||||
) -> Expr<HdlOption<Self::MOp>> {
|
) -> Expr<HdlOption<Self::MOp>> {
|
||||||
UnitMOp::alu_branch_mop(mop)
|
UnitMOp::alu_branch_mop(mop)
|
||||||
}
|
}
|
||||||
|
|
@ -624,7 +628,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<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> {
|
) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize>> {
|
||||||
this.unit_to_reg_alloc
|
this.unit_to_reg_alloc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{CpuConfig, CpuConfigUnitCount, PhantomConstCpuConfig},
|
config::CpuConfig,
|
||||||
instruction::{COMMON_MOP_SRC_LEN, MOpTrait, PRegNum, UnitNum, UnitOutRegNum},
|
instruction::{COMMON_MOP_SRC_LEN, MOpTrait, PRegNum, UnitNum, UnitOutRegNum},
|
||||||
register::PRegValue,
|
register::PRegValue,
|
||||||
unit::{UnitCancelInput, UnitOutput, UnitOutputWrite},
|
unit::{UnitCancelInput, UnitOutput, UnitOutputWrite},
|
||||||
|
|
@ -15,11 +15,13 @@ use fayalite::{
|
||||||
ty::StaticType,
|
ty::StaticType,
|
||||||
util::ready_valid::ReadyValid,
|
util::ready_valid::ReadyValid,
|
||||||
};
|
};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
#[hdl(no_static)]
|
#[hdl]
|
||||||
pub struct UnitForwardingInfo<C: PhantomConstGet<CpuConfig>> {
|
pub struct UnitForwardingInfo<UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size> {
|
||||||
pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<C>>, CpuConfigUnitCount<C>>,
|
pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<OutRegNumWidth>>, UnitCount>,
|
||||||
pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<C>>, CpuConfigUnitCount<C>>,
|
pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<OutRegNumWidth>>, UnitCount>,
|
||||||
|
pub _phantom: PhantomData<UnitNumWidth>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -28,18 +30,26 @@ pub struct UnitInput<MOp: Type> {
|
||||||
pub pc: UInt<64>,
|
pub pc: UInt<64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(no_static)]
|
#[hdl]
|
||||||
pub struct UnitToRegAlloc<C: PhantomConstGet<CpuConfig>, MOp: Type, ExtraOut: Type> {
|
pub struct UnitToRegAlloc<
|
||||||
|
MOp: Type,
|
||||||
|
ExtraOut: Type,
|
||||||
|
UnitNumWidth: Size,
|
||||||
|
OutRegNumWidth: Size,
|
||||||
|
UnitCount: Size,
|
||||||
|
> {
|
||||||
#[hdl(flip)]
|
#[hdl(flip)]
|
||||||
pub unit_forwarding_info: UnitForwardingInfo<C>,
|
pub unit_forwarding_info: UnitForwardingInfo<UnitNumWidth, OutRegNumWidth, UnitCount>,
|
||||||
#[hdl(flip)]
|
#[hdl(flip)]
|
||||||
pub input: ReadyValid<UnitInput<MOp>>,
|
pub input: ReadyValid<UnitInput<MOp>>,
|
||||||
#[hdl(flip)]
|
#[hdl(flip)]
|
||||||
pub cancel_input: HdlOption<UnitCancelInput<C>>,
|
pub cancel_input: HdlOption<UnitCancelInput<OutRegNumWidth>>,
|
||||||
pub output: HdlOption<UnitOutput<C, ExtraOut>>,
|
pub output: HdlOption<UnitOutput<OutRegNumWidth, ExtraOut>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: PhantomConstCpuConfig, MOp: Type, ExtraOut: Type> UnitToRegAlloc<C, MOp, ExtraOut> {
|
impl<MOp: Type, ExtraOut: Type, UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size>
|
||||||
|
UnitToRegAlloc<MOp, ExtraOut, UnitNumWidth, OutRegNumWidth, UnitCount>
|
||||||
|
{
|
||||||
pub fn mop_ty(self) -> MOp {
|
pub fn mop_ty(self) -> MOp {
|
||||||
self.input.data.HdlSome.mop
|
self.input.data.HdlSome.mop
|
||||||
}
|
}
|
||||||
|
|
@ -48,20 +58,16 @@ impl<C: PhantomConstCpuConfig, MOp: Type, ExtraOut: Type> UnitToRegAlloc<C, MOp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(no_static)]
|
#[hdl]
|
||||||
pub struct ExecuteStart<
|
pub struct ExecuteStart<MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>>> {
|
||||||
C: PhantomConstGet<CpuConfig>,
|
|
||||||
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<C>>,
|
|
||||||
> {
|
|
||||||
pub mop: MOp,
|
pub mop: MOp,
|
||||||
pub pc: UInt<64>,
|
pub pc: UInt<64>,
|
||||||
pub src_values: Array<PRegValue, { COMMON_MOP_SRC_LEN }>,
|
pub src_values: Array<PRegValue, { COMMON_MOP_SRC_LEN }>,
|
||||||
pub config: C,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl(no_static)]
|
#[hdl]
|
||||||
pub struct ExecuteEnd<C: PhantomConstGet<CpuConfig>, ExtraOut> {
|
pub struct ExecuteEnd<OutRegNumWidth: Size, ExtraOut> {
|
||||||
pub unit_output: UnitOutput<C, ExtraOut>,
|
pub unit_output: UnitOutput<OutRegNumWidth, ExtraOut>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -234,10 +240,10 @@ impl InFlightOpsSummary<DynSize> {
|
||||||
|
|
||||||
#[hdl_module]
|
#[hdl_module]
|
||||||
pub fn unit_base<
|
pub fn unit_base<
|
||||||
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<PhantomConst<CpuConfig>>, SrcRegWidth = DynSize>,
|
MOp: Type + MOpTrait<DestReg = UnitOutRegNum<DynSize>, SrcRegWidth = DynSize>,
|
||||||
ExtraOut: Type,
|
ExtraOut: Type,
|
||||||
>(
|
>(
|
||||||
config: PhantomConst<CpuConfig>,
|
config: &CpuConfig,
|
||||||
unit_index: usize,
|
unit_index: usize,
|
||||||
mop_ty: MOp,
|
mop_ty: MOp,
|
||||||
extra_out_ty: ExtraOut,
|
extra_out_ty: ExtraOut,
|
||||||
|
|
@ -245,18 +251,17 @@ pub fn unit_base<
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let cd: ClockDomain = m.input();
|
let cd: ClockDomain = m.input();
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let unit_to_reg_alloc: UnitToRegAlloc<PhantomConst<CpuConfig>, MOp, ExtraOut> =
|
let unit_to_reg_alloc: UnitToRegAlloc<MOp, ExtraOut, DynSize, DynSize, DynSize> =
|
||||||
m.output(UnitToRegAlloc[config][mop_ty][extra_out_ty]);
|
m.output(config.unit_to_reg_alloc(mop_ty, extra_out_ty));
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let execute_start: ReadyValid<ExecuteStart<PhantomConst<CpuConfig>, MOp>> =
|
let execute_start: ReadyValid<ExecuteStart<MOp>> = m.output(ReadyValid[ExecuteStart[mop_ty]]);
|
||||||
m.output(ReadyValid[ExecuteStart[config][mop_ty]]);
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let execute_end: HdlOption<ExecuteEnd<PhantomConst<CpuConfig>, ExtraOut>> =
|
let execute_end: HdlOption<ExecuteEnd<DynSize, ExtraOut>> =
|
||||||
m.input(HdlOption[ExecuteEnd[config][extra_out_ty]]);
|
m.input(HdlOption[ExecuteEnd[config.out_reg_num_width][extra_out_ty]]);
|
||||||
|
|
||||||
connect(execute_start.data, execute_start.ty().data.HdlNone());
|
connect(execute_start.data, execute_start.ty().data.HdlNone());
|
||||||
|
|
||||||
let max_in_flight = config.get().unit_max_in_flight(unit_index).get();
|
let max_in_flight = config.unit_max_in_flight(unit_index).get();
|
||||||
let in_flight_op_ty = InFlightOp[mop_ty];
|
let in_flight_op_ty = InFlightOp[mop_ty];
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let in_flight_ops = reg_builder()
|
let in_flight_ops = reg_builder()
|
||||||
|
|
@ -274,15 +279,16 @@ pub fn unit_base<
|
||||||
);
|
);
|
||||||
|
|
||||||
#[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(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
|
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
|
||||||
);
|
);
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let read_src_values = wire();
|
let read_src_values = wire();
|
||||||
|
|
@ -291,7 +297,7 @@ pub fn unit_base<
|
||||||
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(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
|
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
|
||||||
);
|
);
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let input_src_regs_valid = wire();
|
let input_src_regs_valid = wire();
|
||||||
|
|
@ -303,7 +309,7 @@ pub fn unit_base<
|
||||||
Bool,
|
Bool,
|
||||||
SourceLocation::caller(),
|
SourceLocation::caller(),
|
||||||
);
|
);
|
||||||
mem.depth(1 << config.get().out_reg_num_width);
|
mem.depth(1 << config.out_reg_num_width);
|
||||||
mem
|
mem
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
@ -313,11 +319,11 @@ pub fn unit_base<
|
||||||
PRegValue,
|
PRegValue,
|
||||||
SourceLocation::caller(),
|
SourceLocation::caller(),
|
||||||
);
|
);
|
||||||
unit_output_regs.depth(1 << config.get().out_reg_num_width);
|
unit_output_regs.depth(1 << config.out_reg_num_width);
|
||||||
|
|
||||||
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(PRegNum[config]);
|
let p_reg_num = read_src_regs[src_index].cast_bits_to(config.p_reg_num());
|
||||||
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);
|
||||||
|
|
@ -330,7 +336,7 @@ pub fn unit_base<
|
||||||
|
|
||||||
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(PRegNum[config]);
|
let p_reg_num = input_src_regs[src_index].cast_bits_to(config.p_reg_num());
|
||||||
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);
|
||||||
|
|
@ -361,8 +367,8 @@ pub fn unit_base<
|
||||||
connect_any(ready_write_port.addr, unit_output_write.which.value);
|
connect_any(ready_write_port.addr, unit_output_write.which.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: UnitNum[config].from_index(unit_index),
|
unit_num: config.unit_num().from_index(unit_index),
|
||||||
unit_out_reg: unit_output_write.which,
|
unit_out_reg: unit_output_write.which,
|
||||||
};
|
};
|
||||||
for src_index in 0..COMMON_MOP_SRC_LEN {
|
for src_index in 0..COMMON_MOP_SRC_LEN {
|
||||||
|
|
@ -393,11 +399,10 @@ pub fn unit_base<
|
||||||
execute_start.data,
|
execute_start.data,
|
||||||
HdlSome(
|
HdlSome(
|
||||||
#[hdl]
|
#[hdl]
|
||||||
ExecuteStart::<_, _> {
|
ExecuteStart::<_> {
|
||||||
mop: in_flight_op.mop,
|
mop: in_flight_op.mop,
|
||||||
pc: in_flight_op.pc,
|
pc: in_flight_op.pc,
|
||||||
src_values: read_src_values,
|
src_values: read_src_values,
|
||||||
config,
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -420,7 +425,7 @@ pub fn unit_base<
|
||||||
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(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
|
repeat(config.p_reg_num().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(
|
||||||
|
|
@ -492,7 +497,7 @@ pub fn unit_base<
|
||||||
);
|
);
|
||||||
connect(
|
connect(
|
||||||
src_regs,
|
src_regs,
|
||||||
repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize),
|
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
|
||||||
);
|
);
|
||||||
MOp::connect_src_regs(mop, src_regs);
|
MOp::connect_src_regs(mop, src_regs);
|
||||||
|
|
||||||
|
|
@ -516,8 +521,8 @@ pub fn unit_base<
|
||||||
value: _,
|
value: _,
|
||||||
} = unit_output_write;
|
} = unit_output_write;
|
||||||
let p_reg_num = #[hdl]
|
let p_reg_num = #[hdl]
|
||||||
PRegNum::<_> {
|
PRegNum::<_, _> {
|
||||||
unit_num: UnitNum[config].from_index(unit_index),
|
unit_num: config.unit_num().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 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue