Issie logo Issie

FastCreate Module

Functions and values

Function or value Description

addComponentWaveDrivers f fc pType

Full Usage: addComponentWaveDrivers f fc pType

Parameters:
Returns: WaveIndexT[] array
f : FastSimulation
fc : FastComponent
pType : PortType
Returns: WaveIndexT[] array

addWaveIndexAndDrivers comps f

Full Usage: addWaveIndexAndDrivers comps f

Parameters:
Returns: WaveIndexT array

Called after the fs.Drivers array is created. waveComps must contain all components that can be viewed in the wave simulation. This function mutates fs.Drivers adding the correct arrays where these are used. In some cases an array may never be used and therefore is not added. In parallel with this, the function returns an array of WaveIndexT records that reference component ports which can be viewed in a wave simulation. Every WaveIndex references an element of fs.Drivers from which the simulation data is found.

comps : FastComponent array
f : FastSimulation
Returns: WaveIndexT array

addWavesToFastSimulation comps fs

Full Usage: addWavesToFastSimulation comps fs

Parameters:
Returns: FastSimulation

Adds the Drivers and WaveIndex fields to a fast simulation. For use by waveform Simulator. Needs to be run after widths are calculated. **What a simulation needs only in order to be DRAWN**, and all of it sized by the expansion: a map of every component of every instance, an entry per step array, and an entry per wave-carrying port. `WaveTables` is what decides whether a build pays for them; a simulator that runs and answers reads by name does not.

comps : FastComponent array
fs : FastSimulation
Returns: FastSimulation

assertThat cond msg

Full Usage: assertThat cond msg

Parameters:
    cond : bool
    msg : string

Modifiers: inline
cond : bool
msg : string

checkSimulationFits arraySize cost

Full Usage: checkSimulationFits arraySize cost

Parameters:
Returns: Result<unit, SimulationError>

Refuse a simulation whose step arrays would not fit, before a byte of them is allocated. Before rather than after, because the arrays ARE what exhausts memory: a check that had to build them first would be the thing it is meant to prevent. Everything it needs is known by then - the flattened design gives every width, and the caller has said how many cycles it wants - so the answer is exact rather than a guess. A Result and not an exception: this is a limit an ordinary user reaches by asking for a long waveform simulation of a big design, so it travels the same path as any other simulation error and is shown the same way, saying what would fit instead. The line enforced here is the budget times SimulationBudget.runtimeHeadroom, not the budget: this check is the crash guard of last resort, and the configuration dialog - which holds users to the budgets exactly - is the advertised limit. The gap is for the simulation that arrives without passing that dialog, a LastClock saved into a sheet on a larger machine above all, which should run if it safely can rather than fail the moment Start is pressed. The advice in the refusal still quotes the dialog's own bound, so following it always works.

arraySize : int
cost : StepCost
Returns: Result<unit, SimulationError>

compType t

Full Usage: compType t

Parameters:
Returns: string
t : ComponentType
Returns: string

costAndSizeOfGraph graph

Full Usage: costAndSizeOfGraph graph

Parameters:
Returns: StepCost * int

What one clock cycle of this design will cost, read straight off the merged SimulationGraph - before it is flattened, before a FastComponent exists, and allocating nothing itself. One step array is allocated per output port of every component of every INSTANCE, so that is what is counted: the graph is walked the way the flatten walks it, descending into each custom component's own graph, so a sheet used ten times is charged ten times. It is deliberately taken from the graph and not from the flattened design. The flatten now creates the step arrays as it goes, so a cost worked out from its output would be worked out after the memory it is meant to refuse had been taken - see checkSimulationFits below, whose whole point is to come first. Reading the graph keeps the check where it belongs and, as a bonus, is what lets the waveform simulator's configuration dialog price a design (ModelHelpers.waveSimStepCost) without building any of it. Custom components are counted, not skipped: their output arrays are allocated and then replaced by links to the arrays inside them (linkFastCustomComponentsToDriverArrays), and the replaced ones stay in the step-array arena for the simulation's whole life. So this count is exactly what a built simulation occupies, the replaced quarter included, not an estimate of it. The per-step State array is counted too. Only RAMs ever write it, but createFastComponent allocates one for every component that could be synchronous - customs included - so on a register-heavy design it is real memory, and the estimate that omitted it said a design was smaller than it is. The count comes back alongside the cost because both are wanted at the same moment, by the same caller, from the same walk: the build sizes its component store from the count so that the store never has to grow, and refuses the design outright on the cost.

graph : SimulationGraph
Returns: StepCost * int

createFastComponent maxArraySize sComp accessPath fullName

Full Usage: createFastComponent maxArraySize sComp accessPath fullName

Parameters:
Returns: FastComponent

create a FastComponent data structure with data arrays from a SimulationComponent. numSteps is the number of past clocks data kept - arrays are managed as circular buffers. fullName is given rather than filled in afterwards: the flatten stores this object in its index space, and `{ fc with FullName = ... }` afterwards would put a DIFFERENT object there than the one the caller kept - a copy of a 23-field record per component, and a reference-equal identity broken, for a string that is known when it is made.

maxArraySize : int
sComp : SimulationComponent
accessPath : ComponentId list
fullName : string
Returns: FastComponent

createInitFastCompPhase simulationArraySize g f

Full Usage: createInitFastCompPhase simulationArraySize g f

Parameters:
Returns: FastSimulation

The door between the build's index space and the rest of the program. It used to create the FastComponents as well; the flatten does that now, so what is left of it is the boundary. What a built simulation offers is the STORE - FCompsByIndex, in gather order - and one map, FIndexOf, from the design-time name a caller arrives with to a place in it. The name is what survives a rebuild and so what the renderer holds; the index is what everything inside the simulation works in. Custom against ordinary is decided here, by a predicate over the one store. It is not a second index space and must not become one: the links the flatten resolved are positions in this store, and splitting it would make the same integer mean two different things.

simulationArraySize : int
g : GatherData
f : FastSimulation
Returns: FastSimulation

determineBigIntState comps f

Full Usage: determineBigIntState comps f

Parameters:
Returns: FastSimulation
comps : FastComponent array
f : FastSimulation
Returns: FastSimulation

emptyFastSimulation diagramName

Full Usage: emptyFastSimulation diagramName

Parameters:
    diagramName : string

Returns: FastSimulation
diagramName : string
Returns: FastSimulation

findBigIntState fc

Full Usage: findBigIntState fc

Parameters:
Returns: bool * BigIntState option
fc : FastComponent
Returns: bool * BigIntState option

finishStepArena ()

Full Usage: finishStepArena ()

Parameters:
    () : unit

() : unit

gatherSimulation maxArraySize size graph

Full Usage: gatherSimulation maxArraySize size graph

Parameters:
Returns: GatherData

Flatten the SimulationGraph into the one index space the rest of the build works in, creating every FastComponent - and so every step array - as it goes. size is how many components the expanded design has, from costAndSizeOfGraph, so the store is made at exactly the right size and never grows. That same walk is what priced the design and refused it if it would not fit, which is why this may allocate at all: by the time it runs the budget has been checked and the step-array arena opened for what it said.

maxArraySize : int
size : int
graph : SimulationGraph
Returns: GatherData

getFid cid ap

Full Usage: getFid cid ap

Parameters:
Returns: ComponentId * ComponentId list
cid : ComponentId
ap : ComponentId list
Returns: ComponentId * ComponentId list

getPortNumbers sc

Full Usage: getPortNumbers sc

Parameters:
Returns: int * int
sc : SimulationComponent
Returns: int * int

linkCustomComponentPorts comps fs

Full Usage: linkCustomComponentPorts comps fs

Parameters:
Returns: FastSimulation

Point every custom component's ports at the arrays of the Input and Output components inside it, so that reading a custom component's port reads the signal it actually carries. Not optional, and not part of the wave tables below even though it used to be in the same phase: a port that points at the dummy array it was created with reads as nothing. Cheap - one re-pointing per port of each custom component, and there are far fewer of those than of ordinary ones. `comps` is every component of the build in creation order - the array the gather filled, not the maps. See the note on createFastArrays: walking the maps here means walking the components in a different order from the one they were allocated in, and on a design of any size that is most of what this phase costs.

comps : FastComponent array
fs : FastSimulation
Returns: FastSimulation

linkFastComponents g f

Full Usage: linkFastComponents g f

Parameters:
Returns: FastSimulation

Use the links the flatten resolved to tie the FastComponents' data arrays together. InputLinks[i] is set equal to the driving Outputs array, so that input i reads the data reduced by the correct output of the component that drives it. The main work is dealing with custom components, which represent whole design sheets with recursively defined component graphs. The custom component itself is not linked and does not exist as a simulatable FastComponent - instead its graph's Input and Output components are linked to whatever connects to the corresponding ports of the custom component. Note: custom components are linked in later as unsimulatable placeholders, to let the wave simulation reach their ports. Everything here works in store indices. It used to work in (ComponentId, access path) pairs against four maps, and that was the build's shape problem: a structural key costs a boxed comparison of a GUID-like id and a list per tree level, and this function does one per link of every component of the expanded design.

g : GatherData
f : FastSimulation
Returns: FastSimulation

linkFastCustomComponentsToDriverArrays fs (arg2, arg3) fc

Full Usage: linkFastCustomComponentsToDriverArrays fs (arg2, arg3) fc

Parameters:
Returns: Unit

Changes all the custom component in and out StepArray links so they point to the correct drivers. (fid, fc) must be a custom component. Called after the simulation has been fully constructed and linked.

fs : FastSimulation
arg1 : ComponentId
arg2 : ComponentId list
fc : FastComponent
Returns: Unit

makeIOArray size

Full Usage: makeIOArray size

Parameters:
    size : 'a

Returns: IOArray
size : 'a
Returns: IOArray

makeIOArrayW w size

Full Usage: makeIOArrayW w size

Parameters:
    w : int
    size : int

Returns: IOArray
w : int
size : int
Returns: IOArray

makeStepArray arr

Full Usage: makeStepArray arr

Parameters:
    arr : 'T array

Returns: StepArray<'T>
arr : 'T array
Returns: StepArray<'T>

maxCyclesFor cost

Full Usage: maxCyclesFor cost

Parameters:
Returns: int

The most clock cycles of a design costing this much that will be allowed, whichever of the two budgets binds first. Used both to refuse a simulation and to say in the waveform simulator's configuration what may be asked for, so that the two cannot disagree.

cost : StepCost
Returns: int

maxLastClockFor cost

Full Usage: maxLastClockFor cost

Parameters:
Returns: int

The largest WSConfig.LastClock a design costing this much can be configured to. maxCyclesFor bounds the step ARRAYS, and the arrays carry a zoom margin past the last clock - up to CommonTypes.waveSimMaxArrayMargin - so the two numbers differ by exactly that margin. Every message that tells the user what may be ASKED for must quote this one: quoting the array bound as a configuration value told the user to set a number that was itself refused.

cost : StepCost
Returns: int

portCarriesWave f fc pType

Full Usage: portCarriesWave f fc pType

Parameters:
Returns: bool

Add one driver changing the fs.Driver array reference. Return a WaveIndex reference. WaveIndex refrences are bound to specific component ports and not unique per driver. Whether a port of a component carries a waveform the user can watch. The rules the wave index is built from, said once. They used to live only inside addComponentWaveDrivers, which walks every port of every component of the whole expanded simulation; anything wanting to know which ports one INSTANCE offers - without walking the expansion to find out - has to decide it the same way, and two copies of a rule like this drift. The builder below now asks this, so there is one answer. What is excluded, and why each: the input side of components whose input is not a signal of its own (an IOLabel, an Input1, a Viewer, a NotConnected, an Output); a Constant1, whose output drives but is not worth watching; every IOLabel of a same-named group except the one elected to drive it, since they are all one net; the wiring components, which carry no signal distinct from what they are wired to; and the Input1 and Output components INSIDE a subsheet, whose signal is the enclosing custom component's port and is offered there instead.

f : FastSimulation
fc : FastComponent
pType : PortType
Returns: bool

simulationPlaceholder

Full Usage: simulationPlaceholder

Returns: FastSimulation
Returns: FastSimulation

startStepArena cost steps

Full Usage: startStepArena cost steps

Parameters:

Start drawing step regions from arena slabs, sized for what this build is about to need. The size matters more than it looks. A slab used to be a fixed 256MB whatever was being built, so EVERY simulation - a three-component test circuit as much as a CPU - allocated and zeroed 256MB before it could hold its first cycle. Under .NET that is a large-object allocation per build, and a test suite that builds a few thousand small simulations spent eight minutes of its twelve doing nothing else. The cost of a build is now the cost of what it holds. The numbers come from `stepCostOfGraph`, which is computed for the memory budget before the arrays are allocated and charges for exactly what the arena keeps - so the first slab is the whole of an ordinary build. A build that needs more than a slab, or more than was planned for, simply takes another; nothing depends on the estimate being right. Callers must pair this with finishStepArena however the build ends, or the next truth-table build would draw from a slab nobody meant it to share.

cost : StepCost
steps : int

stepArrayIndex

Full Usage: stepArrayIndex

Returns: int
Returns: int

stepBytesForWidth w

Full Usage: stepBytesForWidth w

Parameters:
    w : int

Returns: int

One clock cycle of a bus of this width, in bytes of the memory it is stored in. See above, and keep in step with makeIOArrayW immediately below: they describe the same allocation.

w : int
Returns: int

stepCostOfGraph graph

Full Usage: stepCostOfGraph graph

Parameters:
Returns: StepCost
graph : SimulationGraph
Returns: StepCost

Type something to start searching.