Monata API Boundaries

Monata separates stable public APIs from internal implementation details. The 0.1.x public names should usually live only in their owning modules rather than being carried through transitional facades. The only standing exception is a deliberately small root facade for foundational package concepts.

Stable public APIs

  • monata.library, monata.cell, monata.registry, and monata.workspace for project/library/cell metadata and lookup.

  • monata.netlist for native netlist IR types, mutation, and rendering: Circuit, SubCircuit, Element, Directive, SourceValue, MutationError, MutationProjection, apply_mutation, project_param_overrides, and render_ngspice. Circuit.to_spice(), SubCircuit.to_spice(), Element.to_spice(), Directive.to_spice(), ModelCard.to_spice(), and SourceValue.to_spice() are explicit convenience methods for rendering native objects through the same owned renderer. Native scopes also own stable element lookup and edit operations through methods such as get_element(), element(), remove_element(), and replace_element(), plus node-name inspection through get_node(), node(), and has_node(). Node helpers return native node-name strings rather than a separate public node object model. get_node(name, create=True) and node(name, create=True) may pre-register loose node names for authoring and topology handoff without rendering standalone SPICE lines. Attribute access such as scope.Rload is a convenience lookup for uniquely named elements and does not replace explicit lookup/edit APIs. Element.parameters, Directive.parameters, SourceValue.parameters, Element.get(), Directive.get(), SourceValue.get(), Element[...], Directive[...], SourceValue[...], and missing attribute lookup expose read-only access to native record parameters. Element.clone(), Directive.clone(), and SourceValue.clone() are native record-copy helpers for immutable-style edits before replacing or reusing records in a scope. Disabled elements remain addressable records through Element.enabled = False but are omitted by scope rendering. Element.comment is rendered as a preceding SPICE comment line by the owned renderer. Element.raw_suffix is the element-level one-line escape hatch for unsupported trailing tokens after structured parameters; prefer structured params whenever Monata can represent a token. Scope-level raw simulator text belongs in ordered raw directives through raw_directive() and raw_block(); this remains a line-oriented escape hatch rather than a second mutable netlist model. Convenience helpers such as Circuit.resistor() and Circuit.mos() reserve their Python argument names for structural fields like element name, nodes, value, and model. When a simulator parameter must use one of those names, use the explicit IR escape hatch: construct Element(..., params=...) and add it with Circuit.add(). monata.netlist.device_schema owns optional element/pin/parameter metadata records. monata.netlist.topology owns the optional editable node/pin graph that can be projected back into the record IR; the record IR remains the render/simulation boundary.

  • monata.circuits for reusable circuit construction helpers such as CMOS transistor/gate helpers and source-subcircuit construction helpers. Project-specific topology recipes, such as a fixed library multiplier, belong in the owning circuit library.

  • monata.corner for the canonical OperatingCorner model shared by techlib and simulation.

  • monata.views.registry for registering and resolving view type factories.

  • monata.cell.Cell.write_generated_view owns generated artifact writes and metadata commits. monata.generation owns generated symbol/netlist content construction and calls that public cell boundary.

  • monata.techlib.registry, monata.techlib.schema, and monata.techlib.projection for techlib loading, registry discovery, schema records, PDK instance validation, and projection records. monata.techlib is a namespace package surface, not a compatibility facade.

  • monata.projection for resolving PDK projection owner context and applying validated source-level PDK instances into netlist scopes.

  • monata.parser for SPICE import and conversion entry points: parse_spice_to_circuit, import_spice_deck, import_spice_asset, spice_to_python, inspect_spice_import, inspect_spice_analysis, spice_to_sim_tasks, parse_spice_expression, render_spice_expression, walk_spice_expression, parse_source_subcircuit, ImportedAsset, SpiceImportPlan, SpiceImportStep, SpiceImportExpressionCheck, SpiceControlCommand, SpiceSourceDependency, SpiceImportIssue, SpiceAnalysisPlan, SpiceAnalysisStep, SpiceAnalysisMeasurement, SpiceAnalysisSweep, SpiceAnalysisIssue, SpiceExpression and its concrete expression record types, SourceSubcircuit, SourceSubcircuitInstance, SpiceParseError, and UnsupportedConstructError. SPICE import is a two-stage boundary: recognized commands are either projected into native Monata IR, used for import flow control, or preserved as raw directives for the simulator. Import inspection exposes those decisions and unsupported constructs without turning parsed SPICE into a second public netlist model. Analysis import is a separate parser boundary: deck-level .tran/.ac/.op and related commands may be projected into backend-neutral SimTask records while the base circuit is rendered without duplicate analysis directives. Pure task-style .control blocks may also be migrated when they contain only analysis, measurement, output-vector, and ignorable run/quit commands; stateful or side-effecting control scripts remain outside the SimTask migration contract. Imported .measure commands are exposed as plan records and filtered into the matching task’s circuit and metadata; they are not promoted into a second Monata measurement DSL. Imported .step param sweeps are exposed as sweep records and expand into multiple SimTask instances with param_overrides; imported .step temp sweeps expand into task operating corners. Step imports support list, linear, decade, and octave sweep forms at this analysis boundary. The native netlist IR still preserves .step as raw text outside the analysis-import boundary. String inputs are treated as SPICE text; filesystem reads require an explicit Path. The expression parser is a lightweight inspect/render frontend for SPICE math expressions; it does not evaluate parameters or own netlist semantics. Import plans may attach expression checks and warning diagnostics to expression-like fields, but native projection still preserves the original string values. LTspice/RKM number forms such as 2k3 are accepted only through explicit dialect options on expression-oriented APIs, not as the default SPICE number contract. .control blocks remain raw simulator text at projection time, but import plans classify internal commands so analysis/measure migration candidates and side-effecting control commands are visible. .include and .lib references are exposed as source dependency records with optional search-path resolution diagnostics; import inspection does not recursively load those files or replace monata.spice_library/project-library ownership. Common ngspice aliases and library-section markers such as .meas and .endl are accepted at the import boundary; projected measurements use Monata’s canonical measure directive representation.

  • monata.eda.kicad for KiCad XML netlist import. The adapter parses KiCad components/nets, reports a component-level import plan, and projects supported components into native Circuit/Element records or a generated Monata netlist cell view. It can also export a supported netlist projection as Python builder source for editable handoff. It is a front-end adapter, not a schematic object model.

  • monata.spice_library for indexing third-party SPICE model/subcircuit files. This is separate from monata.library, which remains the Monata project cell library abstraction. The index may expose lightweight category/tag metadata for discovery and may attach indexed items to native netlist scopes as .include/.lib references. Indexed items may return their original source .model/.subckt snippets for downstream import or inspection, but the library index does not own a full SPICE AST and does not define a fixed vendor or product catalog schema.

  • monata.sim.analysis_spec, monata.sim.task, monata.sim.results, monata.sim.waveform, monata.sim.executor, and monata.sim.vector_names own the core simulation contracts. monata.sim.core is a stable convenience import bundle over those owner modules; it should not contain implementation logic or become a broad compatibility facade. Its export set is intentionally locked by public API tests; add a new core export only when the name belongs in the small simulation kernel rather than a specialized workflow module. Sweep and Monte Carlo orchestration belong in monata.sim.sweep and monata.sim.montecarlo; digital testbench orchestration belongs in monata.sim.digital_table and related digital owner modules. Those workflow modules are public owner-module APIs, but they are intentionally not part of the monata.sim.core compatibility bundle. monata.sim.task owns simulation input contracts such as SimTask, task defaults, output-name normalization, and SimArtifactOptions. monata.sim.results owns execution output contracts such as SimResult, SimStatus, AnalysisResult, waveform lookup, result payload aliases, and array-to-result construction. monata.sim.result_ops owns result-level numeric transforms such as derivative, integral, resampling, sampling, and windowing; AnalysisResult keeps thin method wrappers for ergonomic use. Typed Waveform/AnalysisResult objects may expose plotting-neutral data projections such as magnitude, phase, derivative, integral, and ordered numeric/unit-array column projection, including Bode traces derived from frequency-domain analysis results. monata.sim.vector_names owns output vector identity helpers such as normalize_vector_name() and VectorName. Its voltage_vector(), branch_current_vector(), node_current_vector(), device_parameter_vector(), internal_parameter_vector(), and expression_vector() helpers are Monata-owned request builders; bare SimTask.output_names entries remain node-voltage shorthand. Result groupings use explicit Monata names such as node_voltages_by_node, branch_currents_by_element, and element_parameters. Measurement pass/fail semantics remain in monata.measure. SimTask.metadata is descriptive user/task metadata, not a backend control channel. Backend-specific execution controls belong in SimTask.backend_options; simulator artifact persistence belongs in SimTask.artifacts/SimArtifactOptions. Backend results may promote stable Monata result descriptors such as analysis names, requested/observed vectors, measures, artifacts, and compact execution summaries to top-level result metadata, but backend-only diagnostics remain under the backend namespace such as metadata["ngspice"]. Monata-owned workflow control payloads use reserved, versioned namespaces under metadata["monata"]; digital truth-table task scheduling data lives in metadata["monata"]["digital_task_v1"] with schema monata.sim.digital-task.v1, while caller descriptive metadata remains at the task metadata top level. Simulation results that need digital task reconstruction carry that task metadata only through SimResult.metadata["task_metadata"]; older top-level control keys are not accepted.

  • monata.sim.session for the stateful simulation-session builder facade over circuit directives, raw directive blocks, and backend-neutral SimTask creation. Session-level metadata, backend options, and artifact options are copied into tasks and may be overridden per task. Because the session facade is mutable, tasks snapshot the session circuit by default; explicit snapshot_tasks=False/snapshot=False opts back into sharing the live circuit object.

  • monata.sim.analysis_spec for immutable user-facing analysis contracts and their generic canonical analysis names.

  • monata.sim.cache for content-addressed SimTask fingerprints and optional filesystem result caching. The cache key is derived from simulation inputs such as rendered circuit text, analysis spec, corner, parameter overrides, output requests, backend options, task metadata, and referenced model/include/OSDI artifact digests. Timeout and artifact output destination remain outside the identity contract.

  • monata.sim.backends for backend protocol, capability, task-validation, task-planning, and registry APIs. The built-in ngspice runner remains ngspice-subprocess; ngspice-shared is the same-simulator runner for libngspice command/session workflows and requires an available user-provided shared library. Backend extension points are explicit: implement Backend.run() for execution, ValidatingBackend.validate_task() for preflight failures, and PlanningBackend.plan_task() for backend-facing plan introspection. Ngspice backends preserve ordinary simulator and parser failures as failed SimResult values by default; set backend_options["raise_backend_exceptions"] = True when development or CI should surface backend adapter exceptions directly.

  • monata.sim.capabilities for simulator model-flow profiles used when resolving model artifacts and device-level simulator support. These profiles describe a simulator family/dialect and model support; they are not backend registry entries and do not replace monata.sim.backends.BackendCapabilities.

  • monata.sim.digital_table for the user-facing digital truth-table construction/execution facade, monata.sim.digital_results for digital truth-table result and propagation-delay row records, monata.sim.digital_claims for digital oracle/comparison records, and monata.sim.digital_projection for PDK projection helpers used by digital flows. Internal digital task construction and result extraction share explicit plan/schedule/stimulus-metadata records from monata.sim.digital_plan instead of depending on DigitalTruthTable private methods or untyped result metadata reads. Digital table timing options are behavioral contracts: skew_step offsets each input source transition and the corresponding extraction schedule by input index.

  • Digital workflows do not have a compatibility aggregation module; import from the owner modules above. monata.sim is a namespace package surface, not a compatibility facade.

  • monata.sim.export for simulation result serialization helpers, including HDF5 export/import through the default h5py runtime dependency.

  • monata.sim.rawfile for loading external ngspice rawfiles into typed AnalysisResult/Waveform records. Rawfile parser records under monata.sim.backends remain backend implementation details. Ngspice-specific header fields such as circuit name, date, warnings, and TEMP/TNOM are preserved as result metadata. Optional node/element name lists may restore result display casing without changing the underlying raw vector provenance.

  • monata.units and monata.physics for circuit-oriented scalar/array unit values, SPICE suffix parsing, and small sizing/thermal helper formulas.

Root facade

monata may re-export foundational names that are needed before a user chooses a simulation, circuit-construction, techlib, or backend workflow:

  • Cell, Library, LibraryRegistry, and View.

  • OperatingCorner.

  • Common Monata errors.

  • Quantity, Unit, and UnitArray.

The root facade must stay lightweight: importing monata must not import monata.sim, monata.sim.backends, backend implementation modules, or optional plotting/model execution dependencies.

Internal implementation details

  • Import-time backend registration, simulator planning internals, parser record types such as monata.parser.deck.SpiceDeck, and view-loading mechanics are implementation details unless explicitly re-exported in the stable API.

  • Python-backed schematic and testbench views are trusted project code. Calling View.load() or APIs that generate/load those views executes Python in the current process; Monata does not sandbox view code.

  • Private attributes on netlist scopes and mutation indexes are not extension points.

  • Generation implementation details live under monata.generation; higher-level cell methods may call those services but should not duplicate them.

  • Projection algorithms live under monata.projection; higher-level library methods may call those services but should not duplicate them.

Ownership rule

When adding or moving an API:

  1. Put the implementation and public export in the owner module.

  2. Update callers and documentation to import from the owner module directly.

  3. Do not add root-package exports unless the name belongs in the small foundational facade above.

  4. Do not add new cross-module compatibility re-exports during pre-release development. Prefer owner-module imports over migration shims.

  5. Cover boundary decisions with tests when the import path is user-facing.