forked from libre-chip/cpu
		
	WIP: adding micro ops
This commit is contained in:
		
							parent
							
								
									0f4f067996
								
							
						
					
					
						commit
						4c3dd128a3
					
				
					 5 changed files with 149 additions and 39 deletions
				
			
		
							
								
								
									
										8
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -279,7 +279,7 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" | ||||||
| [[package]] | [[package]] | ||||||
| name = "fayalite" | name = "fayalite" | ||||||
| version = "0.2.0" | version = "0.2.0" | ||||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#bf907c38721ebc804d6aaf0bf5ed6798d8604dab" | source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#1a2149b0406fd29fa2032532dfba3b371cf74a26" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "bitvec", |  "bitvec", | ||||||
|  "blake3", |  "blake3", | ||||||
|  | @ -300,7 +300,7 @@ dependencies = [ | ||||||
| [[package]] | [[package]] | ||||||
| name = "fayalite-proc-macros" | name = "fayalite-proc-macros" | ||||||
| version = "0.2.0" | version = "0.2.0" | ||||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#bf907c38721ebc804d6aaf0bf5ed6798d8604dab" | source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#1a2149b0406fd29fa2032532dfba3b371cf74a26" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "fayalite-proc-macros-impl", |  "fayalite-proc-macros-impl", | ||||||
| ] | ] | ||||||
|  | @ -308,7 +308,7 @@ dependencies = [ | ||||||
| [[package]] | [[package]] | ||||||
| name = "fayalite-proc-macros-impl" | name = "fayalite-proc-macros-impl" | ||||||
| version = "0.2.0" | version = "0.2.0" | ||||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#bf907c38721ebc804d6aaf0bf5ed6798d8604dab" | source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#1a2149b0406fd29fa2032532dfba3b371cf74a26" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "base16ct", |  "base16ct", | ||||||
|  "num-bigint", |  "num-bigint", | ||||||
|  | @ -323,7 +323,7 @@ dependencies = [ | ||||||
| [[package]] | [[package]] | ||||||
| name = "fayalite-visit-gen" | name = "fayalite-visit-gen" | ||||||
| version = "0.2.0" | version = "0.2.0" | ||||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#bf907c38721ebc804d6aaf0bf5ed6798d8604dab" | source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#1a2149b0406fd29fa2032532dfba3b371cf74a26" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "indexmap", |  "indexmap", | ||||||
|  "prettyplease", |  "prettyplease", | ||||||
|  |  | ||||||
|  | @ -11,4 +11,4 @@ impl CpuConfig { | ||||||
|     pub fn unit_num(&self) -> UnitNum<DynSize> { |     pub fn unit_num(&self) -> UnitNum<DynSize> { | ||||||
|         UnitNum[UInt::range(0..self.units.len()).width()] |         UnitNum[UInt::range(0..self.units.len()).width()] | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| use fayalite::prelude::*; |  | ||||||
| use crate::config::CpuConfig; | use crate::config::CpuConfig; | ||||||
|  | use fayalite::prelude::*; | ||||||
|  | use std::marker::PhantomData; | ||||||
| 
 | 
 | ||||||
| pub mod power_isa; | pub mod power_isa; | ||||||
| 
 | 
 | ||||||
|  | @ -9,7 +10,7 @@ macro_rules! all_units { | ||||||
|         #[unit_kind = $UnitKind:ident] |         #[unit_kind = $UnitKind:ident] | ||||||
|         #[hdl] |         #[hdl] | ||||||
|         $(#[$enum_meta:meta])* |         $(#[$enum_meta:meta])* | ||||||
|         $vis:vis enum $UnitMOpEnum:ident { |         $vis:vis enum $UnitMOpEnum:ident<$RegWidth:ident: Size> { | ||||||
|             $( |             $( | ||||||
|                 $(#[$variant_meta:meta])* |                 $(#[$variant_meta:meta])* | ||||||
|                 $Unit:ident($Op:ty), |                 $Unit:ident($Op:ty), | ||||||
|  | @ -46,21 +47,21 @@ macro_rules! all_units { | ||||||
| 
 | 
 | ||||||
|         #[hdl] |         #[hdl] | ||||||
|         $(#[$enum_meta])* |         $(#[$enum_meta])* | ||||||
|         $vis enum $UnitMOpEnum { |         $vis enum $UnitMOpEnum<$RegWidth: Size> { | ||||||
|             $( |             $( | ||||||
|                 $(#[$variant_meta])* |                 $(#[$variant_meta])* | ||||||
|                 $Unit($Op), |                 $Unit($Op), | ||||||
|             )* |             )* | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         impl $UnitMOpEnum { |         impl<$RegWidth: Size> $UnitMOpEnum<$RegWidth> { | ||||||
|             #[hdl] |             #[hdl] | ||||||
|             $vis fn kind(expr: impl ToExpr<Type = Self>) -> Expr<$HdlUnitKind> { |             $vis fn kind(expr: impl ToExpr<Type = Self>) -> Expr<$HdlUnitKind> { | ||||||
|                 #[hdl] |                 #[hdl] | ||||||
|                 let unit_kind = wire(); |                 let unit_kind = wire(); | ||||||
|                 #[hdl] |                 #[hdl] | ||||||
|                 match expr { |                 match expr { | ||||||
|                     $($UnitMOpEnum::$Unit(_) => connect(unit_kind, $HdlUnitKind.$Unit()),)* |                     $($UnitMOpEnum::<$RegWidth>::$Unit(_) => connect(unit_kind, $HdlUnitKind.$Unit()),)* | ||||||
|                 } |                 } | ||||||
|                 unit_kind |                 unit_kind | ||||||
|             } |             } | ||||||
|  | @ -87,32 +88,152 @@ all_units! { | ||||||
|     #[hdl_unit_kind = HdlUnitKind] |     #[hdl_unit_kind = HdlUnitKind] | ||||||
|     #[unit_kind = UnitKind] |     #[unit_kind = UnitKind] | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     pub enum UnitMOp { |     pub enum UnitMOp<RegWidth: Size> { | ||||||
|         AluBranch(AluBranchMOp), |         AluBranch(AluBranchMOp<RegWidth>), | ||||||
|         L2RegisterFile(L2RegisterFileMOp), |         L2RegisterFile(L2RegisterFileMOp<RegWidth>), | ||||||
|         LoadStore(LoadStoreMOp), |         LoadStore(LoadStoreMOp<RegWidth>), | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl] | ||||||
| pub enum AluBranchMOp { | pub enum OutputIntegerMode { | ||||||
|     Add64, |     Full64, | ||||||
|     Sub64, |     DupLow32, | ||||||
|     And64, |     ZeroExt32, | ||||||
|     Or64, |     SignExt32, | ||||||
|     Xor64, |     ZeroExt16, | ||||||
|  |     SignExt16, | ||||||
|  |     ZeroExt8, | ||||||
|  |     SignExt8, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub const MOP_IMM_WIDTH: usize = 34; | ||||||
|  | pub const MOP_MIN_REG_WIDTH: usize = 8; | ||||||
|  | pub const COMMON_MOP_OTHER_WIDTH: usize = | ||||||
|  |     MOP_IMM_WIDTH - (COMMON_MOP_SRC_REG_COUNT - COMMON_MOP_IMM_SRC_REG_COUNT) * MOP_MIN_REG_WIDTH; | ||||||
|  | pub const COMMON_MOP_SRC_REG_COUNT: usize = 3; | ||||||
|  | pub const COMMON_MOP_IMM_SRC_REG_COUNT: usize = 2; | ||||||
|  | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub struct CommonMOp<PrefixPad: KnownSize, RegWidth: Size, SrcCount: KnownSize> { | ||||||
|  |     pub prefix_pad: UIntType<PrefixPad>, | ||||||
|  |     pub dest: UIntType<RegWidth>, | ||||||
|  |     pub src: Array<UIntType<RegWidth>, { COMMON_MOP_SRC_REG_COUNT }>, | ||||||
|  |     pub other: UInt<{ COMMON_MOP_OTHER_WIDTH }>, | ||||||
|  |     pub _phantom: PhantomData<SrcCount>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<PrefixPad: KnownSize, RegWidth: Size, SrcCount: KnownSize> | ||||||
|  |     CommonMOp<PrefixPad, RegWidth, SrcCount> | ||||||
|  | { | ||||||
|  |     pub fn imm_ty(self) -> SInt { | ||||||
|  |         assert!(self.src.element().width() >= MOP_MIN_REG_WIDTH); | ||||||
|  |         assert!(SrcCount::VALUE <= COMMON_MOP_SRC_REG_COUNT); | ||||||
|  |         SInt[(COMMON_MOP_SRC_REG_COUNT - SrcCount::VALUE) * MOP_MIN_REG_WIDTH | ||||||
|  |             + COMMON_MOP_OTHER_WIDTH] | ||||||
|  |     } | ||||||
|  |     #[hdl] | ||||||
|  |     pub fn imm(expr: impl ToExpr<Type = Self>) -> Expr<SInt> { | ||||||
|  |         let expr = expr.to_expr(); | ||||||
|  |         assert!(Expr::ty(expr).src.element().width() >= MOP_MIN_REG_WIDTH); | ||||||
|  |         let mut acc = expr.other[..COMMON_MOP_OTHER_WIDTH - 1]; | ||||||
|  |         for i in SrcCount::VALUE..COMMON_MOP_SRC_REG_COUNT { | ||||||
|  |             acc = (acc, expr.src[i][..MOP_MIN_REG_WIDTH]).cast_to_bits(); | ||||||
|  |         } | ||||||
|  |         acc = (acc, expr.other[COMMON_MOP_OTHER_WIDTH - 1]).cast_to_bits(); | ||||||
|  |         #[hdl] | ||||||
|  |         let imm = wire(Expr::ty(expr).imm_ty()); | ||||||
|  |         debug_assert_eq!(Expr::ty(acc).width(), Expr::ty(imm).width()); | ||||||
|  |         connect(imm, acc.cast_to(Expr::ty(imm))); | ||||||
|  |         imm | ||||||
|  |     } | ||||||
|  |     #[hdl] | ||||||
|  |     pub fn connect_to_imm(expr: impl ToExpr<Type = Self>, imm: impl ToExpr<Type = SInt>) { | ||||||
|  |         let expr = expr.to_expr(); | ||||||
|  |         let imm = imm.to_expr(); | ||||||
|  |         let imm_ty = Expr::ty(expr).imm_ty(); | ||||||
|  |         assert_eq!(Expr::ty(imm), imm_ty); | ||||||
|  |         let mut pos = COMMON_MOP_OTHER_WIDTH - 1; | ||||||
|  |         connect_any( | ||||||
|  |             expr.other, | ||||||
|  |             (imm[..pos], imm[imm_ty.width() - 1]).cast_to_bits(), | ||||||
|  |         ); | ||||||
|  |         for i in SrcCount::VALUE..COMMON_MOP_SRC_REG_COUNT { | ||||||
|  |             connect_any(expr.src[i], imm[pos..pos + MOP_MIN_REG_WIDTH]); | ||||||
|  |             pos += MOP_MIN_REG_WIDTH; | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl] | ||||||
| pub enum L2RegisterFileMOp { | pub struct AluCommonMOp<RegWidth: Size, SrcCount: KnownSize> { | ||||||
|     Read, |     pub common: CommonMOp<ConstUsize<0>, RegWidth, SrcCount>, | ||||||
|     Write, |     pub output_integer_mode: OutputIntegerMode, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl] | ||||||
| pub enum LoadStoreMOp { | pub struct AddSubMOp<RegWidth: Size, SrcCount: KnownSize> { | ||||||
|     Load, |     pub alu_common: AluCommonMOp<RegWidth, SrcCount>, | ||||||
|     Store, |     pub invert_src0: Bool, | ||||||
|  |     pub invert_carry_in: Bool, | ||||||
|  |     pub invert_carry_out: Bool, | ||||||
|  |     pub add_pc: Bool, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub struct LogicalMOp<RegWidth: Size> { | ||||||
|  |     pub alu_common: AluCommonMOp<RegWidth, ConstUsize<2>>, | ||||||
|  |     pub lut: UInt<4>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub struct BranchMOp<RegWidth: Size> { | ||||||
|  |     pub alu_common: AluCommonMOp<RegWidth, ConstUsize<2>>, | ||||||
|  |     pub lut: UInt<4>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub enum AluBranchMOp<RegWidth: Size> { | ||||||
|  |     AddSub(AddSubMOp<RegWidth, ConstUsize<3>>), | ||||||
|  |     AddSubI(AddSubMOp<RegWidth, ConstUsize<2>>), | ||||||
|  |     Logical(LogicalMOp<RegWidth>), | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub struct ReadL2RegMOp<RegWidth: Size> { | ||||||
|  |     pub common: CommonMOp<ConstUsize<1>, RegWidth, ConstUsize<0>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub struct WriteL2RegMOp<RegWidth: Size> { | ||||||
|  |     pub common: CommonMOp<ConstUsize<1>, RegWidth, ConstUsize<1>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub enum L2RegisterFileMOp<RegWidth: Size> { | ||||||
|  |     ReadL2Reg(ReadL2RegMOp<RegWidth>), | ||||||
|  |     WriteL2Reg(WriteL2RegMOp<RegWidth>), | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub struct LoadStoreCommonMOp<RegWidth: Size, SrcCount: KnownSize> { | ||||||
|  |     pub common: CommonMOp<ConstUsize<1>, RegWidth, SrcCount>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub struct LoadMOp<RegWidth: Size> { | ||||||
|  |     pub load_store_common: LoadStoreCommonMOp<RegWidth, ConstUsize<1>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub struct StoreMOp<RegWidth: Size> { | ||||||
|  |     pub load_store_common: LoadStoreCommonMOp<RegWidth, ConstUsize<2>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[hdl] | ||||||
|  | pub enum LoadStoreMOp<RegWidth: Size> { | ||||||
|  |     Load(CommonMOp<ConstUsize<1>, RegWidth, ConstUsize<0>>), | ||||||
|  |     Store(CommonMOp<ConstUsize<1>, RegWidth, ConstUsize<1>>), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[hdl] | #[hdl] | ||||||
|  | @ -142,14 +263,3 @@ pub struct PRegNum<UnitNumWidth: Size, OutRegNumWidth: Size> { | ||||||
| pub struct MOpRegNum { | pub struct MOpRegNum { | ||||||
|     pub value: UInt<8>, |     pub value: UInt<8>, | ||||||
| } | } | ||||||
| 
 |  | ||||||
| #[hdl] |  | ||||||
| /// µOp -- a micro-operation
 |  | ||||||
| #[doc(alias = "UOp")] // help you find it in the docs if you mis-spell it
 |  | ||||||
| #[doc(alias = "\u{B5}Op")] // micro sign
 |  | ||||||
| #[doc(alias = "\u{39C}Op")] // greek capital letter mu
 |  | ||||||
| #[doc(alias = "\u{3BC}Op")] // greek small letter mu
 |  | ||||||
| pub struct MOp { |  | ||||||
|     pub op: UnitMOp, |  | ||||||
|     pub value: UInt<8>, |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -19,4 +19,4 @@ pub struct PowerIsaCrFieldNum { | ||||||
| pub struct PowerIsaCrBitNum { | pub struct PowerIsaCrBitNum { | ||||||
|     pub cr_field: PowerIsaCrFieldNum, |     pub cr_field: PowerIsaCrFieldNum, | ||||||
|     pub bit_in_field: UInt<2>, |     pub bit_in_field: UInt<2>, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,2 +1,2 @@ | ||||||
|  | pub mod config; | ||||||
| pub mod instruction; | pub mod instruction; | ||||||
| pub mod config; |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue