Compare commits
	
		
			2 commits
		
	
	
		
			265b5a9cec
			...
			b51109f4f6
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b51109f4f6 | |||
| 1a72425156 | 
					 6 changed files with 155 additions and 14 deletions
				
			
		
							
								
								
									
										16
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										16
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -299,8 +299,8 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" | |||
| 
 | ||||
| [[package]] | ||||
| name = "fayalite" | ||||
| version = "0.2.0" | ||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#cb17913004259b6e0908a477a67e5a6b621b5c1c" | ||||
| version = "0.2.1" | ||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#3d5d8c54b6f2b7bbb0a31458c00139359ca3006e" | ||||
| dependencies = [ | ||||
|  "bitvec", | ||||
|  "blake3", | ||||
|  | @ -322,16 +322,16 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "fayalite-proc-macros" | ||||
| version = "0.2.0" | ||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#cb17913004259b6e0908a477a67e5a6b621b5c1c" | ||||
| version = "0.2.1" | ||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#3d5d8c54b6f2b7bbb0a31458c00139359ca3006e" | ||||
| dependencies = [ | ||||
|  "fayalite-proc-macros-impl", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "fayalite-proc-macros-impl" | ||||
| version = "0.2.0" | ||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#cb17913004259b6e0908a477a67e5a6b621b5c1c" | ||||
| version = "0.2.1" | ||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#3d5d8c54b6f2b7bbb0a31458c00139359ca3006e" | ||||
| dependencies = [ | ||||
|  "base16ct", | ||||
|  "num-bigint", | ||||
|  | @ -345,8 +345,8 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "fayalite-visit-gen" | ||||
| version = "0.2.0" | ||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#cb17913004259b6e0908a477a67e5a6b621b5c1c" | ||||
| version = "0.2.1" | ||||
| source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#3d5d8c54b6f2b7bbb0a31458c00139359ca3006e" | ||||
| dependencies = [ | ||||
|  "indexmap", | ||||
|  "prettyplease", | ||||
|  |  | |||
|  | @ -14,4 +14,4 @@ categories = [] | |||
| rust-version = "1.79" | ||||
| 
 | ||||
| [workspace.dependencies] | ||||
| fayalite = { git = "https://git.libre-chip.org/libre-chip/fayalite.git", version = "0.2.0", branch = "master" } | ||||
| fayalite = { git = "https://git.libre-chip.org/libre-chip/fayalite.git", version = "0.2.1", branch = "master" } | ||||
|  |  | |||
|  | @ -5,12 +5,14 @@ use crate::{ | |||
|     unit::UnitKind, | ||||
| }; | ||||
| use fayalite::prelude::*; | ||||
| use std::num::NonZeroUsize; | ||||
| 
 | ||||
| #[derive(Clone, Eq, PartialEq, Hash, Debug)] | ||||
| #[non_exhaustive] | ||||
| pub struct CpuConfig { | ||||
|     pub unit_kinds: Vec<UnitKind>, | ||||
|     pub out_reg_num_width: usize, | ||||
|     pub fetch_width: NonZeroUsize, | ||||
| } | ||||
| 
 | ||||
| impl CpuConfig { | ||||
|  |  | |||
|  | @ -183,4 +183,5 @@ impl MOpRegNum { | |||
|     pub const CONST_ZERO_REG_NUM: u32 = 0; | ||||
| } | ||||
| 
 | ||||
| #[hdl] | ||||
| pub type MOp = UnitMOp<ConstUsize<{ MOpRegNum::WIDTH }>>; | ||||
|  |  | |||
|  | @ -1,11 +1,128 @@ | |||
| // SPDX-License-Identifier: LGPL-3.0-or-later
 | ||||
| // See Notices.txt for copyright information
 | ||||
| use crate::config::CpuConfig; | ||||
| use fayalite::prelude::*; | ||||
| use crate::{ | ||||
|     config::CpuConfig, | ||||
|     instruction::{MOp, UnitNum}, | ||||
|     unit::{TrapData, UnitTrait}, | ||||
|     util::tree_reduce::{tree_reduce, tree_reduce_with_state}, | ||||
| }; | ||||
| use fayalite::{module::instance_with_loc, prelude::*, util::ready_valid::ReadyValid}; | ||||
| use std::num::NonZeroUsize; | ||||
| 
 | ||||
| pub mod unit_free_regs_tracker; | ||||
| 
 | ||||
| #[hdl_module] | ||||
| pub fn reg_alloc(config: CpuConfig) { | ||||
|     todo!() | ||||
| #[hdl] | ||||
| pub struct FetchedDecodedMOp { | ||||
|     pub uop: MOp, | ||||
|     /// true if pc doesn't have to be related to the previous instruction.
 | ||||
|     /// (enable to stop detecting when the current instruction isn't
 | ||||
|     /// supposed to be run next, e.g. on branch mis-prediction)
 | ||||
|     pub is_unrelated_pc: Bool, | ||||
|     pub pc: UInt<64>, | ||||
| } | ||||
| 
 | ||||
| #[hdl] | ||||
| pub enum FetchDecodeSpecialOp { | ||||
|     Trap(TrapData), | ||||
|     ICacheFlush, | ||||
| } | ||||
| 
 | ||||
| #[hdl] | ||||
| pub struct FetchDecodeInterface<FetchWidth: Size> { | ||||
|     pub decoded_insns: ArrayType<ReadyValid<FetchedDecodedMOp>, FetchWidth>, | ||||
|     #[hdl(flip)] | ||||
|     pub fetch_decode_special_op: ReadyValid<FetchDecodeSpecialOp>, | ||||
| } | ||||
| 
 | ||||
| #[hdl_module] | ||||
| /// combination register allocator, register renaming, unit selection, and retire handling
 | ||||
| pub fn reg_alloc(config: &CpuConfig) { | ||||
|     #[hdl] | ||||
|     let cd: ClockDomain = m.input(); | ||||
|     #[hdl] | ||||
|     let fetch_decode_interface: FetchDecodeInterface<DynSize> = | ||||
|         m.input(FetchDecodeInterface[config.fetch_width.get()]); | ||||
|     // TODO: propagate traps, branch mis-predictions, and special ops
 | ||||
|     connect( | ||||
|         fetch_decode_interface.fetch_decode_special_op.data, | ||||
|         HdlNone(), | ||||
|     ); | ||||
|     // TODO: finish
 | ||||
|     #[hdl] | ||||
|     let available_units = | ||||
|         wire(Array[Array[Bool][config.unit_kinds.len()]][config.fetch_width.get()]); | ||||
|     #[hdl] | ||||
|     let selected_unit_nums = wire(Array[HdlOption[config.unit_num()]][config.fetch_width.get()]); | ||||
|     for fetch_index in 0..config.fetch_width.get() { | ||||
|         connect( | ||||
|             fetch_decode_interface.decoded_insns[fetch_index].ready, | ||||
|             true, | ||||
|         ); | ||||
|         connect( | ||||
|             available_units[fetch_index], | ||||
|             repeat(false, config.unit_kinds.len()), | ||||
|         ); | ||||
|         #[hdl] | ||||
|         if let HdlSome(decoded_insn) = fetch_decode_interface.decoded_insns[fetch_index].data { | ||||
|             connect( | ||||
|                 available_units[fetch_index], | ||||
|                 config.available_units_for_kind(MOp::kind(decoded_insn.uop)), | ||||
|             ); | ||||
|         } | ||||
|         connect( | ||||
|             selected_unit_nums[fetch_index], | ||||
|             tree_reduce_with_state( | ||||
|                 0..config.unit_kinds.len(), | ||||
|                 &mut (), | ||||
|                 |_state, unit_index| { | ||||
|                     #[hdl] | ||||
|                     let selected_unit_leaf = wire(HdlOption[config.unit_num()]); | ||||
|                     connect(selected_unit_leaf, HdlOption[config.unit_num()].HdlNone()); | ||||
|                     #[hdl] | ||||
|                     let unit_num = wire(config.unit_num()); | ||||
|                     connect_any(unit_num.value, unit_index); | ||||
|                     #[hdl] | ||||
|                     if available_units[fetch_index][unit_index] { | ||||
|                         connect(selected_unit_leaf, HdlSome(unit_num)) | ||||
|                     } | ||||
|                     selected_unit_leaf | ||||
|                 }, | ||||
|                 |_state, l, r| { | ||||
|                     #[hdl] | ||||
|                     let selected_unit_node = wire(Expr::ty(l)); | ||||
|                     connect(selected_unit_node, l); | ||||
|                     #[hdl] | ||||
|                     if let HdlNone = l { | ||||
|                         connect(selected_unit_node, r); | ||||
|                     } | ||||
|                     selected_unit_node | ||||
|                 }, | ||||
|             ) | ||||
|             .expect("expected at least one unit"), | ||||
|         ); | ||||
|     } | ||||
|     for (unit_index, &unit_kind) in config.unit_kinds.iter().enumerate() { | ||||
|         let dyn_unit = unit_kind.unit(config); | ||||
|         let unit = instance_with_loc( | ||||
|             &format!("unit_{unit_index}"), | ||||
|             dyn_unit.make_module(), | ||||
|             SourceLocation::caller(), | ||||
|         ); | ||||
|         connect(dyn_unit.cd(unit), cd); | ||||
|         // TODO: handle assigning multiple instructions to a unit at a time
 | ||||
|         let assign_to_unit_at_once = NonZeroUsize::new(1).unwrap(); | ||||
|         // TODO: handle retiring multiple instructions from a unit at a time
 | ||||
|         let retire_from_unit_at_once = NonZeroUsize::new(1).unwrap(); | ||||
|         let unit_free_regs_tracker = instance_with_loc( | ||||
|             &format!("unit_{unit_index}_free_regs_tracker"), | ||||
|             unit_free_regs_tracker::unit_free_regs_tracker( | ||||
|                 retire_from_unit_at_once, | ||||
|                 assign_to_unit_at_once, | ||||
|                 config.out_reg_num_width, | ||||
|             ), | ||||
|             SourceLocation::caller(), | ||||
|         ); | ||||
|         connect(unit_free_regs_tracker.cd, cd); | ||||
|         // TODO: finish
 | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ macro_rules! all_units { | |||
|         $(#[$enum_meta:meta])* | ||||
|         $vis:vis enum $UnitMOpEnum:ident<$RegWidth:ident: Size> { | ||||
|             $( | ||||
|                 #[create_dyn_unit_fn = $create_dyn_unit_fn:expr] | ||||
|                 $(#[$variant_meta:meta])* | ||||
|                 $Unit:ident($Op:ty), | ||||
|             )* | ||||
|  | @ -35,6 +36,14 @@ macro_rules! all_units { | |||
|             )* | ||||
|         } | ||||
| 
 | ||||
|         impl $UnitKind { | ||||
|             pub fn unit(self, config: &CpuConfig) -> DynUnit { | ||||
|                 match self { | ||||
|                     $($UnitKind::$Unit => $create_dyn_unit_fn(config),)* | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         impl ToExpr for $UnitKind { | ||||
|             type Type = $HdlUnitKind; | ||||
| 
 | ||||
|  | @ -98,8 +107,11 @@ all_units! { | |||
|     #[unit_kind = UnitKind] | ||||
|     #[hdl] | ||||
|     pub enum UnitMOp<RegWidth: Size> { | ||||
|         #[create_dyn_unit_fn = |config| todo!()] | ||||
|         AluBranch(AluBranchMOp<RegWidth>), | ||||
|         #[create_dyn_unit_fn = |config| todo!()] | ||||
|         L2RegisterFile(L2RegisterFileMOp<RegWidth>), | ||||
|         #[create_dyn_unit_fn = |config| todo!()] | ||||
|         LoadStore(LoadStoreMOp<RegWidth>), | ||||
|     } | ||||
| } | ||||
|  | @ -156,6 +168,7 @@ pub trait UnitTrait: | |||
|         &self, | ||||
|         this: Expr<Self::Type>, | ||||
|     ) -> Expr<ReadyValid<UnitOutput<DynSize, DynSize, Self::ExtraOut>>>; | ||||
|     fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain>; | ||||
| 
 | ||||
|     fn to_dyn(&self) -> DynUnit; | ||||
| } | ||||
|  | @ -217,6 +230,10 @@ impl UnitTrait for DynUnit { | |||
|         self.unit.output(this) | ||||
|     } | ||||
| 
 | ||||
|     fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain> { | ||||
|         self.unit.cd(this) | ||||
|     } | ||||
| 
 | ||||
|     fn to_dyn(&self) -> DynUnit { | ||||
|         *self | ||||
|     } | ||||
|  | @ -264,6 +281,10 @@ impl<T: UnitTrait + Clone + std::hash::Hash + Eq> UnitTrait for DynUnitWrapper<T | |||
|         Expr::from_bundle(Expr::as_bundle(self.0.output(Expr::from_bundle(this)))) | ||||
|     } | ||||
| 
 | ||||
|     fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain> { | ||||
|         self.0.cd(Expr::from_bundle(this)) | ||||
|     } | ||||
| 
 | ||||
|     fn to_dyn(&self) -> DynUnit { | ||||
|         let unit = self.intern(); | ||||
|         DynUnit { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue