WIP: adding micro ops
This commit is contained in:
parent
0f4f067996
commit
4c3dd128a3
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
pub mod instruction;
|
||||
pub mod config;
|
||||
pub mod instruction;
|
||||
|
|
Loading…
Reference in a new issue