Skip to main content

Pipeline

Struct Pipeline 

Source
pub struct Pipeline {
    pub cop2_latch: u64,
    pub ic_rf: Latch,
    pub rf_ex: Latch,
    pub ex_dc: Latch,
    pub dc_wb: Latch,
    pub retired: u64,
    pub cop1: Cop1Control,
    pub fpr: Fpr,
    pub tlb: Tlb,
    pub icache: Icache,
    pub dcache: Dcache,
    pub cop0: Cop0,
    /* private fields */
}
Expand description

The four inter-stage latches plus the pipeline control state.

Fields§

§cop2_latch: u64

The whole of COP2: one 64-bit latch.

COP2 is not populated on the VR4300, and what remains is a single value that every MTC2/DMTC2 writes and every MFC2/DMFC2 reads, with the register index ignored. See the EX stage and ledger C-20.

§ic_rf: Latch

ICRF.

§rf_ex: Latch

RFEX.

§ex_dc: Latch

EXDC.

§dc_wb: Latch

DCWB.

§retired: u64

Instructions retired at WB — a work tally, not a time position.

§cop1: Cop1Control

COP1 control registers (T-12-006).

§fpr: Fpr

The floating-point register file (T-13-001).

§tlb: Tlb

The joint TLB and its instruction micro-TLB (T-12-004).

§icache: Icache

The 16 KiB primary instruction cache (T-11-003).

§dcache: Dcache

The 8 KiB primary write-back data cache (T-11-003).

§cop0: Cop0

The COP0 register file (T-12-001).

Public because exception dispatch, the TLB and the interrupt path all read it, and they land in separate tickets.

Implementations§

Source§

impl Pipeline

Source

pub const fn new() -> Self

A fresh, empty pipeline.

Source

pub const fn stalled_by(&self) -> Option<Interlock>

The interlock currently stalling the pipeline, if any.

Source

pub const fn prev_cycle_was_run(&self) -> bool

Was the previous PCycle a run cycle? Gates interrupt acceptance.

Source

pub const fn ll_bit(&self) -> bool

The link bit, as SC would test it.

Exposed for the COP0 / ERET work in Sprint 2, which must clear it.

Source

pub const fn ll_addr(&self) -> u64

LLAddr (COP0 register 17): PA(31:4) of the most recent LL.

Reads straight out of the COP0 file. LL writes it there and nowhere else — there is deliberately no second copy, because two stores of one architectural value drift, and MFC0 $rt, $17 would then disagree with the CPU’s own idea of the link address.

Source

pub const fn stall_for(&mut self, cycles: u32, cause: Interlock)

Request a stall of cycles PCycles.

A zero-cycle request is not a stall and is ignored. Recording it would still consume a cycle in Pipeline::advance and mark it as not-a-run cycle, which silently inserts a bubble and suppresses interrupt acceptance on the following cycle (UM §4.7.1) — a one-cycle timing error with no visible cause.

Source

pub const fn signal_nmi(&mut self)

Assert the NMI line.

Latched, then taken at the next instruction boundary. Nothing in the core calls this yet: on hardware the source is the console’s reset button, which reaches the CPU as PRENMI followed by NMI, and the frontend owns that button (Phase 6). It exists now because the exception itself is Phase 1 work and belongs with the rest of the exception model — the wire from the button is a separate, later concern.

Source

pub const fn abort_from(&mut self, at: Stage, exc: Exception)

Stamp an abort into at and every latch upstream of it — the kill-younger-instructions step. Instructions older than at have already passed and are unaffected.

§Ordering contract

A stage must call this BEFORE it moves its latch. The instruction executing in stage S this cycle sits in S’s input latch until the move, so stamping first is what makes the abort travel with the instruction that caused it. Calling it after the move stamps the abort onto the younger instruction instead, and the causing one escapes — a misalignment that no single-cycle assertion catches. an_abort_survives_the_cascade advances the pipeline to verify it, rather than checking latch state in place.

The abort also raises an internal pending-flush flag, so the instruction fetched later in the same cycle is a bubble rather than a live wrong-path fetch.

Source

pub const fn abort_with(&mut self, at: Stage, exc: Exception, bad_vaddr: u64)

Pipeline::abort_from, additionally recording the offending address for the exceptions that write BadVAddr.

Source

pub fn advance<B: Bus>( &mut self, bus: &mut B, regs: &mut Regs, next_pc: &mut u64, )

Advance the pipeline by exactly one PCycle.

Stages run WB → DC → EX → RF → IC. Because each stage reads its input latch before any upstream stage writes it, no value moves two stages in one cycle and no double buffering is required. Do not reorder this.

Hot path: allocation-free.

Source

pub fn advance_at<B: Bus>( &mut self, bus: &mut B, regs: &mut Regs, next_pc: &mut u64, count_now: u64, )

Pipeline::advance, with the scheduler’s Count timeline supplied.

Count is derived from the master clock (ADR 0006), so the position is passed in rather than incremented here. This is the path the scheduler uses (crate::Cpu::tick_at); Pipeline::advance is a convenience for callers with no scheduler, and holds the timeline rather than guessing at it.

Trait Implementations§

Source§

impl Clone for Pipeline

Source§

fn clone(&self) -> Pipeline

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Pipeline

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Pipeline

Source§

fn default() -> Pipeline

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Pipeline

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for Pipeline

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,