Simulation Workflow¶
Monata separates simulation setup from simulation execution. A simulation is
described as data, submitted to an executor, then returned as a SimResult.
circuit + AnalysisSpec + optional corner/parameters
-> SimTask
-> Executor
-> SimResult
Analysis Specifications¶
Analysis specs describe what to run. Creating a spec does not start a simulation.
from monata.sim.core import ACSpec, DCSpec, NoiseSpec, OPSpec, TranSpec
tran = TranSpec(stop=10e-9, step=10e-12)
ac = ACSpec(start=1e3, stop=1e9, points=100, variation="dec")
dc = DCSpec(source="Vin", start=0.0, stop=1.2, step=0.01)
op = OPSpec()
noise = NoiseSpec(output_node="out", input_source="Vin", start=1e3, stop=1e9, points=100)
The built-in ngspice-subprocess backend currently executes DCSpec,
TranSpec, ACSpec, OPSpec, and NoiseSpec. Operating-point outputs use
task-level output_names; noise outputs use NoiseSpec.output_node and
NoiseSpec.input_source.
Simulation Tasks¶
SimTask is the unit of work. It combines the circuit, analysis, backend, and
optional context such as corners or parameter overrides.
from monata.sim.core import SimTask
task = SimTask(
circuit=circuit,
analysis_spec=tran,
simulator="ngspice-subprocess",
output_names=["in", "out"],
param_overrides={"w_p": 2e-6},
osdi_paths=["models/bsimcmg.osdi"],
metadata={"run": "nominal"},
)
For native ngspice execution, circuit must be a monata.netlist.Circuit.
output_names is required for DC, transient, AC, and operating-point runs:
the backend does not guess or enumerate nodes. DC and transient runs write
v(name) vectors; AC runs write mag(v(name)) vectors; operating-point runs
return one-row arrays for requested node voltages.
Noise is the exception to the task-level output rule. A NoiseSpec already
names the output node and input source, so SimTask.output_names must be
empty. Noise results return onoise_spectrum and inoise_spectrum waveforms
aligned to sweep_var, with onoise_total and inoise_total in metadata.
The input source must have an AC value in the netlist.
osdi_paths are loaded with ngspice pre_osdi commands before the analysis
command.
param_overrides supports circuit-level .param overrides whose names are
simple identifiers, plus structured native element overrides written as
element.parameter targets such as R1.R or M1.W. A structured target must
match an element in the native intermediate representation; otherwise the
backend fails explicitly with
metadata["reason"] == "unsupported_param_overrides".
Corner voltage overrides are applied through the same structured mutation path
when the named source exists, for example {"VDD": 1.0} becomes a VDD.V
source-value override. Process/model corner fields still require concrete
model files or techlib projection before ngspice can execute them.
Executors¶
LocalExecutor dispatches tasks on the local machine. Use one task for a
single run, or map many tasks for sweeps and corners.
from monata.sim.core import LocalExecutor
executor = LocalExecutor(max_workers=4)
future = executor.submit(task)
result = future.result()
For multiple independent tasks:
futures = executor.map(tasks)
results = [future.result() for future in futures]
Results¶
SimResult contains:
Field |
Meaning |
|---|---|
|
|
|
named waveform arrays or backend output objects |
|
x-axis values for swept data when available |
|
corner metadata when the run came from a corner matrix |
|
backend-specific details |
|
failure text when the task failed |
Always check status before evaluating measurements.
if result.status != "ok":
raise RuntimeError(result.error_message)
vout = result.waveforms["out"]
Common ngspice failure reasons include:
Reason |
Meaning |
|---|---|
|
|
|
the selected analysis is not implemented by the native backend |
|
|
|
an output name, analysis field, OSDI path, or command token was invalid |
|
an OSDI or corner model file path did not exist |
|
a parameter or source override target was not found or could not be applied safely |
|
a process/model corner field could not be projected to a concrete ngspice model reference |
|
ngspice ran but exited non-zero |
|
ngspice output could not be parsed into the requested outputs |
Backend Selection¶
Keep backend selection close to the task or library technology configuration:
task = SimTask(
circuit=circuit,
analysis_spec=spec,
simulator="ngspice-subprocess",
)
SimTask.simulator is resolved through Monata’s backend registry. Use
ngspice-subprocess as the default stable local runner. Use ngspice-shared
only when a compatible user-installed libngspice shared library is available
in the runtime environment. Both runners preserve the same SimTask and
SimResult contract and keep ngspice itself as an external runtime dependency.
Use the user guide for Monata concepts, and use the toolchain pages for backend-specific behavior: