Issie logo Issie

WaveData Module

Where the waveform viewer gets its data, whichever simulator produced it. Two sources answer the same two questions. `Local` reads the renderer's own `FastSimulation` step arrays in place, which is what the viewer has always done. `Fetched` answers from the window most recently pulled off the .NET sidecar, which holds only the samples the current view draws - that being the whole point, since a sidecar simulation is sized for the machine's memory rather than a browser heap and its step arrays are far too large to ship. **Both questions are answered with a slice**, even the point reads: a cursor column is one sample of every selected wave, which is a window of one. That keeps one shape on the wire, one shape in the cache and one shape for the drawing code - and it is the shape that will carry run-length encoded waveforms when they arrive (see WaveSlice). **Why the source is module state.** The functions here are called from view code - `getWaveValue` while laying out the value column, the hover cache while building a tooltip - which has no model to thread a flag through, and reaching for a global is what that code already does for the simulation itself (`Simulator.simCache`). This mirrors it deliberately rather than inventing a second convention: set when the waveform simulator refreshes, cleared when it ends, and read from view code. See docs/mutableState.md - this is a cache of what the app is displaying, not model state.

Types

Type Description

CachedWave

One wave's samples, and the window they cover. Per WAVE, not per view. What the viewer needs to know is "does this wave have the cycles it is being drawn over", and that is a question about one wave: a wave just added to the selection is missing while every other wave is fine, and a window that has moved leaves them all missing together. Keying by wave says both without a special case, where one entry for the whole view could only say "all" or "none". Waves fetched together share one array - a reply is signal-major and copying it apart would be the only copy in the path - so each entry carries where its own row starts.

Held

What the cache holds for one wave over one window: its samples, or the reason there are none. "There are none, and asking again will not help" has to be sayable. A missing wave is exactly what asks for a fetch, so a wave that can never be fetched - the simulation has no driver to name it by - would be asked for again by every update for as long as it stayed selected. The answer is recorded like any other, against the window it was asked over.

Source

Functions and values

Function or value Description

current ()

Full Usage: current ()

Parameters:
    () : unit

Returns: Source
() : unit
Returns: Source

hasData arg1 window

Full Usage: hasData arg1 window

Parameters:
Returns: bool

Does this wave hold the window it is about to be drawn over? The renderer's own simulation always does - it is read in place - so only a fetched source can answer no, and a no is what makes a wave one that needs fetching.

arg0 : SignalHandle
window : Window
Returns: bool

heldWindow arg1

Full Usage: heldWindow arg1

Parameters:
Returns: Window option

The window this wave's samples cover, when it has some. What the viewer can draw for it RIGHT NOW, which while a view is being scrolled is neither the window on screen nor the one the controls ask for: it is whatever the last fetch to land carried. Drawing that rather than keeping what is on screen is what makes a fast scroll move.

arg0 : SignalHandle
Returns: Window option

holdNothing epoch

Full Usage: holdNothing epoch

Parameters:
    epoch : int

Read from the sidecar session `epoch`, holding nothing yet: every wave has to be asked for. NOT the same as Local, which is what the renderer's own simulation is. In .NET mode the renderer's step arrays exist but are never run, so reading through to them would draw a column of zeros with the confidence of simulation output. This says "ask", where Local says "look".

epoch : int

needFetching handles window

Full Usage: needFetching handles window

Parameters:
Returns: SignalHandle list

The waves, of those being drawn, that do not hold the window they are drawn over. Derived, every time it is asked for, from the cache and the view. Nothing records which waves are outstanding: a wave needs fetching exactly when it has not got the cycles it is being drawn over, and that is a question with an answer at any moment.

handles : SignalHandle list
window : Window
Returns: SignalHandle list

setFetched epoch waves

Full Usage: setFetched epoch waves

Parameters:

Add what a fetch of session `epoch` carried, keeping any waves already held that it did not carry - a fetch asks only for the waves that were missing, so the rest are still current. **Refused unless the cache is of that session** (invariant D4). This is written from inside the promise that fetched, where the model - and so which session is on screen - is not reachable; the alternative was to write regardless and check somewhere later, and there is no later that comes before the next render. A reply from a build that has been replaced would otherwise land under driver indices the new build has reused, and be drawn under the new signal's name until something moved. A wave short of its own samples is reported AND kept out (invariant D3). A short reply is silent: reading past the end of a typed array is `undefined` in JavaScript rather than a fault, so every wave after the truncation point drew somebody else's samples - or NaNs - as confidently as the rest. Reporting it and then storing it anyway made the check a description of the failure instead of a stop to it. A wave with no entry draws nothing, which is what the viewer already does for one whose data has not arrived.

epoch : int
waves : (DriverIndex * CachedWave) list

setLocal lookup clock

Full Usage: setLocal lookup clock

Parameters:

Read from the renderer's own simulation, through `lookup`. Nothing is copied - a local slice names the step array where it lies - so this "fill" is only recording how to find it.

lookup : SignalHandle -> IOArray option
clock : unit -> int

setNoDriver epoch handles window

Full Usage: setNoDriver epoch handles window

Parameters:

Record that these waves were asked for over this window under session `epoch`, and the simulation cannot name them. Not an error and not a gap to be retried: a wave whose driver the simulation does not offer is one this build has no way of fetching, so what is recorded is that answer. It goes in the cache rather than in a list of exceptions because the question - "has this wave got the window it is drawn over" - is the same one, and one answer is easier to keep true than two. Session-checked exactly as `setFetched` is, and for the same reason: "no driver" is an answer about one build, and the next build may well have one.

epoch : int
handles : DriverIndex list
window : Window

slice h window

Full Usage: slice h window

Parameters:
Returns: WaveSlice option

A slice of one wave over `window`, or None where the data is not held - which for a fetched source means the view has moved and the fetch for it has not landed yet, and for a local one means the simulation has not run that far. Every caller already has a way of showing nothing.

h : SignalHandle
window : Window
Returns: WaveSlice option

valueAt h cycle

Full Usage: valueAt h cycle

Parameters:
Returns: FastData option

The value of one wave at one clock cycle, for the value column, the hover tooltip and the schematic probe. None where it cannot be answered.

h : SignalHandle
cycle : int
Returns: FastData option

Type something to start searching.