From 49d13648ec00074cf9d73eb8c4e5bac7c3b5df8a Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Sun, 26 Oct 2025 03:43:18 -0700 Subject: [PATCH 1/6] update Fayalite to 0be9f9ce23 to get support for PhantomConst accessor type aliases --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f417853..53f08f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -303,7 +303,7 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fayalite" version = "0.3.0" -source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#edcc5927a5f9ebca6df5720bb1f5931e50095a57" +source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#0be9f9ce2329fd455a40f87e70c51a3ab672cc40" dependencies = [ "base64", "bitvec", @@ -330,7 +330,7 @@ dependencies = [ [[package]] name = "fayalite-proc-macros" version = "0.3.0" -source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#edcc5927a5f9ebca6df5720bb1f5931e50095a57" +source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#0be9f9ce2329fd455a40f87e70c51a3ab672cc40" dependencies = [ "fayalite-proc-macros-impl", ] @@ -338,7 +338,7 @@ dependencies = [ [[package]] name = "fayalite-proc-macros-impl" version = "0.3.0" -source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#edcc5927a5f9ebca6df5720bb1f5931e50095a57" +source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#0be9f9ce2329fd455a40f87e70c51a3ab672cc40" dependencies = [ "base16ct", "num-bigint", @@ -353,7 +353,7 @@ dependencies = [ [[package]] name = "fayalite-visit-gen" version = "0.3.0" -source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#edcc5927a5f9ebca6df5720bb1f5931e50095a57" +source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#0be9f9ce2329fd455a40f87e70c51a3ab672cc40" dependencies = [ "indexmap", "prettyplease", From 6b703b012a83484aef2542458c534ae54b0199e1 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 27 Oct 2025 20:25:40 -0700 Subject: [PATCH 2/6] add Serialize/Deserialize impls for CpuConfig --- Cargo.lock | 1 + Cargo.toml | 1 + crates/cpu/Cargo.toml | 1 + crates/cpu/src/config.rs | 5 +++-- crates/cpu/src/unit.rs | 3 ++- 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53f08f2..0e630d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -210,6 +210,7 @@ name = "cpu" version = "0.1.0" dependencies = [ "fayalite", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 57ca631..a3e74f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ rust-version = "1.89.0" [workspace.dependencies] fayalite = { git = "https://git.libre-chip.org/libre-chip/fayalite.git", version = "0.3.0", branch = "master" } +serde = { version = "1.0.202", features = ["derive"] } [profile.dev] opt-level = 1 diff --git a/crates/cpu/Cargo.toml b/crates/cpu/Cargo.toml index 16ec0b9..4dd85d8 100644 --- a/crates/cpu/Cargo.toml +++ b/crates/cpu/Cargo.toml @@ -16,3 +16,4 @@ version.workspace = true [dependencies] fayalite.workspace = true +serde.workspace = true diff --git a/crates/cpu/src/config.rs b/crates/cpu/src/config.rs index 4e66010..9a66c68 100644 --- a/crates/cpu/src/config.rs +++ b/crates/cpu/src/config.rs @@ -8,9 +8,10 @@ use crate::{ }, }; use fayalite::prelude::*; +use serde::{Deserialize, Serialize}; use std::num::NonZeroUsize; -#[derive(Clone, Eq, PartialEq, Hash, Debug)] +#[derive(Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] #[non_exhaustive] pub struct UnitConfig { pub kind: UnitKind, @@ -27,7 +28,7 @@ impl UnitConfig { } } -#[derive(Clone, Eq, PartialEq, Hash, Debug)] +#[derive(Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] #[non_exhaustive] pub struct CpuConfig { pub units: Vec, diff --git a/crates/cpu/src/unit.rs b/crates/cpu/src/unit.rs index d6cd1d6..b71f79a 100644 --- a/crates/cpu/src/unit.rs +++ b/crates/cpu/src/unit.rs @@ -15,6 +15,7 @@ use fayalite::{ intern::{Intern, Interned}, prelude::*, }; +use serde::{Deserialize, Serialize}; pub mod alu_branch; pub mod unit_base; @@ -36,7 +37,7 @@ macro_rules! all_units { } ) => { $(#[$enum_meta])* - #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)] $vis enum $UnitKind { $( $(#[$variant_meta])* From c423dc4f15941ac77ded2c307e8568b9df9f2660 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 27 Oct 2025 22:41:33 -0700 Subject: [PATCH 3/6] WIP adding next_pc --- crates/cpu/src/config.rs | 25 ++++++++ crates/cpu/src/lib.rs | 1 + crates/cpu/src/next_pc.rs | 117 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 crates/cpu/src/next_pc.rs diff --git a/crates/cpu/src/config.rs b/crates/cpu/src/config.rs index 9a66c68..ed3b814 100644 --- a/crates/cpu/src/config.rs +++ b/crates/cpu/src/config.rs @@ -34,6 +34,8 @@ pub struct CpuConfig { pub units: Vec, pub out_reg_num_width: usize, pub fetch_width: NonZeroUsize, + pub max_branches_per_fetch: NonZeroUsize, + pub fetch_width_in_bytes: NonZeroUsize, /// default value for [`UnitConfig::max_in_flight`] pub default_unit_max_in_flight: NonZeroUsize, pub rob_size: NonZeroUsize, @@ -47,6 +49,18 @@ impl CpuConfig { }; v }; + pub const DEFAULT_MAX_BRANCHES_PER_FETCH: NonZeroUsize = { + let Some(v) = NonZeroUsize::new(1) else { + unreachable!(); + }; + v + }; + pub const DEFAULT_FETCH_WIDTH_IN_BYTES: NonZeroUsize = { + let Some(v) = NonZeroUsize::new(4) else { + unreachable!(); + }; + v + }; pub const DEFAULT_UNIT_MAX_IN_FLIGHT: NonZeroUsize = { let Some(v) = NonZeroUsize::new(8) else { unreachable!(); @@ -58,6 +72,8 @@ impl CpuConfig { units, out_reg_num_width: Self::DEFAULT_OUT_REG_NUM_WIDTH, fetch_width: Self::DEFAULT_FETCH_WIDTH, + max_branches_per_fetch: Self::DEFAULT_MAX_BRANCHES_PER_FETCH, + fetch_width_in_bytes: Self::DEFAULT_FETCH_WIDTH_IN_BYTES, default_unit_max_in_flight: Self::DEFAULT_UNIT_MAX_IN_FLIGHT, rob_size, } @@ -118,3 +134,12 @@ impl CpuConfig { [self.non_const_unit_nums().len()] } } + +#[hdl(get(|c| c.fetch_width.get()))] +pub type CpuConfigFetchWidth> = DynSize; + +#[hdl(get(|c| c.max_branches_per_fetch.get()))] +pub type CpuConfigMaxBranchesPerFetch> = DynSize; + +#[hdl(get(|c| c.fetch_width_in_bytes.get()))] +pub type CpuConfigFetchWidthInBytes> = DynSize; diff --git a/crates/cpu/src/lib.rs b/crates/cpu/src/lib.rs index bae3720..a00b668 100644 --- a/crates/cpu/src/lib.rs +++ b/crates/cpu/src/lib.rs @@ -2,6 +2,7 @@ // See Notices.txt for copyright information pub mod config; pub mod instruction; +pub mod next_pc; pub mod reg_alloc; pub mod register; pub mod unit; diff --git a/crates/cpu/src/next_pc.rs b/crates/cpu/src/next_pc.rs new file mode 100644 index 0000000..db0c910 --- /dev/null +++ b/crates/cpu/src/next_pc.rs @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// See Notices.txt for copyright information + +//! [Next-Instruction Logic](https://git.libre-chip.org/libre-chip/grant-tracking/issues/10) +//! +//! The basic idea here is that there's a `next_pc` stage that sends predicted fetch PCs to the `fetch` stage, +//! the `fetch` stage's outputs eventually end up in the `decode` stage, +//! after the `decode` stage there's a `post_decode` stage (that may run in the same clock cycle as `decode`) +//! that checks that the fetched instructions' kinds match the predicted instruction kinds and that feeds +//! information back to the `fetch` stage to cancel fetches that need to be predicted differently. + +use crate::{config::CpuConfig, util::array_vec::ArrayVec}; +use fayalite::prelude::*; +use fayalite::util::ready_valid::ReadyValid; + +#[hdl] +pub enum PredictedCond { + Taken, + Fallthrough, +} + +#[hdl] +pub struct PredictedFallthrough {} + +#[hdl] +pub enum BranchPredictionKind { + Branch(HdlOption), + IndirectBranch(HdlOption), + Call(HdlOption), + IndirectCall(HdlOption), + Ret(HdlOption), +} + +#[hdl(get(|c| c.max_branches_per_fetch.get() - 1))] +pub type NextPcPredictionMaxBranchesBeforeLast> = DynSize; + +#[hdl(no_static)] +pub struct NextPcPrediction> { + pub fetch_pc: UInt<64>, + pub async_interrupt: Bool, + pub branches_before_last: ArrayVec< + BranchPredictionKind, + NextPcPredictionMaxBranchesBeforeLast, + >, + pub last_branch: HdlOption>, + pub last_branch_target_pc: UInt<64>, +} + +#[hdl] +pub struct NextPcToFetchInterfaceInner { + pub next_fetch_pc: UInt<64>, + pub in_progress_fetches_to_cancel: UInt<8>, +} + +#[hdl(no_static)] +pub struct NextPcToFetchInterface> { + pub inner: ReadyValid, + pub config: C, +} + +#[hdl(no_static)] +/// handles updating speculative branch predictor state (e.g. branch histories) when instructions retire, +/// as well as updating state when a branch instruction is mis-speculated. +pub struct NextPcToRetireInterface> { + // TODO: add needed fields + pub config: C, +} + +#[hdl(no_static)] +pub struct NextPcToPostDecodeInterface> { + // TODO: add needed fields + pub config: C, +} + +#[hdl(no_static)] +pub struct FetchToPostDecodeInterface> { + // TODO: add needed fields + pub config: C, +} + +#[hdl(no_static)] +pub struct PostDecodeOutputInterface> { + // TODO: add needed fields + pub config: C, +} + +#[hdl_module] +pub fn next_pc(config: PhantomConst) { + #[hdl] + let cd: ClockDomain = m.input(); + #[hdl] + let to_fetch_interface: NextPcToFetchInterface> = + m.output(NextPcToFetchInterface[config]); + #[hdl] + let to_post_decode_interface: NextPcToPostDecodeInterface> = + m.output(NextPcToPostDecodeInterface[config]); + #[hdl] + let to_retire_interface: NextPcToRetireInterface> = + m.output(NextPcToRetireInterface[config]); + todo!() +} + +#[hdl_module] +pub fn post_decode(config: PhantomConst) { + #[hdl] + let cd: ClockDomain = m.input(); + #[hdl] + let from_next_pc_interface: NextPcToPostDecodeInterface> = + m.input(NextPcToPostDecodeInterface[config]); + #[hdl] + let from_fetch_interface: FetchToPostDecodeInterface> = + m.output(FetchToPostDecodeInterface[config]); + #[hdl] + let output: PostDecodeOutputInterface> = + m.output(PostDecodeOutputInterface[config]); + todo!() +} From 2c5b1b7f4498fdd3c6797498fe656033de3e4a9f Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Sun, 26 Oct 2025 03:43:18 -0700 Subject: [PATCH 4/6] update Fayalite to c11a1743f9 to get support for PhantomConst accessor type aliases and fork_join --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f417853..3ffff3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -303,7 +303,7 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fayalite" version = "0.3.0" -source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#edcc5927a5f9ebca6df5720bb1f5931e50095a57" +source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#c11a1743f97b5219725d123d876effe717b633f2" dependencies = [ "base64", "bitvec", @@ -330,7 +330,7 @@ dependencies = [ [[package]] name = "fayalite-proc-macros" version = "0.3.0" -source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#edcc5927a5f9ebca6df5720bb1f5931e50095a57" +source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#c11a1743f97b5219725d123d876effe717b633f2" dependencies = [ "fayalite-proc-macros-impl", ] @@ -338,7 +338,7 @@ dependencies = [ [[package]] name = "fayalite-proc-macros-impl" version = "0.3.0" -source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#edcc5927a5f9ebca6df5720bb1f5931e50095a57" +source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#c11a1743f97b5219725d123d876effe717b633f2" dependencies = [ "base16ct", "num-bigint", @@ -353,7 +353,7 @@ dependencies = [ [[package]] name = "fayalite-visit-gen" version = "0.3.0" -source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#edcc5927a5f9ebca6df5720bb1f5931e50095a57" +source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#c11a1743f97b5219725d123d876effe717b633f2" dependencies = [ "indexmap", "prettyplease", From f728964cb3836c5488422d97f61178c3b7a12eeb Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 27 Oct 2025 20:25:40 -0700 Subject: [PATCH 5/6] add Serialize/Deserialize impls for CpuConfig --- Cargo.lock | 1 + Cargo.toml | 1 + crates/cpu/Cargo.toml | 1 + crates/cpu/src/config.rs | 5 +++-- crates/cpu/src/unit.rs | 3 ++- 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3ffff3a..ba8845a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -210,6 +210,7 @@ name = "cpu" version = "0.1.0" dependencies = [ "fayalite", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 57ca631..a3e74f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ rust-version = "1.89.0" [workspace.dependencies] fayalite = { git = "https://git.libre-chip.org/libre-chip/fayalite.git", version = "0.3.0", branch = "master" } +serde = { version = "1.0.202", features = ["derive"] } [profile.dev] opt-level = 1 diff --git a/crates/cpu/Cargo.toml b/crates/cpu/Cargo.toml index 16ec0b9..4dd85d8 100644 --- a/crates/cpu/Cargo.toml +++ b/crates/cpu/Cargo.toml @@ -16,3 +16,4 @@ version.workspace = true [dependencies] fayalite.workspace = true +serde.workspace = true diff --git a/crates/cpu/src/config.rs b/crates/cpu/src/config.rs index 4e66010..9a66c68 100644 --- a/crates/cpu/src/config.rs +++ b/crates/cpu/src/config.rs @@ -8,9 +8,10 @@ use crate::{ }, }; use fayalite::prelude::*; +use serde::{Deserialize, Serialize}; use std::num::NonZeroUsize; -#[derive(Clone, Eq, PartialEq, Hash, Debug)] +#[derive(Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] #[non_exhaustive] pub struct UnitConfig { pub kind: UnitKind, @@ -27,7 +28,7 @@ impl UnitConfig { } } -#[derive(Clone, Eq, PartialEq, Hash, Debug)] +#[derive(Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] #[non_exhaustive] pub struct CpuConfig { pub units: Vec, diff --git a/crates/cpu/src/unit.rs b/crates/cpu/src/unit.rs index d6cd1d6..b71f79a 100644 --- a/crates/cpu/src/unit.rs +++ b/crates/cpu/src/unit.rs @@ -15,6 +15,7 @@ use fayalite::{ intern::{Intern, Interned}, prelude::*, }; +use serde::{Deserialize, Serialize}; pub mod alu_branch; pub mod unit_base; @@ -36,7 +37,7 @@ macro_rules! all_units { } ) => { $(#[$enum_meta])* - #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] + #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)] $vis enum $UnitKind { $( $(#[$variant_meta])* From 10db8b3f90de4c875331a794736f8fbf83492c52 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 27 Oct 2025 22:41:33 -0700 Subject: [PATCH 6/6] WIP adding next_pc --- crates/cpu/src/config.rs | 25 ++++++++ crates/cpu/src/lib.rs | 1 + crates/cpu/src/next_pc.rs | 117 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 crates/cpu/src/next_pc.rs diff --git a/crates/cpu/src/config.rs b/crates/cpu/src/config.rs index 9a66c68..ed3b814 100644 --- a/crates/cpu/src/config.rs +++ b/crates/cpu/src/config.rs @@ -34,6 +34,8 @@ pub struct CpuConfig { pub units: Vec, pub out_reg_num_width: usize, pub fetch_width: NonZeroUsize, + pub max_branches_per_fetch: NonZeroUsize, + pub fetch_width_in_bytes: NonZeroUsize, /// default value for [`UnitConfig::max_in_flight`] pub default_unit_max_in_flight: NonZeroUsize, pub rob_size: NonZeroUsize, @@ -47,6 +49,18 @@ impl CpuConfig { }; v }; + pub const DEFAULT_MAX_BRANCHES_PER_FETCH: NonZeroUsize = { + let Some(v) = NonZeroUsize::new(1) else { + unreachable!(); + }; + v + }; + pub const DEFAULT_FETCH_WIDTH_IN_BYTES: NonZeroUsize = { + let Some(v) = NonZeroUsize::new(4) else { + unreachable!(); + }; + v + }; pub const DEFAULT_UNIT_MAX_IN_FLIGHT: NonZeroUsize = { let Some(v) = NonZeroUsize::new(8) else { unreachable!(); @@ -58,6 +72,8 @@ impl CpuConfig { units, out_reg_num_width: Self::DEFAULT_OUT_REG_NUM_WIDTH, fetch_width: Self::DEFAULT_FETCH_WIDTH, + max_branches_per_fetch: Self::DEFAULT_MAX_BRANCHES_PER_FETCH, + fetch_width_in_bytes: Self::DEFAULT_FETCH_WIDTH_IN_BYTES, default_unit_max_in_flight: Self::DEFAULT_UNIT_MAX_IN_FLIGHT, rob_size, } @@ -118,3 +134,12 @@ impl CpuConfig { [self.non_const_unit_nums().len()] } } + +#[hdl(get(|c| c.fetch_width.get()))] +pub type CpuConfigFetchWidth> = DynSize; + +#[hdl(get(|c| c.max_branches_per_fetch.get()))] +pub type CpuConfigMaxBranchesPerFetch> = DynSize; + +#[hdl(get(|c| c.fetch_width_in_bytes.get()))] +pub type CpuConfigFetchWidthInBytes> = DynSize; diff --git a/crates/cpu/src/lib.rs b/crates/cpu/src/lib.rs index bae3720..a00b668 100644 --- a/crates/cpu/src/lib.rs +++ b/crates/cpu/src/lib.rs @@ -2,6 +2,7 @@ // See Notices.txt for copyright information pub mod config; pub mod instruction; +pub mod next_pc; pub mod reg_alloc; pub mod register; pub mod unit; diff --git a/crates/cpu/src/next_pc.rs b/crates/cpu/src/next_pc.rs new file mode 100644 index 0000000..db0c910 --- /dev/null +++ b/crates/cpu/src/next_pc.rs @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// See Notices.txt for copyright information + +//! [Next-Instruction Logic](https://git.libre-chip.org/libre-chip/grant-tracking/issues/10) +//! +//! The basic idea here is that there's a `next_pc` stage that sends predicted fetch PCs to the `fetch` stage, +//! the `fetch` stage's outputs eventually end up in the `decode` stage, +//! after the `decode` stage there's a `post_decode` stage (that may run in the same clock cycle as `decode`) +//! that checks that the fetched instructions' kinds match the predicted instruction kinds and that feeds +//! information back to the `fetch` stage to cancel fetches that need to be predicted differently. + +use crate::{config::CpuConfig, util::array_vec::ArrayVec}; +use fayalite::prelude::*; +use fayalite::util::ready_valid::ReadyValid; + +#[hdl] +pub enum PredictedCond { + Taken, + Fallthrough, +} + +#[hdl] +pub struct PredictedFallthrough {} + +#[hdl] +pub enum BranchPredictionKind { + Branch(HdlOption), + IndirectBranch(HdlOption), + Call(HdlOption), + IndirectCall(HdlOption), + Ret(HdlOption), +} + +#[hdl(get(|c| c.max_branches_per_fetch.get() - 1))] +pub type NextPcPredictionMaxBranchesBeforeLast> = DynSize; + +#[hdl(no_static)] +pub struct NextPcPrediction> { + pub fetch_pc: UInt<64>, + pub async_interrupt: Bool, + pub branches_before_last: ArrayVec< + BranchPredictionKind, + NextPcPredictionMaxBranchesBeforeLast, + >, + pub last_branch: HdlOption>, + pub last_branch_target_pc: UInt<64>, +} + +#[hdl] +pub struct NextPcToFetchInterfaceInner { + pub next_fetch_pc: UInt<64>, + pub in_progress_fetches_to_cancel: UInt<8>, +} + +#[hdl(no_static)] +pub struct NextPcToFetchInterface> { + pub inner: ReadyValid, + pub config: C, +} + +#[hdl(no_static)] +/// handles updating speculative branch predictor state (e.g. branch histories) when instructions retire, +/// as well as updating state when a branch instruction is mis-speculated. +pub struct NextPcToRetireInterface> { + // TODO: add needed fields + pub config: C, +} + +#[hdl(no_static)] +pub struct NextPcToPostDecodeInterface> { + // TODO: add needed fields + pub config: C, +} + +#[hdl(no_static)] +pub struct FetchToPostDecodeInterface> { + // TODO: add needed fields + pub config: C, +} + +#[hdl(no_static)] +pub struct PostDecodeOutputInterface> { + // TODO: add needed fields + pub config: C, +} + +#[hdl_module] +pub fn next_pc(config: PhantomConst) { + #[hdl] + let cd: ClockDomain = m.input(); + #[hdl] + let to_fetch_interface: NextPcToFetchInterface> = + m.output(NextPcToFetchInterface[config]); + #[hdl] + let to_post_decode_interface: NextPcToPostDecodeInterface> = + m.output(NextPcToPostDecodeInterface[config]); + #[hdl] + let to_retire_interface: NextPcToRetireInterface> = + m.output(NextPcToRetireInterface[config]); + todo!() +} + +#[hdl_module] +pub fn post_decode(config: PhantomConst) { + #[hdl] + let cd: ClockDomain = m.input(); + #[hdl] + let from_next_pc_interface: NextPcToPostDecodeInterface> = + m.input(NextPcToPostDecodeInterface[config]); + #[hdl] + let from_fetch_interface: FetchToPostDecodeInterface> = + m.output(FetchToPostDecodeInterface[config]); + #[hdl] + let output: PostDecodeOutputInterface> = + m.output(PostDecodeOutputInterface[config]); + todo!() +}