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()] | ||||
|     } | ||||
|     pub fn execute_start<MOp: Type>(&self, mop: MOp) -> ExecuteStart<MOp, DynSize, DynSize> { | ||||
|         ExecuteStart[mop][self.out_reg_num_width][self.retire_queue_index_width()] | ||||
|     } | ||||
|     pub fn execute_end<ExtraOut: Type>( | ||||
|         &self, | ||||
|         extra_out_ty: ExtraOut, | ||||
|     ) -> ExecuteEnd<DynSize, DynSize, ExtraOut> { | ||||
|         ExecuteEnd[self.out_reg_num_width][self.retire_queue_index_width()][extra_out_ty] | ||||
| } | ||||
| 
 | ||||
| mod sealed { | ||||
|     pub trait Sealed {} | ||||
| } | ||||
| 
 | ||||
| impl sealed::Sealed for PhantomConst<CpuConfig> {} | ||||
| 
 | ||||
| pub trait CpuConfigType: Type + ToExpr<Type = Self> + sealed::Sealed { | ||||
|     fn get(self) -> Interned<CpuConfig>; | ||||
| } | ||||
| 
 | ||||
| impl CpuConfigType for PhantomConst<CpuConfig> { | ||||
|     fn get(self) -> Interned<CpuConfig> { | ||||
|         self.get() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub trait Identity<Arg: ?Sized> { | ||||
|     type SelfType: ?Sized; | ||||
|     type ArgType: ?Sized; | ||||
| } | ||||
| 
 | ||||
| impl<T: ?Sized, Arg: ?Sized> Identity<Arg> for T { | ||||
|     type SelfType = T; | ||||
|     type ArgType = Arg; | ||||
| } | ||||
| 
 | ||||
| macro_rules! impl_cpu_config_accessors { | ||||
|     ( | ||||
|         $( | ||||
|             #[without_generics = $without_generics:ident] | ||||
|             $vis:vis type $ident:ident<$T:ident> = |$arg:ident| $expr:expr; | ||||
|         )* | ||||
|     ) => { | ||||
|         $( | ||||
|             #[allow(non_camel_case_types)] | ||||
|             $vis struct $without_generics; | ||||
| 
 | ||||
|             #[allow(non_upper_case_globals)] | ||||
|             $vis const $ident: $without_generics = $without_generics; | ||||
| 
 | ||||
|             $vis type $ident<$T> = <DynSize as Identity<$T>>::SelfType; | ||||
| 
 | ||||
|             impl<$T: CpuConfigType> std::ops::Index<$T> for $without_generics { | ||||
|                 type Output = usize; | ||||
| 
 | ||||
|                 fn index(&self, $arg: $T) -> &Self::Output { | ||||
|                     Interned::into_inner(Intern::intern_sized($expr)) | ||||
|                 } | ||||
|             } | ||||
|         )* | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| impl_cpu_config_accessors! { | ||||
|     #[without_generics = __UnitNumWidth_WithoutGenerics] | ||||
|     pub type UnitNumWidth<T> = |arg| arg.get().unit_num_width(); | ||||
|     #[without_generics = __UnitOutRegNumWidth_WithoutGenerics] | ||||
|     pub type UnitOutRegNumWidth<T> = |arg| arg.get().out_reg_num_width; | ||||
|     #[without_generics = __PRegNumWidth_WithoutGenerics] | ||||
|     pub type PRegNumWidth<T> = |arg| PRegNum[arg].canonical().bit_width(); | ||||
|     #[without_generics = __RetireQueueIndexWidth_WithoutGenerics] | ||||
|     pub type RetireQueueIndexWidth<T> = |arg| arg.get().retire_queue_index_width(); | ||||
|     #[without_generics = __UnitCount_WithoutGenerics] | ||||
|     pub type UnitCount<T> = |arg| arg.get().non_const_unit_nums().len(); | ||||
|     #[without_generics = __FetchWidth_WithoutGenerics] | ||||
|     pub type FetchWidth<T> = |arg| arg.get().fetch_width.get(); | ||||
| } | ||||
|  |  | |||
|  | @ -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