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" | version = "0.1.0" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "fayalite", |  "fayalite", | ||||||
|  |  "name_mangling_serde", | ||||||
|  |  "serde", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
|  | @ -300,7 +302,7 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" | ||||||
| [[package]] | [[package]] | ||||||
| name = "fayalite" | name = "fayalite" | ||||||
| version = "0.3.0" | version = "0.3.0" | ||||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#450e1004b6eef6fcdce74a94e3bded3e0268610d" | source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#d453755bb2cd0b6f2340f3e49058d29a2ee279e8" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "bitvec", |  "bitvec", | ||||||
|  "blake3", |  "blake3", | ||||||
|  | @ -325,7 +327,7 @@ dependencies = [ | ||||||
| [[package]] | [[package]] | ||||||
| name = "fayalite-proc-macros" | name = "fayalite-proc-macros" | ||||||
| version = "0.3.0" | version = "0.3.0" | ||||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#450e1004b6eef6fcdce74a94e3bded3e0268610d" | source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#d453755bb2cd0b6f2340f3e49058d29a2ee279e8" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "fayalite-proc-macros-impl", |  "fayalite-proc-macros-impl", | ||||||
| ] | ] | ||||||
|  | @ -333,7 +335,7 @@ dependencies = [ | ||||||
| [[package]] | [[package]] | ||||||
| name = "fayalite-proc-macros-impl" | name = "fayalite-proc-macros-impl" | ||||||
| version = "0.3.0" | version = "0.3.0" | ||||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#450e1004b6eef6fcdce74a94e3bded3e0268610d" | source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#d453755bb2cd0b6f2340f3e49058d29a2ee279e8" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "base16ct", |  "base16ct", | ||||||
|  "num-bigint", |  "num-bigint", | ||||||
|  | @ -348,7 +350,7 @@ dependencies = [ | ||||||
| [[package]] | [[package]] | ||||||
| name = "fayalite-visit-gen" | name = "fayalite-visit-gen" | ||||||
| version = "0.3.0" | version = "0.3.0" | ||||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#450e1004b6eef6fcdce74a94e3bded3e0268610d" | source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#d453755bb2cd0b6f2340f3e49058d29a2ee279e8" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "indexmap", |  "indexmap", | ||||||
|  "prettyplease", |  "prettyplease", | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ categories = [] | ||||||
| rust-version = "1.82.0" | rust-version = "1.82.0" | ||||||
| 
 | 
 | ||||||
| [workspace.dependencies] | [workspace.dependencies] | ||||||
|  | name_mangling_serde = { version = "=0.1.0", path = "crates/name_mangling_serde" } | ||||||
| fayalite = { git = "https://git.libre-chip.org/libre-chip/fayalite.git", version = "0.3.0", branch = "master" } | fayalite = { git = "https://git.libre-chip.org/libre-chip/fayalite.git", version = "0.3.0", branch = "master" } | ||||||
| serde = { version = "1.0.202", features = ["derive"] } | serde = { version = "1.0.202", features = ["derive"] } | ||||||
| serde_json = { version = "1.0.117", features = ["preserve_order"] } | serde_json = { version = "1.0.117", features = ["preserve_order"] } | ||||||
|  |  | ||||||
|  | @ -16,6 +16,8 @@ version.workspace = true | ||||||
| 
 | 
 | ||||||
| [dependencies] | [dependencies] | ||||||
| fayalite.workspace = true | fayalite.workspace = true | ||||||
|  | serde.workspace = true | ||||||
|  | name_mangling_serde.workspace = true | ||||||
| 
 | 
 | ||||||
| [lints.rust] | [lints.rust] | ||||||
| unexpected_cfgs = { level = "warn", check-cfg = ['cfg(todo)'] } | unexpected_cfgs = { level = "warn", check-cfg = ['cfg(todo)'] } | ||||||
|  |  | ||||||
|  | @ -1,17 +1,17 @@ | ||||||
| // SPDX-License-Identifier: LGPL-3.0-or-later
 | // SPDX-License-Identifier: LGPL-3.0-or-later
 | ||||||
| // See Notices.txt for copyright information
 | // See Notices.txt for copyright information
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     instruction::{MOpTrait, PRegNum, RenamedMOp, UnitNum, UnitOutRegNum, CONST_ZERO_UNIT_NUM}, |     instruction::{PRegNum, CONST_ZERO_UNIT_NUM}, | ||||||
|     unit::{ |     unit::UnitKind, | ||||||
|         unit_base::{ExecuteEnd, ExecuteStart}, |  | ||||||
|         RenamedInsnData, RetireQueueIndex, UnitForwardingInfo, UnitKind, UnitOutputWrite, |  | ||||||
|         UnitToRegAlloc, |  | ||||||
|     }, |  | ||||||
| }; | }; | ||||||
| use fayalite::prelude::*; | use fayalite::{ | ||||||
|  |     intern::{Intern, Interned}, | ||||||
|  |     prelude::*, | ||||||
|  | }; | ||||||
|  | use serde::{Deserialize, Serialize}; | ||||||
| use std::num::NonZeroUsize; | use std::num::NonZeroUsize; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Eq, PartialEq, Hash, Debug)] | #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] | ||||||
| #[non_exhaustive] | #[non_exhaustive] | ||||||
| pub struct UnitConfig { | pub struct UnitConfig { | ||||||
|     pub kind: UnitKind, |     pub kind: UnitKind, | ||||||
|  | @ -28,10 +28,10 @@ impl UnitConfig { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Eq, PartialEq, Hash, Debug)] | #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] | ||||||
| #[non_exhaustive] | #[non_exhaustive] | ||||||
| pub struct CpuConfig { | pub struct CpuConfig { | ||||||
|     pub units: Vec<UnitConfig>, |     pub units: Interned<[UnitConfig]>, | ||||||
|     pub out_reg_num_width: usize, |     pub out_reg_num_width: usize, | ||||||
|     pub fetch_width: NonZeroUsize, |     pub fetch_width: NonZeroUsize, | ||||||
|     /// default value for [`UnitConfig::max_in_flight`]
 |     /// default value for [`UnitConfig::max_in_flight`]
 | ||||||
|  | @ -52,7 +52,7 @@ impl CpuConfig { | ||||||
|         }; |         }; | ||||||
|         v |         v | ||||||
|     }; |     }; | ||||||
|     pub fn new(units: Vec<UnitConfig>) -> Self { |     pub fn new(units: Interned<[UnitConfig]>) -> Self { | ||||||
|         Self { |         Self { | ||||||
|             units, |             units, | ||||||
|             out_reg_num_width: Self::DEFAULT_OUT_REG_NUM_WIDTH, |             out_reg_num_width: Self::DEFAULT_OUT_REG_NUM_WIDTH, | ||||||
|  | @ -66,70 +66,83 @@ impl CpuConfig { | ||||||
|     pub fn unit_num_width(&self) -> usize { |     pub fn unit_num_width(&self) -> usize { | ||||||
|         UInt::range(CONST_ZERO_UNIT_NUM..self.non_const_unit_nums().end).width() |         UInt::range(CONST_ZERO_UNIT_NUM..self.non_const_unit_nums().end).width() | ||||||
|     } |     } | ||||||
|     pub fn unit_num(&self) -> UnitNum<DynSize> { |  | ||||||
|         UnitNum[self.unit_num_width()] |  | ||||||
|     } |  | ||||||
|     pub fn unit_out_reg_num(&self) -> UnitOutRegNum<DynSize> { |  | ||||||
|         UnitOutRegNum[self.out_reg_num_width] |  | ||||||
|     } |  | ||||||
|     pub fn p_reg_num(&self) -> PRegNum<DynSize, DynSize> { |  | ||||||
|         PRegNum[self.unit_num_width()][self.out_reg_num_width] |  | ||||||
|     } |  | ||||||
|     pub fn p_reg_num_width(&self) -> usize { |  | ||||||
|         self.unit_num_width() + self.out_reg_num_width |  | ||||||
|     } |  | ||||||
|     pub fn renamed_mop(&self) -> RenamedMOp<DynSize> { |  | ||||||
|         RenamedMOp[self.p_reg_num_width()] |  | ||||||
|     } |  | ||||||
|     pub fn unit_output_write(&self) -> UnitOutputWrite<DynSize> { |  | ||||||
|         UnitOutputWrite[self.out_reg_num_width] |  | ||||||
|     } |  | ||||||
|     pub fn unit_output_writes(&self) -> Array<HdlOption<UnitOutputWrite<DynSize>>> { |  | ||||||
|         Array[HdlOption[self.unit_output_write()]][self.non_const_unit_nums().len()] |  | ||||||
|     } |  | ||||||
|     pub fn unit_forwarding_info(&self) -> UnitForwardingInfo<DynSize, DynSize, DynSize> { |  | ||||||
|         UnitForwardingInfo[self.unit_num_width()][self.out_reg_num_width] |  | ||||||
|             [self.non_const_unit_nums().len()] |  | ||||||
|     } |  | ||||||
|     pub fn unit_max_in_flight(&self, unit_index: usize) -> NonZeroUsize { |     pub fn unit_max_in_flight(&self, unit_index: usize) -> NonZeroUsize { | ||||||
|         self.units[unit_index] |         self.units[unit_index] | ||||||
|             .max_in_flight |             .max_in_flight | ||||||
|             .unwrap_or(self.default_unit_max_in_flight) |             .unwrap_or(self.default_unit_max_in_flight) | ||||||
|     } |     } | ||||||
|     pub fn unit_to_reg_alloc< |  | ||||||
|         MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, |  | ||||||
|         ExtraOut: Type, |  | ||||||
|     >( |  | ||||||
|         &self, |  | ||||||
|         mop_ty: MOp, |  | ||||||
|         extra_out_ty: ExtraOut, |  | ||||||
|     ) -> UnitToRegAlloc<MOp, ExtraOut, DynSize, DynSize, DynSize, DynSize> { |  | ||||||
|         UnitToRegAlloc[mop_ty][extra_out_ty][self.unit_num_width()][self.out_reg_num_width] |  | ||||||
|             [self.non_const_unit_nums().len()][self.retire_queue_index_width()] |  | ||||||
|     } |  | ||||||
|     pub fn retire_queue_index_width(&self) -> usize { |     pub fn retire_queue_index_width(&self) -> usize { | ||||||
|         let max_in_flight: usize = (0..self.units.len()) |         let max_in_flight: usize = (0..self.units.len()) | ||||||
|             .map(|unit_index| self.unit_max_in_flight(unit_index).get()) |             .map(|unit_index| self.unit_max_in_flight(unit_index).get()) | ||||||
|             .sum(); |             .sum(); | ||||||
|         2 + max_in_flight.next_power_of_two().ilog2() as usize |         2 + max_in_flight.next_power_of_two().ilog2() as usize | ||||||
|     } |     } | ||||||
|     pub fn retire_queue_index(&self) -> RetireQueueIndex<DynSize> { | } | ||||||
|         RetireQueueIndex[self.retire_queue_index_width()] | 
 | ||||||
|     } | mod sealed { | ||||||
|     pub fn renamed_insn_data<MOp: Type, DestReg: Type>( |     pub trait Sealed {} | ||||||
|         &self, | } | ||||||
|         mop: MOp, | 
 | ||||||
|         dest: DestReg, | impl sealed::Sealed for PhantomConst<CpuConfig> {} | ||||||
|     ) -> RenamedInsnData<MOp, DestReg, DynSize> { | 
 | ||||||
|         RenamedInsnData[mop][dest][self.retire_queue_index_width()] | pub trait CpuConfigType: Type + ToExpr<Type = Self> + sealed::Sealed { | ||||||
|     } |     fn get(self) -> Interned<CpuConfig>; | ||||||
|     pub fn execute_start<MOp: Type>(&self, mop: MOp) -> ExecuteStart<MOp, DynSize, DynSize> { | } | ||||||
|         ExecuteStart[mop][self.out_reg_num_width][self.retire_queue_index_width()] | 
 | ||||||
|     } | impl CpuConfigType for PhantomConst<CpuConfig> { | ||||||
|     pub fn execute_end<ExtraOut: Type>( |     fn get(self) -> Interned<CpuConfig> { | ||||||
|         &self, |         self.get() | ||||||
|         extra_out_ty: ExtraOut, |  | ||||||
|     ) -> ExecuteEnd<DynSize, DynSize, ExtraOut> { |  | ||||||
|         ExecuteEnd[self.out_reg_num_width][self.retire_queue_index_width()][extra_out_ty] |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | pub trait Identity<Arg: ?Sized> { | ||||||
|  |     type SelfType: ?Sized; | ||||||
|  |     type ArgType: ?Sized; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T: ?Sized, Arg: ?Sized> Identity<Arg> for T { | ||||||
|  |     type SelfType = T; | ||||||
|  |     type ArgType = Arg; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | macro_rules! impl_cpu_config_accessors { | ||||||
|  |     ( | ||||||
|  |         $( | ||||||
|  |             #[without_generics = $without_generics:ident] | ||||||
|  |             $vis:vis type $ident:ident<$T:ident> = |$arg:ident| $expr:expr; | ||||||
|  |         )* | ||||||
|  |     ) => { | ||||||
|  |         $( | ||||||
|  |             #[allow(non_camel_case_types)] | ||||||
|  |             $vis struct $without_generics; | ||||||
|  | 
 | ||||||
|  |             #[allow(non_upper_case_globals)] | ||||||
|  |             $vis const $ident: $without_generics = $without_generics; | ||||||
|  | 
 | ||||||
|  |             $vis type $ident<$T> = <DynSize as Identity<$T>>::SelfType; | ||||||
|  | 
 | ||||||
|  |             impl<$T: CpuConfigType> std::ops::Index<$T> for $without_generics { | ||||||
|  |                 type Output = usize; | ||||||
|  | 
 | ||||||
|  |                 fn index(&self, $arg: $T) -> &Self::Output { | ||||||
|  |                     Interned::into_inner(Intern::intern_sized($expr)) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         )* | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl_cpu_config_accessors! { | ||||||
|  |     #[without_generics = __UnitNumWidth_WithoutGenerics] | ||||||
|  |     pub type UnitNumWidth<T> = |arg| arg.get().unit_num_width(); | ||||||
|  |     #[without_generics = __UnitOutRegNumWidth_WithoutGenerics] | ||||||
|  |     pub type UnitOutRegNumWidth<T> = |arg| arg.get().out_reg_num_width; | ||||||
|  |     #[without_generics = __PRegNumWidth_WithoutGenerics] | ||||||
|  |     pub type PRegNumWidth<T> = |arg| PRegNum[arg].canonical().bit_width(); | ||||||
|  |     #[without_generics = __RetireQueueIndexWidth_WithoutGenerics] | ||||||
|  |     pub type RetireQueueIndexWidth<T> = |arg| arg.get().retire_queue_index_width(); | ||||||
|  |     #[without_generics = __UnitCount_WithoutGenerics] | ||||||
|  |     pub type UnitCount<T> = |arg| arg.get().non_const_unit_nums().len(); | ||||||
|  |     #[without_generics = __FetchWidth_WithoutGenerics] | ||||||
|  |     pub type FetchWidth<T> = |arg| arg.get().fetch_width.get(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,10 @@ | ||||||
| // SPDX-License-Identifier: LGPL-3.0-or-later
 | // SPDX-License-Identifier: LGPL-3.0-or-later
 | ||||||
| // See Notices.txt for copyright information
 | // See Notices.txt for copyright information
 | ||||||
| use crate::{unit::UnitMOp, util::range_u32_len}; | use crate::{ | ||||||
|  |     config::{CpuConfigType, UnitNumWidth, UnitOutRegNumWidth}, | ||||||
|  |     unit::UnitMOp, | ||||||
|  |     util::range_u32_len, | ||||||
|  | }; | ||||||
| use fayalite::{ | use fayalite::{ | ||||||
|     expr::ops::{ArrayLiteral, ExprPartialEq}, |     expr::ops::{ArrayLiteral, ExprPartialEq}, | ||||||
|     intern::Interned, |     intern::Interned, | ||||||
|  | @ -805,19 +809,21 @@ common_mop_struct! { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl(cmp_eq)] | #[hdl(cmp_eq, no_static)] | ||||||
| /// there may be more than one unit of a given kind, so UnitNum is not the same as UnitKind.
 | /// there may be more than one unit of a given kind, so UnitNum is not the same as UnitKind.
 | ||||||
| /// zero is used for built-in constants, such as the zero register
 | /// zero is used for built-in constants, such as the zero register
 | ||||||
| pub struct UnitNum<Width: Size> { | pub struct UnitNum<C: Type + CpuConfigType> { | ||||||
|     pub adj_value: UIntType<Width>, |     pub adj_value: UIntType<UnitNumWidth<C>>, | ||||||
|  |     pub config: C, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<Width: Size> UnitNum<Width> { | impl<C: Type + CpuConfigType> UnitNum<C> { | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     pub fn const_zero(self) -> Expr<Self> { |     pub fn const_zero(self) -> Expr<Self> { | ||||||
|         #[hdl] |         #[hdl] | ||||||
|         UnitNum { |         UnitNum { | ||||||
|             adj_value: CONST_ZERO_UNIT_NUM.cast_to(self.adj_value), |             adj_value: CONST_ZERO_UNIT_NUM.cast_to(self.adj_value), | ||||||
|  |             config: self.config, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     #[hdl] |     #[hdl] | ||||||
|  | @ -825,6 +831,7 @@ impl<Width: Size> UnitNum<Width> { | ||||||
|         #[hdl] |         #[hdl] | ||||||
|         UnitNum { |         UnitNum { | ||||||
|             adj_value: (index + 1).cast_to(self.adj_value), |             adj_value: (index + 1).cast_to(self.adj_value), | ||||||
|  |             config: self.config, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     pub fn is_index(expr: impl ToExpr<Type = Self>, index: usize) -> Expr<Bool> { |     pub fn is_index(expr: impl ToExpr<Type = Self>, index: usize) -> Expr<Bool> { | ||||||
|  | @ -835,7 +842,7 @@ impl<Width: Size> UnitNum<Width> { | ||||||
|             .cmp_eq(expr.adj_value) |             .cmp_eq(expr.adj_value) | ||||||
|     } |     } | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     pub fn as_index(expr: impl ToExpr<Type = Self>) -> Expr<HdlOption<UIntType<Width>>> { |     pub fn as_index(expr: impl ToExpr<Type = Self>) -> Expr<HdlOption<UIntType<DynSize>>> { | ||||||
|         let expr = expr.to_expr(); |         let expr = expr.to_expr(); | ||||||
|         #[hdl] |         #[hdl] | ||||||
|         let unit_index = wire(HdlOption[Expr::ty(expr).adj_value]); |         let unit_index = wire(HdlOption[Expr::ty(expr).adj_value]); | ||||||
|  | @ -853,19 +860,20 @@ impl<Width: Size> UnitNum<Width> { | ||||||
| 
 | 
 | ||||||
| pub const CONST_ZERO_UNIT_NUM: usize = 0; | pub const CONST_ZERO_UNIT_NUM: usize = 0; | ||||||
| 
 | 
 | ||||||
| #[hdl(cmp_eq)] | #[hdl(cmp_eq, no_static)] | ||||||
| pub struct UnitOutRegNum<Width: Size> { | pub struct UnitOutRegNum<C: Type + CpuConfigType> { | ||||||
|     pub value: UIntType<Width>, |     pub value: UIntType<UnitOutRegNumWidth<C>>, | ||||||
|  |     pub config: C, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl(cmp_eq)] | #[hdl(cmp_eq, no_static)] | ||||||
| /// Physical Register Number -- registers in the CPU's backend
 | /// Physical Register Number -- registers in the CPU's backend
 | ||||||
| pub struct PRegNum<UnitNumWidth: Size, OutRegNumWidth: Size> { | pub struct PRegNum<C: Type + CpuConfigType> { | ||||||
|     pub unit_num: UnitNum<UnitNumWidth>, |     pub unit_num: UnitNum<C>, | ||||||
|     pub unit_out_reg: UnitOutRegNum<OutRegNumWidth>, |     pub unit_out_reg: UnitOutRegNum<C>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<UnitNumWidth: Size, OutRegNumWidth: Size> PRegNum<UnitNumWidth, OutRegNumWidth> { | impl<C: Type + CpuConfigType> PRegNum<C> { | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     pub fn const_zero(self) -> Expr<Self> { |     pub fn const_zero(self) -> Expr<Self> { | ||||||
|         #[hdl] |         #[hdl] | ||||||
|  | @ -874,6 +882,7 @@ impl<UnitNumWidth: Size, OutRegNumWidth: Size> PRegNum<UnitNumWidth, OutRegNumWi | ||||||
|             unit_out_reg: #[hdl] |             unit_out_reg: #[hdl] | ||||||
|             UnitOutRegNum { |             UnitOutRegNum { | ||||||
|                 value: 0u8.cast_to(self.unit_out_reg.value), |                 value: 0u8.cast_to(self.unit_out_reg.value), | ||||||
|  |                 config: self.unit_out_reg.config, | ||||||
|             }, |             }, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| // See Notices.txt for copyright information
 | // See Notices.txt for copyright information
 | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     config::CpuConfig, |     config::{CpuConfig, CpuConfigType, FetchWidth, PRegNumWidth}, | ||||||
|     instruction::{MOp, MOpDestReg, MOpRegNum, MOpTrait, MoveRegMOp, PRegNum, RenamedMOp}, |     instruction::{MOp, MOpDestReg, MOpRegNum, MOpTrait, MoveRegMOp, PRegNum, RenamedMOp}, | ||||||
|     rename_table::{rename_table, RenameTablePortConfig}, |     rename_table::{rename_table, RenameTablePortConfig}, | ||||||
|     unit::{RenamedInsnData, RetireQueueIndex, UnitMOp}, |     unit::{RenamedInsnData, RetireQueueIndex, UnitMOp}, | ||||||
|  | @ -13,49 +13,47 @@ use fayalite::{ | ||||||
|     util::{prefix_sum::PrefixSumAlgorithm, ready_valid::ReadyValid}, |     util::{prefix_sum::PrefixSumAlgorithm, ready_valid::ReadyValid}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl(no_static)] | ||||||
| pub struct InstructionRenameInputInsn<UnitNumWidth: Size, OutRegNumWidth: Size> { | pub struct InstructionRenameInputInsn<C: Type + CpuConfigType> { | ||||||
|     pub mop: MOp, |     pub mop: MOp, | ||||||
|     pub pc: UInt<64>, |     pub pc: UInt<64>, | ||||||
|     pub renamed_dest: PRegNum<UnitNumWidth, OutRegNumWidth>, |     pub renamed_dest: PRegNum<C>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl CpuConfig { | #[hdl(no_static)] | ||||||
|     pub fn instruction_rename_input_insn(&self) -> InstructionRenameInputInsn<DynSize, DynSize> { | struct InsnsInPrefixSummary<C: Type + CpuConfigType> { | ||||||
|         InstructionRenameInputInsn[self.unit_num_width()][self.out_reg_num_width] |     all_ready: Bool, | ||||||
|     } |     ready_count: Length<FetchWidth<C>>, | ||||||
|  |     retire_queue_used: Length<FetchWidth<C>>, | ||||||
|  |     config: C, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type C = PhantomConst<CpuConfig>; | ||||||
|  | 
 | ||||||
| #[hdl] | #[hdl] | ||||||
| struct InsnsInPrefixSummary<FetchWidth: Size> { | pub type InstructionRenameInsnsOut<C: Type + CpuConfigType> = ArrayType< | ||||||
|     all_ready: Bool, |     ReadyValid<RenamedInsnData<C, RenamedMOp<PRegNumWidth<C>>, PRegNum<C>>>, | ||||||
|     ready_count: Length<FetchWidth>, |     FetchWidth<C>, | ||||||
|     retire_queue_used: Length<FetchWidth>, | >; | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| #[hdl_module] | #[hdl_module] | ||||||
| pub fn instruction_rename(config: &CpuConfig) { | pub fn instruction_rename(config: PhantomConst<CpuConfig>) { | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let cd: ClockDomain = m.input(); |     let cd: ClockDomain = m.input(); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let insns_in: ReadyValidArray<InstructionRenameInputInsn<DynSize, DynSize>, DynSize> = |     let insns_in: ReadyValidArray<InstructionRenameInputInsn<C>, FetchWidth<C>> = | ||||||
|         m.input(ReadyValidArray[config.instruction_rename_input_insn()][config.fetch_width.get()]); |         m.input(ReadyValidArray[InstructionRenameInputInsn[config]][FetchWidth[config]]); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let start_retire_queue_index: RetireQueueIndex<DynSize> = m.input(config.retire_queue_index()); |     let start_retire_queue_index: RetireQueueIndex<C> = m.input(RetireQueueIndex[config]); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let end_retire_queue_index: RetireQueueIndex<DynSize> = m.output(config.retire_queue_index()); |     let end_retire_queue_index: RetireQueueIndex<C> = m.output(RetireQueueIndex[config]); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let insns_out: Array< |     let insns_out: InstructionRenameInsnsOut<C> = m.output(InstructionRenameInsnsOut[config]); | ||||||
|         ReadyValid<RenamedInsnData<RenamedMOp<DynSize>, PRegNum<DynSize, DynSize>, DynSize>>, |  | ||||||
|     > = m.output( |  | ||||||
|         Array[ReadyValid[config.renamed_insn_data(config.renamed_mop(), config.p_reg_num())]] |  | ||||||
|             [config.fetch_width.get()], |  | ||||||
|     ); |  | ||||||
| 
 | 
 | ||||||
|     // TODO: handle resetting table after cancelling instructions
 |     // TODO: handle resetting table after cancelling instructions
 | ||||||
| 
 | 
 | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let insns_ready_or_move = wire(Array[Bool][config.fetch_width.get()]); |     let insns_ready_or_move = wire(ArrayType[Bool][FetchWidth[config]]); | ||||||
| 
 | 
 | ||||||
|     for (insn_ready_or_move, insn_out) in insns_ready_or_move.into_iter().zip(insns_out) { |     for (insn_ready_or_move, insn_out) in insns_ready_or_move.into_iter().zip(insns_out) { | ||||||
|         connect(insn_ready_or_move, insn_out.ready); |         connect(insn_ready_or_move, insn_out.ready); | ||||||
|  | @ -71,12 +69,11 @@ pub fn instruction_rename(config: &CpuConfig) { | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     let insns_in_prefix_summary_ty = InsnsInPrefixSummary[config.fetch_width.get()]; |     let insns_in_prefix_summary_ty = InsnsInPrefixSummary[config]; | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let insns_in_prefix_summaries = |     let insns_in_prefix_summaries = wire(ArrayType[insns_in_prefix_summary_ty][FetchWidth[config]]); | ||||||
|         wire(Array[insns_in_prefix_summary_ty][config.fetch_width.get()]); |  | ||||||
|     let insns_in_prefix_summaries_vec = PrefixSumAlgorithm::WorkEfficient.run( |     let insns_in_prefix_summaries_vec = PrefixSumAlgorithm::WorkEfficient.run( | ||||||
|         (0..config.fetch_width.get()).map(|fetch_index| { |         (0..FetchWidth[config]).map(|fetch_index| { | ||||||
|             #[hdl] |             #[hdl] | ||||||
|             let insns_in_prefix_summary_in = wire(insns_in_prefix_summary_ty); |             let insns_in_prefix_summary_in = wire(insns_in_prefix_summary_ty); | ||||||
|             #[hdl] |             #[hdl] | ||||||
|  | @ -84,6 +81,7 @@ pub fn instruction_rename(config: &CpuConfig) { | ||||||
|                 all_ready, |                 all_ready, | ||||||
|                 ready_count, |                 ready_count, | ||||||
|                 retire_queue_used, |                 retire_queue_used, | ||||||
|  |                 config: _, | ||||||
|             } = insns_in_prefix_summary_in; |             } = insns_in_prefix_summary_in; | ||||||
|             connect(all_ready, insns_out[fetch_index].ready); |             connect(all_ready, insns_out[fetch_index].ready); | ||||||
|             connect( |             connect( | ||||||
|  | @ -112,6 +110,7 @@ pub fn instruction_rename(config: &CpuConfig) { | ||||||
|                 all_ready, |                 all_ready, | ||||||
|                 ready_count, |                 ready_count, | ||||||
|                 retire_queue_used, |                 retire_queue_used, | ||||||
|  |                 config: _, | ||||||
|             } = insns_in_prefix_summary_merge; |             } = insns_in_prefix_summary_merge; | ||||||
|             connect(all_ready, l.all_ready & r.all_ready); |             connect(all_ready, l.all_ready & r.all_ready); | ||||||
|             #[hdl] |             #[hdl] | ||||||
|  | @ -143,16 +142,15 @@ pub fn instruction_rename(config: &CpuConfig) { | ||||||
|     } |     } | ||||||
|     connect( |     connect( | ||||||
|         insns_in.ready, |         insns_in.ready, | ||||||
|         insns_in_prefix_summaries[config.fetch_width.get() - 1].ready_count, |         insns_in_prefix_summaries[FetchWidth[config] - 1].ready_count, | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let retire_queue_indexes = |     let retire_queue_indexes = wire(Array[RetireQueueIndex[config]][FetchWidth[config] + 1]); | ||||||
|         wire(Array[config.retire_queue_index()][config.fetch_width.get() + 1]); |  | ||||||
|     connect(retire_queue_indexes[0], start_retire_queue_index); |     connect(retire_queue_indexes[0], start_retire_queue_index); | ||||||
|     connect( |     connect( | ||||||
|         end_retire_queue_index, |         end_retire_queue_index, | ||||||
|         retire_queue_indexes[config.fetch_width.get()], |         retire_queue_indexes[FetchWidth[config]], | ||||||
|     ); |     ); | ||||||
|     for (retire_queue_index, insns_in_prefix_summary) in retire_queue_indexes |     for (retire_queue_index, insns_in_prefix_summary) in retire_queue_indexes | ||||||
|         .into_iter() |         .into_iter() | ||||||
|  | @ -171,7 +169,7 @@ pub fn instruction_rename(config: &CpuConfig) { | ||||||
|     MOpTrait::for_each_src_reg(MOp.uninit(), &mut |_, src_index| { |     MOpTrait::for_each_src_reg(MOp.uninit(), &mut |_, src_index| { | ||||||
|         src_reg_count = src_reg_count.max(src_index + 1); |         src_reg_count = src_reg_count.max(src_index + 1); | ||||||
|     }); |     }); | ||||||
|     for _ in 0..config.fetch_width.get() { |     for _ in 0..FetchWidth[config] { | ||||||
|         for _ in 0..src_reg_count { |         for _ in 0..src_reg_count { | ||||||
|             port_configs.push(RenameTablePortConfig::Read { |             port_configs.push(RenameTablePortConfig::Read { | ||||||
|                 addr_range: MOpRegNum::NON_CONST_REG_NUMS, |                 addr_range: MOpRegNum::NON_CONST_REG_NUMS, | ||||||
|  | @ -194,7 +192,7 @@ pub fn instruction_rename(config: &CpuConfig) { | ||||||
|     } |     } | ||||||
|     for write_port in rename_table.write_ports { |     for write_port in rename_table.write_ports { | ||||||
|         connect_any(write_port.addr, 0_hdl_u0); |         connect_any(write_port.addr, 0_hdl_u0); | ||||||
|         connect_any(write_port.data, config.p_reg_num().const_zero()); |         connect_any(write_port.data, PRegNum[config].const_zero()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ArrayVec::for_each( |     ArrayVec::for_each( | ||||||
|  | @ -203,16 +201,13 @@ pub fn instruction_rename(config: &CpuConfig) { | ||||||
|             let read_port_index = fetch_index * src_reg_count; |             let read_port_index = fetch_index * src_reg_count; | ||||||
|             let write_port_index = fetch_index * MOpDestReg::REG_COUNT; |             let write_port_index = fetch_index * MOpDestReg::REG_COUNT; | ||||||
|             #[hdl] |             #[hdl] | ||||||
|             let InstructionRenameInputInsn::<_, _> { |             let InstructionRenameInputInsn::<_> { | ||||||
|                 mop, |                 mop, | ||||||
|                 pc, |                 pc, | ||||||
|                 renamed_dest, |                 renamed_dest, | ||||||
|             } = input_insn; |             } = input_insn; | ||||||
|             let insn_out = MOpTrait::map_regs( |             let insn_out = | ||||||
|                 mop, |                 MOpTrait::map_regs(mop, (), PRegNumWidth[config], &mut |src_reg, src_index| { | ||||||
|                 (), |  | ||||||
|                 config.p_reg_num_width(), |  | ||||||
|                 &mut |src_reg, src_index| { |  | ||||||
|                     connect( |                     connect( | ||||||
|                         rename_table.read_ports[read_port_index + src_index].addr, |                         rename_table.read_ports[read_port_index + src_index].addr, | ||||||
|                         src_reg.cast_bits_to(MOpRegNum), |                         src_reg.cast_bits_to(MOpRegNum), | ||||||
|  | @ -220,8 +215,7 @@ pub fn instruction_rename(config: &CpuConfig) { | ||||||
|                     rename_table.read_ports[read_port_index + src_index] |                     rename_table.read_ports[read_port_index + src_index] | ||||||
|                         .data |                         .data | ||||||
|                         .cast_to_bits() |                         .cast_to_bits() | ||||||
|                 }, |                 }); | ||||||
|             ); |  | ||||||
|             for (i, dest_reg) in MOpDestReg::regs(MOpTrait::dest_reg(mop)) |             for (i, dest_reg) in MOpDestReg::regs(MOpTrait::dest_reg(mop)) | ||||||
|                 .into_iter() |                 .into_iter() | ||||||
|                 .enumerate() |                 .enumerate() | ||||||
|  | @ -237,13 +231,13 @@ pub fn instruction_rename(config: &CpuConfig) { | ||||||
|             } |             } | ||||||
|             let insn_out = UnitMOp::try_with_transformed_move_op( |             let insn_out = UnitMOp::try_with_transformed_move_op( | ||||||
|                 insn_out, |                 insn_out, | ||||||
|                 config.renamed_mop().TransformedMove, |                 RenamedMOp[PRegNumWidth[config]].TransformedMove, | ||||||
|                 |insn_out: Expr<HdlOption<_>>, move_reg: Expr<MoveRegMOp<_, _>>| { |                 |insn_out: Expr<HdlOption<_>>, move_reg: Expr<MoveRegMOp<_, _>>| { | ||||||
|                     for i in 0..MOpDestReg::REG_COUNT { |                     for i in 0..MOpDestReg::REG_COUNT { | ||||||
|                         // execute move by using same PRegNum as src[0] for dest
 |                         // execute move by using same PRegNum as src[0] for dest
 | ||||||
|                         connect( |                         connect( | ||||||
|                             rename_table.write_ports[write_port_index + i].data, |                             rename_table.write_ports[write_port_index + i].data, | ||||||
|                             move_reg.common.src[0].cast_bits_to(config.p_reg_num()), |                             move_reg.common.src[0].cast_bits_to(PRegNum[config]), | ||||||
|                         ); |                         ); | ||||||
|                     } |                     } | ||||||
|                     // move already executed, so remove it
 |                     // move already executed, so remove it
 | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| // See Notices.txt for copyright information
 | // See Notices.txt for copyright information
 | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     config::CpuConfig, |     config::{CpuConfig, CpuConfigType}, | ||||||
|     instruction::{MOpRegNum, PRegNum}, |     instruction::{MOpRegNum, PRegNum}, | ||||||
|     util::range_intersection, |     util::range_intersection, | ||||||
| }; | }; | ||||||
|  | @ -13,17 +13,17 @@ use fayalite::{ | ||||||
| }; | }; | ||||||
| use std::{mem, ops::Range}; | use std::{mem, ops::Range}; | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl(no_static)] | ||||||
| pub struct RenameTableReadPort<UnitNumWidth: Size, OutRegNumWidth: Size> { | pub struct RenameTableReadPort<C: Type + CpuConfigType> { | ||||||
|     pub addr: MOpRegNum, |     pub addr: MOpRegNum, | ||||||
|     #[hdl(flip)] |     #[hdl(flip)] | ||||||
|     pub data: PRegNum<UnitNumWidth, OutRegNumWidth>, |     pub data: PRegNum<C>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl(no_static)] | ||||||
| pub struct RenameTableWritePort<UnitNumWidth: Size, OutRegNumWidth: Size> { | pub struct RenameTableWritePort<C: Type + CpuConfigType> { | ||||||
|     pub addr: MOpRegNum, |     pub addr: MOpRegNum, | ||||||
|     pub data: PRegNum<UnitNumWidth, OutRegNumWidth>, |     pub data: PRegNum<C>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug)] | #[derive(Clone, Debug)] | ||||||
|  | @ -32,6 +32,8 @@ pub enum RenameTablePortConfig { | ||||||
|     Write { addr_range: Range<u32> }, |     Write { addr_range: Range<u32> }, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type C = PhantomConst<CpuConfig>; | ||||||
|  | 
 | ||||||
| /// register rename table.
 | /// register rename table.
 | ||||||
| /// all read/write operations are done in the order of `port_configs`.
 | /// all read/write operations are done in the order of `port_configs`.
 | ||||||
| /// So if `port_configs[0]` is a write and `port_configs[1]` is a read,
 | /// So if `port_configs[0]` is a write and `port_configs[1]` is a read,
 | ||||||
|  | @ -40,7 +42,7 @@ pub enum RenameTablePortConfig { | ||||||
| /// is a read and `port_configs[1]` is a write, then the read port will
 | /// is a read and `port_configs[1]` is a write, then the read port will
 | ||||||
| /// not see the data written by the write port until the *next* clock cycle.
 | /// not see the data written by the write port until the *next* clock cycle.
 | ||||||
| #[hdl_module] | #[hdl_module] | ||||||
| pub fn rename_table(config: &CpuConfig, port_configs: &[RenameTablePortConfig]) { | pub fn rename_table(config: PhantomConst<CpuConfig>, port_configs: &[RenameTablePortConfig]) { | ||||||
|     let read_count = port_configs |     let read_count = port_configs | ||||||
|         .iter() |         .iter() | ||||||
|         .filter(|v| matches!(v, RenameTablePortConfig::Read { .. })) |         .filter(|v| matches!(v, RenameTablePortConfig::Read { .. })) | ||||||
|  | @ -53,16 +55,14 @@ pub fn rename_table(config: &CpuConfig, port_configs: &[RenameTablePortConfig]) | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let cd: ClockDomain = m.input(); |     let cd: ClockDomain = m.input(); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let read_ports: Array<RenameTableReadPort<DynSize, DynSize>> = m.input( |     let read_ports: Array<RenameTableReadPort<C>> = | ||||||
|         Array[RenameTableReadPort[config.unit_num_width()][config.out_reg_num_width]][read_count], |         m.input(Array[RenameTableReadPort[config]][read_count]); | ||||||
|     ); |  | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let write_ports: Array<RenameTableWritePort<DynSize, DynSize>> = m.input( |     let write_ports: Array<RenameTableWritePort<C>> = | ||||||
|         Array[RenameTableWritePort[config.unit_num_width()][config.out_reg_num_width]][write_count], |         m.input(Array[RenameTableWritePort[config]][write_count]); | ||||||
|     ); |  | ||||||
| 
 | 
 | ||||||
|     for read_port in read_ports { |     for read_port in read_ports { | ||||||
|         connect(read_port.data, config.p_reg_num().const_zero()); |         connect(read_port.data, PRegNum[config].const_zero()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let port_configs_and_indexes = port_configs.iter().scan( |     let port_configs_and_indexes = port_configs.iter().scan( | ||||||
|  | @ -103,7 +103,7 @@ pub fn rename_table(config: &CpuConfig, port_configs: &[RenameTablePortConfig]) | ||||||
|             } else { |             } else { | ||||||
|                 format!("mem_{:#x}_{:#x}", cur_addr_range.start, cur_addr_range.end) |                 format!("mem_{:#x}_{:#x}", cur_addr_range.start, cur_addr_range.end) | ||||||
|             }, |             }, | ||||||
|             config.p_reg_num(), |             PRegNum[config], | ||||||
|             SourceLocation::caller(), |             SourceLocation::caller(), | ||||||
|         ); |         ); | ||||||
|         mem.depth(cur_addr_range.len()); |         mem.depth(cur_addr_range.len()); | ||||||
|  |  | ||||||
|  | @ -4,9 +4,13 @@ | ||||||
| use crate::config::CpuConfig; | use crate::config::CpuConfig; | ||||||
| use fayalite::prelude::*; | use fayalite::prelude::*; | ||||||
| 
 | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub struct RenameRetireInterface {} | ||||||
|  | 
 | ||||||
| #[hdl_module] | #[hdl_module] | ||||||
| pub fn retire_queue(config: &CpuConfig) { | pub fn retire_queue(config: &CpuConfig) { | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let cd: ClockDomain = m.input(); |     let cd: ClockDomain = m.input(); | ||||||
|  | 
 | ||||||
|     todo!(); |     todo!(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| // See Notices.txt for copyright information
 | // See Notices.txt for copyright information
 | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     config::CpuConfig, |     config::{CpuConfig, CpuConfigType, RetireQueueIndexWidth, UnitCount}, | ||||||
|     instruction::{ |     instruction::{ | ||||||
|         mop_enum, AluBranchMOp, LoadStoreMOp, MOp, MOpDestReg, MOpInto, MOpRegNum, MOpTrait, |         mop_enum, AluBranchMOp, LoadStoreMOp, MOp, MOpDestReg, MOpInto, MOpRegNum, MOpTrait, | ||||||
|         RenamedMOp, UnitOutRegNum, |         RenamedMOp, UnitOutRegNum, | ||||||
|  | @ -16,7 +16,7 @@ use fayalite::{ | ||||||
|     prelude::*, |     prelude::*, | ||||||
|     util::ready_valid::ReadyValid, |     util::ready_valid::ReadyValid, | ||||||
| }; | }; | ||||||
| use std::marker::PhantomData; | use serde::{Deserialize, Serialize}; | ||||||
| 
 | 
 | ||||||
| pub mod alu_branch; | pub mod alu_branch; | ||||||
| pub mod unit_base; | pub mod unit_base; | ||||||
|  | @ -38,7 +38,7 @@ macro_rules! all_units { | ||||||
|         } |         } | ||||||
|     ) => { |     ) => { | ||||||
|         $(#[$enum_meta])* |         $(#[$enum_meta])* | ||||||
|         #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] |         #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)] | ||||||
|         $vis enum $UnitKind { |         $vis enum $UnitKind { | ||||||
|             $( |             $( | ||||||
|                 $(#[$variant_meta])* |                 $(#[$variant_meta])* | ||||||
|  | @ -47,7 +47,7 @@ macro_rules! all_units { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         impl $UnitKind { |         impl $UnitKind { | ||||||
|             pub fn unit(self, config: &CpuConfig, unit_index: usize) -> DynUnit { |             pub fn unit(self, config: PhantomConst<CpuConfig>, unit_index: usize) -> DynUnit { | ||||||
|                 match self { |                 match self { | ||||||
|                     $($UnitKind::$Unit => $create_dyn_unit_fn(config, unit_index),)* |                     $($UnitKind::$Unit => $create_dyn_unit_fn(config, unit_index),)* | ||||||
|                 } |                 } | ||||||
|  | @ -261,20 +261,21 @@ pub struct GlobalState { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// index into the retire queue (the queue of instructions that haven't yet retired)
 | /// index into the retire queue (the queue of instructions that haven't yet retired)
 | ||||||
| #[hdl(cmp_eq)] | #[hdl(cmp_eq, no_static)] | ||||||
| pub struct RetireQueueIndex<Width: Size> { | pub struct RetireQueueIndex<C: Type + CpuConfigType> { | ||||||
|     /// increases by one for each instruction added to the retire queue.
 |     /// increases by one for each instruction added to the retire queue.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// this wraps around, so you must not compare it using `cmp_lt`/`cmp_gt`
 |     /// this wraps around, so you must not compare it using `cmp_lt`/`cmp_gt`
 | ||||||
|     /// but instead must use [`Self::insns_until`] and compare the output with zero.
 |     /// but instead must use [`Self::insns_until`] and compare the output with zero.
 | ||||||
|     pub index: UIntType<Width>, |     pub index: UIntType<RetireQueueIndexWidth<C>>, | ||||||
|  |     pub config: C, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<Width: Size> RetireQueueIndex<Width> { | impl<C: Type + CpuConfigType> RetireQueueIndex<C> { | ||||||
|     pub fn insns_until( |     pub fn insns_until( | ||||||
|         this: impl ToExpr<Type = Self>, |         this: impl ToExpr<Type = Self>, | ||||||
|         target: impl ToExpr<Type = Self>, |         target: impl ToExpr<Type = Self>, | ||||||
|     ) -> Expr<SIntType<Width>> { |     ) -> Expr<SIntType<RetireQueueIndexWidth<C>>> { | ||||||
|         let this = this.to_expr(); |         let this = this.to_expr(); | ||||||
|         let target = target.to_expr(); |         let target = target.to_expr(); | ||||||
|         assert_eq!(Expr::ty(this), Expr::ty(target)); |         assert_eq!(Expr::ty(this), Expr::ty(target)); | ||||||
|  | @ -282,50 +283,32 @@ impl<Width: Size> RetireQueueIndex<Width> { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl(no_static)] | ||||||
| pub struct RenamedInsnData<MOp, DestReg, RetireQueueIndexWidth: Size> { | pub struct RenamedInsnData<C: Type + CpuConfigType, MOp, DestReg> { | ||||||
|     pub retire_queue_index: RetireQueueIndex<RetireQueueIndexWidth>, |     pub retire_queue_index: RetireQueueIndex<C>, | ||||||
|     pub pc: UInt<64>, |     pub pc: UInt<64>, | ||||||
|     pub dest: DestReg, |     pub dest: DestReg, | ||||||
|     pub mop: MOp, |     pub mop: MOp, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl(no_static)] | ||||||
| pub struct UnitForwardingInfo<UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size> { | pub struct UnitForwardingInfo<C: Type + CpuConfigType> { | ||||||
|     pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<OutRegNumWidth>>, UnitCount>, |     pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<C>>, UnitCount<C>>, | ||||||
|     pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<OutRegNumWidth>>, UnitCount>, |     pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<C>>, UnitCount<C>>, | ||||||
|     pub _phantom: PhantomData<UnitNumWidth>, |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl(no_static)] | ||||||
| pub struct UnitToRegAlloc< | pub struct UnitToRegAlloc<C: Type + CpuConfigType, MOp: Type, ExtraOut: Type> { | ||||||
|     MOp: Type, |  | ||||||
|     ExtraOut: Type, |  | ||||||
|     UnitNumWidth: Size, |  | ||||||
|     OutRegNumWidth: Size, |  | ||||||
|     UnitCount: Size, |  | ||||||
|     RetireQueueIndexWidth: Size, |  | ||||||
| > { |  | ||||||
|     #[hdl(flip)] |     #[hdl(flip)] | ||||||
|     pub unit_forwarding_info: UnitForwardingInfo<UnitNumWidth, OutRegNumWidth, UnitCount>, |     pub unit_forwarding_info: UnitForwardingInfo<C>, | ||||||
|     #[hdl(flip)] |     #[hdl(flip)] | ||||||
|     pub input: |     pub input: ReadyValid<RenamedInsnData<C, MOp, UnitOutRegNum<C>>>, | ||||||
|         ReadyValid<RenamedInsnData<MOp, UnitOutRegNum<OutRegNumWidth>, RetireQueueIndexWidth>>, |  | ||||||
|     #[hdl(flip)] |     #[hdl(flip)] | ||||||
|     pub cancel_input: HdlOption<UnitCancelInput<OutRegNumWidth>>, |     pub cancel_input: HdlOption<UnitCancelInput<C>>, | ||||||
|     pub output: HdlOption<UnitOutput<OutRegNumWidth, RetireQueueIndexWidth, ExtraOut>>, |     pub output: HdlOption<UnitOutput<C, ExtraOut>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl< | impl<C: Type + CpuConfigType, MOp: Type, ExtraOut: Type> UnitToRegAlloc<C, MOp, ExtraOut> { | ||||||
|         MOp: Type, |  | ||||||
|         ExtraOut: Type, |  | ||||||
|         UnitNumWidth: Size, |  | ||||||
|         OutRegNumWidth: Size, |  | ||||||
|         UnitCount: Size, |  | ||||||
|         RetireQueueIndexWidth: Size, |  | ||||||
|     > |  | ||||||
|     UnitToRegAlloc<MOp, ExtraOut, UnitNumWidth, OutRegNumWidth, UnitCount, RetireQueueIndexWidth> |  | ||||||
| { |  | ||||||
|     pub fn mop_ty(self) -> MOp { |     pub fn mop_ty(self) -> MOp { | ||||||
|         self.input.data.HdlSome.mop |         self.input.data.HdlSome.mop | ||||||
|     } |     } | ||||||
|  | @ -340,12 +323,16 @@ pub struct UnitResultCompleted<ExtraOut> { | ||||||
|     pub extra_out: ExtraOut, |     pub extra_out: ExtraOut, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl(cmp_eq)] | #[hdl(cmp_eq, no_static)] | ||||||
| pub struct UnitOutputWrite<OutRegNumWidth: Size> { | pub struct UnitOutputWrite<C: Type + CpuConfigType> { | ||||||
|     pub dest: UnitOutRegNum<OutRegNumWidth>, |     pub dest: UnitOutRegNum<C>, | ||||||
|     pub value: PRegValue, |     pub value: PRegValue, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub type UnitOutputWrites<C: Type + CpuConfigType> = | ||||||
|  |     ArrayType<HdlOption<UnitOutputWrite<C>>, UnitCount<C>>; | ||||||
|  | 
 | ||||||
| #[hdl(cmp_eq)] | #[hdl(cmp_eq)] | ||||||
| pub struct TrapData { | pub struct TrapData { | ||||||
|     // TODO
 |     // TODO
 | ||||||
|  | @ -363,30 +350,28 @@ impl<ExtraOut: Type> UnitResult<ExtraOut> { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl(no_static)] | ||||||
| pub struct UnitOutput<OutRegNumWidth: Size, RetireQueueIndexWidth: Size, ExtraOut> { | pub struct UnitOutput<C: Type + CpuConfigType, ExtraOut> { | ||||||
|     pub dest: UnitOutRegNum<OutRegNumWidth>, |     pub dest: UnitOutRegNum<C>, | ||||||
|     pub retire_queue_index: RetireQueueIndex<RetireQueueIndexWidth>, |     pub retire_queue_index: RetireQueueIndex<C>, | ||||||
|     pub result: UnitResult<ExtraOut>, |     pub result: UnitResult<ExtraOut>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<OutRegNumWidth: Size, RetireQueueIndexWidth: Size, ExtraOut: Type> | impl<C: Type + CpuConfigType, ExtraOut: Type> UnitOutput<C, ExtraOut> { | ||||||
|     UnitOutput<OutRegNumWidth, RetireQueueIndexWidth, ExtraOut> |  | ||||||
| { |  | ||||||
|     pub fn extra_out_ty(self) -> ExtraOut { |     pub fn extra_out_ty(self) -> ExtraOut { | ||||||
|         self.result.extra_out_ty() |         self.result.extra_out_ty() | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl(cmp_eq)] | #[hdl(cmp_eq, no_static)] | ||||||
| pub struct UnitCancelInput<RetireQueueIndexWidth: Size> { | pub struct UnitCancelInput<C: Type + CpuConfigType> { | ||||||
|     pub target: RetireQueueIndex<RetireQueueIndexWidth>, |     pub target: RetireQueueIndex<C>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<RetireQueueIndexWidth: Size> UnitCancelInput<RetireQueueIndexWidth> { | impl<C: Type + CpuConfigType> UnitCancelInput<C> { | ||||||
|     pub fn is_canceled( |     pub fn is_canceled( | ||||||
|         this: impl ToExpr<Type = Self>, |         this: impl ToExpr<Type = Self>, | ||||||
|         insn_retire_queue_index: impl ToExpr<Type = RetireQueueIndex<RetireQueueIndexWidth>>, |         insn_retire_queue_index: impl ToExpr<Type = RetireQueueIndex<C>>, | ||||||
|     ) -> Expr<Bool> { |     ) -> Expr<Bool> { | ||||||
|         RetireQueueIndex::insns_until(insn_retire_queue_index, this.to_expr().target).cmp_ge(0i8) |         RetireQueueIndex::insns_until(insn_retire_queue_index, this.to_expr().target).cmp_ge(0i8) | ||||||
|     } |     } | ||||||
|  | @ -412,7 +397,7 @@ pub trait UnitTrait: | ||||||
|     fn unit_to_reg_alloc( |     fn unit_to_reg_alloc( | ||||||
|         &self, |         &self, | ||||||
|         this: Expr<Self::Type>, |         this: Expr<Self::Type>, | ||||||
|     ) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize, DynSize>>; |     ) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>>; | ||||||
| 
 | 
 | ||||||
|     fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain>; |     fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain>; | ||||||
| 
 | 
 | ||||||
|  | @ -471,7 +456,7 @@ impl UnitTrait for DynUnit { | ||||||
|     fn unit_to_reg_alloc( |     fn unit_to_reg_alloc( | ||||||
|         &self, |         &self, | ||||||
|         this: Expr<Self::Type>, |         this: Expr<Self::Type>, | ||||||
|     ) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize, DynSize>> { |     ) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> { | ||||||
|         self.unit.unit_to_reg_alloc(this) |         self.unit.unit_to_reg_alloc(this) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -523,7 +508,7 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T | ||||||
|     fn unit_to_reg_alloc( |     fn unit_to_reg_alloc( | ||||||
|         &self, |         &self, | ||||||
|         this: Expr<Self::Type>, |         this: Expr<Self::Type>, | ||||||
|     ) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize, DynSize>> { |     ) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> { | ||||||
|         Expr::from_bundle(Expr::as_bundle( |         Expr::from_bundle(Expr::as_bundle( | ||||||
|             self.0.unit_to_reg_alloc(Expr::from_bundle(this)), |             self.0.unit_to_reg_alloc(Expr::from_bundle(this)), | ||||||
|         )) |         )) | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| // See Notices.txt for copyright information
 | // See Notices.txt for copyright information
 | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     config::CpuConfig, |     config::{CpuConfig, PRegNumWidth}, | ||||||
|     instruction::{ |     instruction::{ | ||||||
|         AddSubMOp, AluBranchMOp, AluCommonMOp, CommonMOp, LogicalMOp, OutputIntegerMode, |         AddSubMOp, AluBranchMOp, AluCommonMOp, CommonMOp, LogicalMOp, OutputIntegerMode, | ||||||
|         RenamedMOp, COMMON_MOP_SRC_LEN, |         RenamedMOp, COMMON_MOP_SRC_LEN, | ||||||
|  | @ -15,10 +15,7 @@ use crate::{ | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| use fayalite::{ | use fayalite::{ | ||||||
|     intern::{Intern, Interned}, |     intern::Interned, module::wire_with_loc, prelude::*, util::ready_valid::ReadyValid, | ||||||
|     module::wire_with_loc, |  | ||||||
|     prelude::*, |  | ||||||
|     util::ready_valid::ReadyValid, |  | ||||||
| }; | }; | ||||||
| use std::{collections::HashMap, ops::RangeTo}; | use std::{collections::HashMap, ops::RangeTo}; | ||||||
| 
 | 
 | ||||||
|  | @ -245,18 +242,15 @@ fn logical( | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl_module] | #[hdl_module] | ||||||
| pub fn alu_branch(config: &CpuConfig, unit_index: usize) { | pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) { | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let cd: ClockDomain = m.input(); |     let cd: ClockDomain = m.input(); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let unit_to_reg_alloc: UnitToRegAlloc< |     let unit_to_reg_alloc: UnitToRegAlloc< | ||||||
|  |         PhantomConst<CpuConfig>, | ||||||
|         AluBranchMOp<(), DynSize>, |         AluBranchMOp<(), DynSize>, | ||||||
|         (), |         (), | ||||||
|         DynSize, |     > = m.output(UnitToRegAlloc[config][AluBranchMOp[()][PRegNumWidth[config]]][()]); | ||||||
|         DynSize, |  | ||||||
|         DynSize, |  | ||||||
|         DynSize, |  | ||||||
|     > = m.output(config.unit_to_reg_alloc(AluBranchMOp[()][config.p_reg_num_width()], ())); |  | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let global_state: GlobalState = m.input(); |     let global_state: GlobalState = m.input(); | ||||||
| 
 | 
 | ||||||
|  | @ -277,16 +271,16 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) { | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     if let HdlSome(execute_start) = ReadyValid::firing_data(unit_base.execute_start) { |     if let HdlSome(execute_start) = ReadyValid::firing_data(unit_base.execute_start) { | ||||||
|         #[hdl] |         #[hdl] | ||||||
|         let ExecuteStart::<_, _, _> { insn, src_values } = execute_start; |         let ExecuteStart::<_, _> { insn, src_values } = execute_start; | ||||||
|         #[hdl] |         #[hdl] | ||||||
|         match insn.mop { |         match insn.mop { | ||||||
|             AluBranchMOp::<_, _>::AddSub(mop) => connect( |             AluBranchMOp::<_, _>::AddSub(mop) => connect( | ||||||
|                 unit_base.execute_end, |                 unit_base.execute_end, | ||||||
|                 HdlSome( |                 HdlSome( | ||||||
|                     #[hdl] |                     #[hdl] | ||||||
|                     ExecuteEnd::<_, _, _> { |                     ExecuteEnd::<_, _> { | ||||||
|                         unit_output: #[hdl] |                         unit_output: #[hdl] | ||||||
|                         UnitOutput::<_, _, _> { |                         UnitOutput::<_, _> { | ||||||
|                             dest: insn.dest, |                             dest: insn.dest, | ||||||
|                             retire_queue_index: insn.retire_queue_index, |                             retire_queue_index: insn.retire_queue_index, | ||||||
|                             result: UnitResult[()].Completed(add_sub( |                             result: UnitResult[()].Completed(add_sub( | ||||||
|  | @ -303,9 +297,9 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) { | ||||||
|                 unit_base.execute_end, |                 unit_base.execute_end, | ||||||
|                 HdlSome( |                 HdlSome( | ||||||
|                     #[hdl] |                     #[hdl] | ||||||
|                     ExecuteEnd::<_, _, _> { |                     ExecuteEnd::<_, _> { | ||||||
|                         unit_output: #[hdl] |                         unit_output: #[hdl] | ||||||
|                         UnitOutput::<_, _, _> { |                         UnitOutput::<_, _> { | ||||||
|                             dest: insn.dest, |                             dest: insn.dest, | ||||||
|                             retire_queue_index: insn.retire_queue_index, |                             retire_queue_index: insn.retire_queue_index, | ||||||
|                             result: UnitResult[()].Completed(add_sub( |                             result: UnitResult[()].Completed(add_sub( | ||||||
|  | @ -322,9 +316,9 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) { | ||||||
|                 unit_base.execute_end, |                 unit_base.execute_end, | ||||||
|                 HdlSome( |                 HdlSome( | ||||||
|                     #[hdl] |                     #[hdl] | ||||||
|                     ExecuteEnd::<_, _, _> { |                     ExecuteEnd::<_, _> { | ||||||
|                         unit_output: #[hdl] |                         unit_output: #[hdl] | ||||||
|                         UnitOutput::<_, _, _> { |                         UnitOutput::<_, _> { | ||||||
|                             dest: insn.dest, |                             dest: insn.dest, | ||||||
|                             retire_queue_index: insn.retire_queue_index, |                             retire_queue_index: insn.retire_queue_index, | ||||||
|                             result: UnitResult[()].Completed(logical( |                             result: UnitResult[()].Completed(logical( | ||||||
|  | @ -342,14 +336,14 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) { | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | ||||||
| pub struct AluBranch { | pub struct AluBranch { | ||||||
|     config: Interned<CpuConfig>, |     config: PhantomConst<CpuConfig>, | ||||||
|     module: Interned<Module<alu_branch>>, |     module: Interned<Module<alu_branch>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl AluBranch { | impl AluBranch { | ||||||
|     pub fn new(config: &CpuConfig, unit_index: usize) -> Self { |     pub fn new(config: PhantomConst<CpuConfig>, unit_index: usize) -> Self { | ||||||
|         Self { |         Self { | ||||||
|             config: config.intern(), |             config, | ||||||
|             module: alu_branch(config, unit_index), |             module: alu_branch(config, unit_index), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -387,7 +381,7 @@ impl UnitTrait for AluBranch { | ||||||
|     fn unit_to_reg_alloc( |     fn unit_to_reg_alloc( | ||||||
|         &self, |         &self, | ||||||
|         this: Expr<Self::Type>, |         this: Expr<Self::Type>, | ||||||
|     ) -> Expr<UnitToRegAlloc<Self::MOp, Self::ExtraOut, DynSize, DynSize, DynSize, DynSize>> { |     ) -> Expr<UnitToRegAlloc<PhantomConst<CpuConfig>, Self::MOp, Self::ExtraOut>> { | ||||||
|         this.unit_to_reg_alloc |         this.unit_to_reg_alloc | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| // See Notices.txt for copyright information
 | // See Notices.txt for copyright information
 | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     config::CpuConfig, |     config::{CpuConfig, CpuConfigType, UnitOutRegNumWidth}, | ||||||
|     instruction::{MOpTrait, PRegNum, UnitNum, UnitOutRegNum, COMMON_MOP_SRC_LEN}, |     instruction::{MOpTrait, PRegNum, UnitNum, UnitOutRegNum, COMMON_MOP_SRC_LEN}, | ||||||
|     register::PRegValue, |     register::PRegValue, | ||||||
|     unit::{ |     unit::{ | ||||||
|  | @ -18,15 +18,15 @@ use fayalite::{ | ||||||
|     util::{prefix_sum::reduce, ready_valid::ReadyValid}, |     util::{prefix_sum::reduce, ready_valid::ReadyValid}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl(no_static)] | ||||||
| pub struct ExecuteStart<MOp: Type, OutRegNumWidth: Size, RetireQueueIndexWidth: Size> { | pub struct ExecuteStart<C: Type + CpuConfigType, MOp: Type> { | ||||||
|     pub insn: RenamedInsnData<MOp, UnitOutRegNum<OutRegNumWidth>, RetireQueueIndexWidth>, |     pub insn: RenamedInsnData<C, MOp, UnitOutRegNum<C>>, | ||||||
|     pub src_values: Array<PRegValue, { COMMON_MOP_SRC_LEN }>, |     pub src_values: Array<PRegValue, { COMMON_MOP_SRC_LEN }>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl(no_static)] | ||||||
| pub struct ExecuteEnd<OutRegNumWidth: Size, RetireQueueIndexWidth: Size, ExtraOut> { | pub struct ExecuteEnd<C: Type + CpuConfigType, ExtraOut> { | ||||||
|     pub unit_output: UnitOutput<OutRegNumWidth, RetireQueueIndexWidth, ExtraOut>, |     pub unit_output: UnitOutput<C, ExtraOut>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl] | ||||||
|  | @ -106,10 +106,10 @@ impl InFlightOpState { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl(no_static)] | ||||||
| struct InFlightOp<MOp: Type, OutRegNumWidth: Size, RetireQueueIndexWidth: Size> { | struct InFlightOp<C: Type + CpuConfigType, MOp: Type> { | ||||||
|     state: InFlightOpState, |     state: InFlightOpState, | ||||||
|     insn: RenamedInsnData<MOp, UnitOutRegNum<OutRegNumWidth>, RetireQueueIndexWidth>, |     insn: RenamedInsnData<C, MOp, UnitOutRegNum<C>>, | ||||||
|     src_ready_flags: Array<Bool, { COMMON_MOP_SRC_LEN }>, |     src_ready_flags: Array<Bool, { COMMON_MOP_SRC_LEN }>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -124,7 +124,7 @@ impl<OpIndexWidth: Size> InFlightOpsSummary<OpIndexWidth> { | ||||||
|     fn new<MOp: Type>( |     fn new<MOp: Type>( | ||||||
|         op_index: usize, |         op_index: usize, | ||||||
|         op_index_ty: UIntType<OpIndexWidth>, |         op_index_ty: UIntType<OpIndexWidth>, | ||||||
|         in_flight_op: impl ToExpr<Type = HdlOption<InFlightOp<MOp, DynSize, DynSize>>>, |         in_flight_op: impl ToExpr<Type = HdlOption<InFlightOp<PhantomConst<CpuConfig>, MOp>>>, | ||||||
|     ) -> Expr<Self> { |     ) -> Expr<Self> { | ||||||
|         let empty_op_index = wire_with_loc( |         let empty_op_index = wire_with_loc( | ||||||
|             &format!("empty_op_index_{op_index}"), |             &format!("empty_op_index_{op_index}"), | ||||||
|  | @ -141,7 +141,7 @@ impl<OpIndexWidth: Size> InFlightOpsSummary<OpIndexWidth> { | ||||||
|         #[hdl] |         #[hdl] | ||||||
|         if let HdlSome(in_flight_op) = in_flight_op { |         if let HdlSome(in_flight_op) = in_flight_op { | ||||||
|             #[hdl] |             #[hdl] | ||||||
|             let InFlightOp::<_, _, _> { |             let InFlightOp::<_, _> { | ||||||
|                 state, |                 state, | ||||||
|                 insn: _, |                 insn: _, | ||||||
|                 src_ready_flags, |                 src_ready_flags, | ||||||
|  | @ -182,7 +182,7 @@ impl<OpIndexWidth: Size> InFlightOpsSummary<OpIndexWidth> { | ||||||
| impl InFlightOpsSummary<DynSize> { | impl InFlightOpsSummary<DynSize> { | ||||||
|     fn summarize<MOp: Type, MaxInFlight: Size>( |     fn summarize<MOp: Type, MaxInFlight: Size>( | ||||||
|         in_flight_ops: impl ToExpr< |         in_flight_ops: impl ToExpr< | ||||||
|             Type = ArrayType<HdlOption<InFlightOp<MOp, DynSize, DynSize>>, MaxInFlight>, |             Type = ArrayType<HdlOption<InFlightOp<PhantomConst<CpuConfig>, MOp>>, MaxInFlight>, | ||||||
|         >, |         >, | ||||||
|     ) -> Expr<Self> { |     ) -> Expr<Self> { | ||||||
|         let in_flight_ops = in_flight_ops.to_expr(); |         let in_flight_ops = in_flight_ops.to_expr(); | ||||||
|  | @ -199,7 +199,7 @@ impl InFlightOpsSummary<DynSize> { | ||||||
| 
 | 
 | ||||||
| #[hdl_module] | #[hdl_module] | ||||||
| pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, ExtraOut: Type>( | pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, ExtraOut: Type>( | ||||||
|     config: &CpuConfig, |     config: PhantomConst<CpuConfig>, | ||||||
|     unit_index: usize, |     unit_index: usize, | ||||||
|     mop_ty: MOp, |     mop_ty: MOp, | ||||||
|     extra_out_ty: ExtraOut, |     extra_out_ty: ExtraOut, | ||||||
|  | @ -207,20 +207,19 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let cd: ClockDomain = m.input(); |     let cd: ClockDomain = m.input(); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let unit_to_reg_alloc: UnitToRegAlloc<MOp, ExtraOut, DynSize, DynSize, DynSize, DynSize> = |     let unit_to_reg_alloc: UnitToRegAlloc<PhantomConst<CpuConfig>, MOp, ExtraOut> = | ||||||
|         m.output(config.unit_to_reg_alloc(mop_ty, extra_out_ty)); |         m.output(UnitToRegAlloc[config][mop_ty][extra_out_ty]); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let execute_start: ReadyValid<ExecuteStart<MOp, DynSize, DynSize>> = |     let execute_start: ReadyValid<ExecuteStart<PhantomConst<CpuConfig>, MOp>> = | ||||||
|         m.output(ReadyValid[config.execute_start(mop_ty)]); |         m.output(ReadyValid[ExecuteStart[config][mop_ty]]); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let execute_end: HdlOption<ExecuteEnd<DynSize, DynSize, ExtraOut>> = |     let execute_end: HdlOption<ExecuteEnd<PhantomConst<CpuConfig>, ExtraOut>> = | ||||||
|         m.input(HdlOption[config.execute_end(extra_out_ty)]); |         m.input(HdlOption[ExecuteEnd[config][extra_out_ty]]); | ||||||
| 
 | 
 | ||||||
|     connect(execute_start.data, Expr::ty(execute_start).data.HdlNone()); |     connect(execute_start.data, Expr::ty(execute_start).data.HdlNone()); | ||||||
| 
 | 
 | ||||||
|     let max_in_flight = config.unit_max_in_flight(unit_index).get(); |     let max_in_flight = config.get().unit_max_in_flight(unit_index).get(); | ||||||
|     let in_flight_op_ty = |     let in_flight_op_ty = InFlightOp[config][mop_ty]; | ||||||
|         InFlightOp[mop_ty][config.out_reg_num_width][config.retire_queue_index_width()]; |  | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let in_flight_ops = reg_builder() |     let in_flight_ops = reg_builder() | ||||||
|         .clock_domain(cd) |         .clock_domain(cd) | ||||||
|  | @ -237,16 +236,15 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let UnitForwardingInfo::<_, _, _> { |     let UnitForwardingInfo::<_> { | ||||||
|         unit_output_writes, |         unit_output_writes, | ||||||
|         unit_reg_frees, |         unit_reg_frees, | ||||||
|         _phantom: _, |  | ||||||
|     } = unit_to_reg_alloc.unit_forwarding_info; |     } = unit_to_reg_alloc.unit_forwarding_info; | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let read_src_regs = wire(mop_ty.src_regs_ty()); |     let read_src_regs = wire(mop_ty.src_regs_ty()); | ||||||
|     connect( |     connect( | ||||||
|         read_src_regs, |         read_src_regs, | ||||||
|         repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize), |         repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize), | ||||||
|     ); |     ); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let read_src_values = wire(); |     let read_src_values = wire(); | ||||||
|  | @ -255,7 +253,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|     let input_src_regs = wire(mop_ty.src_regs_ty()); |     let input_src_regs = wire(mop_ty.src_regs_ty()); | ||||||
|     connect( |     connect( | ||||||
|         input_src_regs, |         input_src_regs, | ||||||
|         repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize), |         repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize), | ||||||
|     ); |     ); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let input_src_regs_valid = wire(); |     let input_src_regs_valid = wire(); | ||||||
|  | @ -267,7 +265,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|                 Bool, |                 Bool, | ||||||
|                 SourceLocation::caller(), |                 SourceLocation::caller(), | ||||||
|             ); |             ); | ||||||
|             mem.depth(1 << config.out_reg_num_width); |             mem.depth(1 << UnitOutRegNumWidth[config]); | ||||||
|             mem |             mem | ||||||
|         }) |         }) | ||||||
|         .collect(); |         .collect(); | ||||||
|  | @ -277,11 +275,11 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|             PRegValue, |             PRegValue, | ||||||
|             SourceLocation::caller(), |             SourceLocation::caller(), | ||||||
|         ); |         ); | ||||||
|         unit_output_regs.depth(1 << config.out_reg_num_width); |         unit_output_regs.depth(1 << UnitOutRegNumWidth[config]); | ||||||
| 
 | 
 | ||||||
|         for src_index in 0..COMMON_MOP_SRC_LEN { |         for src_index in 0..COMMON_MOP_SRC_LEN { | ||||||
|             let read_port = unit_output_regs.new_read_port(); |             let read_port = unit_output_regs.new_read_port(); | ||||||
|             let p_reg_num = read_src_regs[src_index].cast_bits_to(config.p_reg_num()); |             let p_reg_num = read_src_regs[src_index].cast_bits_to(PRegNum[config]); | ||||||
|             connect_any(read_port.addr, p_reg_num.unit_out_reg.value); |             connect_any(read_port.addr, p_reg_num.unit_out_reg.value); | ||||||
|             connect(read_port.en, false); |             connect(read_port.en, false); | ||||||
|             connect(read_port.clk, cd.clk); |             connect(read_port.clk, cd.clk); | ||||||
|  | @ -294,7 +292,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
| 
 | 
 | ||||||
|         for src_index in 0..COMMON_MOP_SRC_LEN { |         for src_index in 0..COMMON_MOP_SRC_LEN { | ||||||
|             let read_port = unit_output_regs_valid[unit_index].new_read_port(); |             let read_port = unit_output_regs_valid[unit_index].new_read_port(); | ||||||
|             let p_reg_num = input_src_regs[src_index].cast_bits_to(config.p_reg_num()); |             let p_reg_num = input_src_regs[src_index].cast_bits_to(PRegNum[config]); | ||||||
|             connect_any(read_port.addr, p_reg_num.unit_out_reg.value); |             connect_any(read_port.addr, p_reg_num.unit_out_reg.value); | ||||||
|             connect(read_port.en, false); |             connect(read_port.en, false); | ||||||
|             connect(read_port.clk, cd.clk); |             connect(read_port.clk, cd.clk); | ||||||
|  | @ -325,8 +323,8 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|             connect_any(ready_write_port.addr, unit_output_write.dest.value); |             connect_any(ready_write_port.addr, unit_output_write.dest.value); | ||||||
|             connect(ready_write_port.en, true); |             connect(ready_write_port.en, true); | ||||||
|             let p_reg_num = #[hdl] |             let p_reg_num = #[hdl] | ||||||
|             PRegNum::<_, _> { |             PRegNum::<_> { | ||||||
|                 unit_num: config.unit_num().from_index(unit_index), |                 unit_num: UnitNum[config].from_index(unit_index), | ||||||
|                 unit_out_reg: unit_output_write.dest, |                 unit_out_reg: unit_output_write.dest, | ||||||
|             }; |             }; | ||||||
|             for src_index in 0..COMMON_MOP_SRC_LEN { |             for src_index in 0..COMMON_MOP_SRC_LEN { | ||||||
|  | @ -357,7 +355,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|                 execute_start.data, |                 execute_start.data, | ||||||
|                 HdlSome( |                 HdlSome( | ||||||
|                     #[hdl] |                     #[hdl] | ||||||
|                     ExecuteStart::<_, _, _> { |                     ExecuteStart::<_, _> { | ||||||
|                         insn: in_flight_op.insn, |                         insn: in_flight_op.insn, | ||||||
|                         src_values: read_src_values, |                         src_values: read_src_values, | ||||||
|                     }, |                     }, | ||||||
|  | @ -387,7 +385,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|         let input_mop_src_regs = wire(mop_ty.src_regs_ty()); |         let input_mop_src_regs = wire(mop_ty.src_regs_ty()); | ||||||
|         connect( |         connect( | ||||||
|             input_mop_src_regs, |             input_mop_src_regs, | ||||||
|             repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize), |             repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize), | ||||||
|         ); |         ); | ||||||
|         MOp::connect_src_regs(mop, input_mop_src_regs); |         MOp::connect_src_regs(mop, input_mop_src_regs); | ||||||
|         let src_ready_flags = wire_with_loc( |         let src_ready_flags = wire_with_loc( | ||||||
|  | @ -413,7 +411,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|                 input_in_flight_op, |                 input_in_flight_op, | ||||||
|                 HdlSome( |                 HdlSome( | ||||||
|                     #[hdl] |                     #[hdl] | ||||||
|                     InFlightOp::<_, _, _> { |                     InFlightOp::<_, _> { | ||||||
|                         state: InFlightOpState.Ready(), |                         state: InFlightOpState.Ready(), | ||||||
|                         insn: input, |                         insn: input, | ||||||
|                         src_ready_flags, |                         src_ready_flags, | ||||||
|  | @ -449,7 +447,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|         #[hdl] |         #[hdl] | ||||||
|         if let HdlSome(in_flight_op) = in_flight_ops[in_flight_op_index] { |         if let HdlSome(in_flight_op) = in_flight_ops[in_flight_op_index] { | ||||||
|             #[hdl] |             #[hdl] | ||||||
|             let InFlightOp::<_, _, _> { |             let InFlightOp::<_, _> { | ||||||
|                 state, |                 state, | ||||||
|                 insn, |                 insn, | ||||||
|                 src_ready_flags, |                 src_ready_flags, | ||||||
|  | @ -461,7 +459,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|             ); |             ); | ||||||
|             connect( |             connect( | ||||||
|                 src_regs, |                 src_regs, | ||||||
|                 repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize), |                 repeat(PRegNum[config].const_zero().cast_to_bits(), ConstUsize), | ||||||
|             ); |             ); | ||||||
|             MOp::connect_src_regs(insn.mop, src_regs); |             MOp::connect_src_regs(insn.mop, src_regs); | ||||||
| 
 | 
 | ||||||
|  | @ -485,8 +483,8 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|                         value: _, |                         value: _, | ||||||
|                     } = unit_output_write; |                     } = unit_output_write; | ||||||
|                     let p_reg_num = #[hdl] |                     let p_reg_num = #[hdl] | ||||||
|                     PRegNum::<_, _> { |                     PRegNum::<_> { | ||||||
|                         unit_num: config.unit_num().from_index(unit_index), |                         unit_num: UnitNum[config].from_index(unit_index), | ||||||
|                         unit_out_reg, |                         unit_out_reg, | ||||||
|                     }; |                     }; | ||||||
|                     for src_index in 0..COMMON_MOP_SRC_LEN { |                     for src_index in 0..COMMON_MOP_SRC_LEN { | ||||||
|  | @ -513,7 +511,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|             #[hdl] |             #[hdl] | ||||||
|             if let HdlSome(execute_end) = execute_end { |             if let HdlSome(execute_end) = execute_end { | ||||||
|                 #[hdl] |                 #[hdl] | ||||||
|                 let ExecuteEnd::<_, _, _> { unit_output } = execute_end; |                 let ExecuteEnd::<_, _> { unit_output } = execute_end; | ||||||
|                 #[hdl] |                 #[hdl] | ||||||
|                 if insn.dest.cmp_eq(unit_output.dest) { |                 if insn.dest.cmp_eq(unit_output.dest) { | ||||||
|                     connect(in_flight_op_execute_ending[in_flight_op_index], true); |                     connect(in_flight_op_execute_ending[in_flight_op_index], true); | ||||||
|  | @ -559,7 +557,7 @@ pub fn unit_base<MOp: Type + MOpTrait<DestReg = (), SrcRegWidth = DynSize>, Extr | ||||||
|                     in_flight_ops[in_flight_op_index], |                     in_flight_ops[in_flight_op_index], | ||||||
|                     HdlSome( |                     HdlSome( | ||||||
|                         #[hdl] |                         #[hdl] | ||||||
|                         InFlightOp::<_, _, _> { |                         InFlightOp::<_, _> { | ||||||
|                             state, |                             state, | ||||||
|                             insn, |                             insn, | ||||||
|                             src_ready_flags: in_flight_op_next_src_ready_flags[in_flight_op_index], |                             src_ready_flags: in_flight_op_next_src_ready_flags[in_flight_op_index], | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue