diff --git a/Cargo.lock b/Cargo.lock index 1247f56..3a73473 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -279,7 +279,7 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fayalite" 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 = [ "bitvec", "blake3", @@ -300,7 +300,7 @@ dependencies = [ [[package]] name = "fayalite-proc-macros" 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 = [ "fayalite-proc-macros-impl", ] @@ -308,7 +308,7 @@ dependencies = [ [[package]] name = "fayalite-proc-macros-impl" 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 = [ "base16ct", "num-bigint", @@ -323,7 +323,7 @@ dependencies = [ [[package]] name = "fayalite-visit-gen" 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 = [ "indexmap", "prettyplease", diff --git a/crates/cpu/src/config.rs b/crates/cpu/src/config.rs index 03d93df..61907f4 100644 --- a/crates/cpu/src/config.rs +++ b/crates/cpu/src/config.rs @@ -11,4 +11,4 @@ impl CpuConfig { pub fn unit_num(&self) -> UnitNum { UnitNum[UInt::range(0..self.units.len()).width()] } -} \ No newline at end of file +} diff --git a/crates/cpu/src/instruction.rs b/crates/cpu/src/instruction.rs index ff4ebcb..8d3144b 100644 --- a/crates/cpu/src/instruction.rs +++ b/crates/cpu/src/instruction.rs @@ -1,5 +1,6 @@ -use fayalite::prelude::*; use crate::config::CpuConfig; +use fayalite::prelude::*; +use std::marker::PhantomData; pub mod power_isa; @@ -9,7 +10,7 @@ macro_rules! all_units { #[unit_kind = $UnitKind:ident] #[hdl] $(#[$enum_meta:meta])* - $vis:vis enum $UnitMOpEnum:ident { + $vis:vis enum $UnitMOpEnum:ident<$RegWidth:ident: Size> { $( $(#[$variant_meta:meta])* $Unit:ident($Op:ty), @@ -46,21 +47,21 @@ macro_rules! all_units { #[hdl] $(#[$enum_meta])* - $vis enum $UnitMOpEnum { + $vis enum $UnitMOpEnum<$RegWidth: Size> { $( $(#[$variant_meta])* $Unit($Op), )* } - impl $UnitMOpEnum { + impl<$RegWidth: Size> $UnitMOpEnum<$RegWidth> { #[hdl] $vis fn kind(expr: impl ToExpr) -> Expr<$HdlUnitKind> { #[hdl] let unit_kind = wire(); #[hdl] match expr { - $($UnitMOpEnum::$Unit(_) => connect(unit_kind, $HdlUnitKind.$Unit()),)* + $($UnitMOpEnum::<$RegWidth>::$Unit(_) => connect(unit_kind, $HdlUnitKind.$Unit()),)* } unit_kind } @@ -87,32 +88,152 @@ all_units! { #[hdl_unit_kind = HdlUnitKind] #[unit_kind = UnitKind] #[hdl] - pub enum UnitMOp { - AluBranch(AluBranchMOp), - L2RegisterFile(L2RegisterFileMOp), - LoadStore(LoadStoreMOp), + pub enum UnitMOp { + AluBranch(AluBranchMOp), + L2RegisterFile(L2RegisterFileMOp), + LoadStore(LoadStoreMOp), } } #[hdl] -pub enum AluBranchMOp { - Add64, - Sub64, - And64, - Or64, - Xor64, +pub enum OutputIntegerMode { + Full64, + DupLow32, + ZeroExt32, + SignExt32, + 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 { + pub prefix_pad: UIntType, + pub dest: UIntType, + pub src: Array, { COMMON_MOP_SRC_REG_COUNT }>, + pub other: UInt<{ COMMON_MOP_OTHER_WIDTH }>, + pub _phantom: PhantomData, +} + +impl + CommonMOp +{ + 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) -> Expr { + 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, imm: impl ToExpr) { + 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] -pub enum L2RegisterFileMOp { - Read, - Write, +pub struct AluCommonMOp { + pub common: CommonMOp, RegWidth, SrcCount>, + pub output_integer_mode: OutputIntegerMode, } #[hdl] -pub enum LoadStoreMOp { - Load, - Store, +pub struct AddSubMOp { + pub alu_common: AluCommonMOp, + pub invert_src0: Bool, + pub invert_carry_in: Bool, + pub invert_carry_out: Bool, + pub add_pc: Bool, +} + +#[hdl] +pub struct LogicalMOp { + pub alu_common: AluCommonMOp>, + pub lut: UInt<4>, +} + +#[hdl] +pub struct BranchMOp { + pub alu_common: AluCommonMOp>, + pub lut: UInt<4>, +} + +#[hdl] +pub enum AluBranchMOp { + AddSub(AddSubMOp>), + AddSubI(AddSubMOp>), + Logical(LogicalMOp), +} + +#[hdl] +pub struct ReadL2RegMOp { + pub common: CommonMOp, RegWidth, ConstUsize<0>>, +} + +#[hdl] +pub struct WriteL2RegMOp { + pub common: CommonMOp, RegWidth, ConstUsize<1>>, +} + +#[hdl] +pub enum L2RegisterFileMOp { + ReadL2Reg(ReadL2RegMOp), + WriteL2Reg(WriteL2RegMOp), +} + +#[hdl] +pub struct LoadStoreCommonMOp { + pub common: CommonMOp, RegWidth, SrcCount>, +} + +#[hdl] +pub struct LoadMOp { + pub load_store_common: LoadStoreCommonMOp>, +} + +#[hdl] +pub struct StoreMOp { + pub load_store_common: LoadStoreCommonMOp>, +} + +#[hdl] +pub enum LoadStoreMOp { + Load(CommonMOp, RegWidth, ConstUsize<0>>), + Store(CommonMOp, RegWidth, ConstUsize<1>>), } #[hdl] @@ -142,14 +263,3 @@ pub struct PRegNum { pub struct MOpRegNum { 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>, -} diff --git a/crates/cpu/src/instruction/power_isa.rs b/crates/cpu/src/instruction/power_isa.rs index 89dc832..a242303 100644 --- a/crates/cpu/src/instruction/power_isa.rs +++ b/crates/cpu/src/instruction/power_isa.rs @@ -19,4 +19,4 @@ pub struct PowerIsaCrFieldNum { pub struct PowerIsaCrBitNum { pub cr_field: PowerIsaCrFieldNum, pub bit_in_field: UInt<2>, -} \ No newline at end of file +} diff --git a/crates/cpu/src/lib.rs b/crates/cpu/src/lib.rs index 1ff8b46..eab7c3e 100644 --- a/crates/cpu/src/lib.rs +++ b/crates/cpu/src/lib.rs @@ -1,2 +1,2 @@ +pub mod config; pub mod instruction; -pub mod config; \ No newline at end of file