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]]
|
[[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",
|
||||||
|
|
|
@ -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>,
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
pub mod instruction;
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
pub mod instruction;
|
||||||
|
|
Loading…
Reference in a new issue