WIP: adding micro ops

This commit is contained in:
Jacob Lifshay 2024-10-10 22:57:11 -07:00
parent 0f4f067996
commit 4c3dd128a3
Signed by: programmerjake
SSH key fingerprint: SHA256:B1iRVvUJkvd7upMIiMqn6OyxvD2SgJkAH3ZnUOj6z+c
5 changed files with 149 additions and 39 deletions

8
Cargo.lock generated
View file

@ -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",

View file

@ -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<Type = Self>) -> 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<RegWidth: Size> {
AluBranch(AluBranchMOp<RegWidth>),
L2RegisterFile(L2RegisterFileMOp<RegWidth>),
LoadStore(LoadStoreMOp<RegWidth>),
}
}
#[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<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]
pub enum L2RegisterFileMOp {
Read,
Write,
pub struct AluCommonMOp<RegWidth: Size, SrcCount: KnownSize> {
pub common: CommonMOp<ConstUsize<0>, RegWidth, SrcCount>,
pub output_integer_mode: OutputIntegerMode,
}
#[hdl]
pub enum LoadStoreMOp {
Load,
Store,
pub struct AddSubMOp<RegWidth: Size, SrcCount: KnownSize> {
pub alu_common: AluCommonMOp<RegWidth, SrcCount>,
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]
@ -142,14 +263,3 @@ pub struct PRegNum<UnitNumWidth: Size, OutRegNumWidth: Size> {
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>,
}

View file

@ -1,2 +1,2 @@
pub mod instruction;
pub mod config;
pub mod instruction;