Skip to main content

TimingModel

Struct TimingModel 

Source
pub struct TimingModel {
    pub paths: Vec<PathEntry>,
    pub timing_checks: Vec<CheckEntry>,
    /* private fields */
}
Expand description

The per-design, runtime-mutable timing-annotation table (§1.1).

Fields§

§paths: Vec<PathEntry>

One per desugared PathEntry (Track A).

§timing_checks: Vec<CheckEntry>

One per CheckEntry (Track B).

Implementations§

Source§

impl TimingModel

Source

pub fn new() -> TimingModel

An empty table (no design has been seeded into it yet).

Source

pub fn seed_specparams(&mut self, infos: &[(InstanceId, Symbol<'_>)])

Seeds the specparam table from every Specparam member of each (instance, body) pair in infos — the SAME per-instance (InstanceId, Symbol) shape vj::primitives::plan’s own bodies parameter already uses — via super::module_items (the same discovery surface primitives.rs already walks). Specparam is a direct module member, legal both inside and outside a specify block (LRM 30.3). Stores each one’s frozen constant_value() — the pre-SDF baseline a later $sdf_annotate LABEL annotation (Task 28) overwrites in place through Self::set_specparam.

A specparam declared INSIDE a specify ... endspecify block (LRM 30.3’s own specify_item production lists specparam_declaration; 30.7.1’s PATHPULSE$ is only ever legal there) is not a direct Specparam member of body the way a module-scope one is: module_items deliberately leaves SpecifyBlock opaque (it only recurses into GenerateBlock/GenerateBlockArray, per that function’s own doc comment — dedup.rs/elaborate.rs/instance.rs/ primitives.rs all rely on that), so a specify-block specparam’s real Specparam symbol is a child of the SpecifyBlock member itself, never surfaced by the module_items walk above. This loop therefore also looks inside every SpecifyBlock member it finds and seeds any Specparam declared directly in it, one level deep (a specify block cannot nest another one — 30.3 gives it no such production — so one level is exhaustive).

Deviation from the plan’s own pseudocode signature: no &EvalSession parameter. Symbol::constant_value() is documented as “a pure read on a frozen design… never evaluates” (sv-lang’s own doc comment), so no session is needed here — the plan carried one for symmetry with specify_eval::eval_specparam_aware’s (which genuinely needs one, for its general-constant-folding fallback), not because seeding itself requires one.

Source

pub fn specparam( &self, instance: InstanceId, uid: &SymbolId, ) -> Option<&ConstantValue>

The specparam identified by (instance, uid)’s current value: the pre-SDF baseline seed_specparams stored, or whatever a later direct mutation ([set_specparam] (Self::set_specparam) — $sdf_annotate, Task 28) has since overwritten it with. A plain table lookup, needing no EvalSession/live Design.

Source

pub fn set_specparam( &mut self, instance: InstanceId, uid: SymbolId, value: ConstantValue, )

Overwrites (or inserts) a specparam’s value directly — what Task 28’s real SDF LABEL annotation calls, and what this task’s own unit tests use to simulate it ahead of time. This task’s “mutation path” acceptance criterion: no EvalSession/Design/Symbol anywhere in this signature, only InstanceId/SymbolId/the plain, fully-owned ConstantValue.

Source

pub fn set_path_delays( &mut self, instance: InstanceId, path_uid: &SymbolId, delays: PathDelaySet, )

Attaches delays to every desugared PathEntry that came from the one TimingPath symbol identified by (instance, path_uid) (LRM 30.4.6: several entries share one declaration, and all share its one delay list) – vj’s own plan-time pass (crate::specify::discover, right after calling Self::discover) is the only caller; see PathEntry::delays’s own doc comment for why evaluation lives there, not here. A no-op, never an error, if nothing matches – Self::discover’s own loop already guarantees that a path_uid it produced has at least one entry, so a caller passing a path_uid it did not itself get from THIS SAME TimingModel’s own Self::paths is a caller bug, not a runtime condition this method needs to report.

Source

pub fn set_path_pulse_limits( &mut self, instance: InstanceId, path_uid: &SymbolId, reject: u64, error: u64, )

Attaches a PATHPULSE$ (LRM 30.7.1) – reject and error, already evaluated and tick-converted by the caller exactly like Self::set_path_delays’s own delays (see that method for why evaluation lives in vj) – to every desugared PathEntry of the one TimingPath symbol (instance, path_uid); every transition of each gets the same two values.

Implementation-defined choice: LRM 30.7.1 requires the error limit to be at least the reject limit but does not say what a source that writes (6, 2) means. Rather than reject a design over it, the error limit is raised to the reject limit (error = max(error, reject)), which makes the region between the two empty: a pulse is then either cancelled or passed, never filtered to x.

Like Self::set_path_delays, a no-op if nothing matches.

Source

pub fn apply_pulse_percent(&mut self, reject_pct: f64, error_pct: f64)

Sets every path’s reject and error limit to reject_pct / error_pct percent of each transition’s OWN delay (LRM 30.7.2, 32.7: the global invocation options), rounded to the nearest tick, an error limit below the reject limit raised to it (the same implementation-defined repair as Self::set_path_pulse_limits). 100.0 is exact (the LRM default, limits equal to the delays). A PATHPULSE$ is more specific than this option and must be applied AFTER it (Self::set_path_pulse_limits); like Self::set_path_delays, which re-establishes the default this replaces, it must come after the delays.

Source

pub fn set_pulse_options( &mut self, style: Option<PulseStyle>, showcancelled: Option<bool>, )

Sets the pulse style and showcancelled invocation options (LRM 30.7.4.1/30.7.4.2). An option that is Some takes precedence over every specify block declaration of its axis (the LRM’s own wording), so Self::discover applies it AFTER the declarations; one that is None was not given and the declarations (then the built-in on-event / noshowcancelled) decide. Must be called BEFORE Self::discover.

Source

pub fn discover<'d>( &mut self, eval: &EvalSession<'d>, infos: &[(InstanceId, Symbol<'d>)], ) -> Result<(), ElabError>

Walks every (instance, body) pair’s SpecifyBlock members (Task 3, docs/superpowers/plans/2026-10-03-sdf.md), appending one PathEntry per desugared module path to Self::paths and one CheckEntry per SystemTimingCheck to Self::timing_checks ([discover_check] decodes its arguments by kind and enforces the clause’s compile-time restrictions as named errors, Task 13).

SpecifyBlock’s own member-kind match is exhaustive over LRM 30.3’s specify_item production (specparam_declaration | path_declaration | system_timing_check | pulsestyle_declaration/showcancelled_declaration, i.e. SymbolKind::{Specparam,TimingPath,SystemTimingCheck,PulseStyle}): any other member kind is a named ElabError::UnsupportedConstruct, never a silent skip, matching this crate’s own top-of-file discipline. Specparam members are skipped here (already seeded by Self::seed_specparams); PulseStyle members (Task 11: pulsestyle_onevent/_ondetect/showcancelled/noshowcancelled) are validated against LRM 30.7.4.1/30.7.4.2’s declaration-order rule as they are met, then applied to the PathEntrys whose outputs they name once the module’s whole specify content has been walked ([discover_pulse_style], [apply_pulse_style_declarations]).

A TimingPath whose desugaring would need [EvalSession:: eval_constant] (a bit-select/part-select terminal whose index is not already folded) is why this method takes eval, unlike Self::seed_specparams — mirrors specify_eval:: eval_specparam_aware’s own reason for carrying one.

Trait Implementations§

Source§

impl Default for TimingModel

Source§

fn default() -> Self

Returns the “default value” for a type. 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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V