Reference Standard library

Standard library

The standard library is plain Hover source, shipped as one ordinary installable package called stdlib. hover --setup installs it into the machine-wide project in ~/.hover — releases do not bundle it — and import <math> then resolves through exactly the same package table as any other package. Everything here is reached with an angle-bracket import, and every model is readable — if a device's behaviour surprises you, the equations are right there.

The one package expands into several importable roots — each of its top-level directories (math, semiconductors, parts, analog, optoelectronics, electromechanical) becomes a package root of its own, so <math> and <stdlib/math> name the same directory and both work. Because nothing in the compiler treats these names as reserved, a project can pin its own standard library (stdlib = "0.8.1" in hover.toml) and have every import resolve there instead — see Packages & hpm. Running straight out of a source tree, the stdlib/ directory next to the repo-built binary is the fallback.

Each heading below is one importable directory, and importing it brings in everything listed under it — an import names a directory, not a file, and subdirectories are separate units. Names arrive qualified by the last path segment (<semiconductors/bjt> binds bjt) unless you write from … import. See Imports.

<math>

Two files, one import. math.hvr is importc "<math.h>" plus extern func declarations covering the C math library end to end — the trigonometrics and their inverses, the hyperbolics, exp/exp2/expm1, the logarithms, pow, sqrt, cbrt, hypot, fabs, erf, tgamma, the rounding family, fmod, fmin/fmax and fma. Import this before using any of them.

physicalmath.hvr is the device-modelling half, written in ordinary Hover and shared by every junction model in the library:

  • limexp(x)exp with its growth capped past a threshold of 80 by a linear extrapolation matching both the value and the slope at the seam, so the function and its derivative stay continuous and Newton meets no new kink. Use it wherever a model's exponential is the suspected source of convergence trouble.
  • pnjlim(v_new, v_old, nvt, v_crit) — SPICE's per-iteration pn-junction limiter, which bounds how far one Newton step may move a junction voltage.
  • jexp(v, nvt), vcrit_of(Is, nvt) — the junction exponential and the critical voltage the limiter needs.
  • q_dep(v, Cj, Vj, Mj, Fc) — depletion charge with the (1 − v/Vj)−Mj law and the Fc forward-bias linearization.
  • rb_of(Rb, Rbm, Irb, ib, qb) — the Gummel-Poon current-dependent base resistance.

In a math-dense analog body, bind the names directly rather than reading math.sin everywhere: from <math> import sin, exp;.

<semiconductors>

  • Diode<Is, N, Rs, Ikf, Isr, Nr, Bv, Ibv, Cjo, Vj, M, Fc, Tt, Vt>[anode, cathode] — a SPICE Level-1 diode card, not a bare Shockley equation. It carries the ohmic Rs to an internal anode node, the high-injection knee Ikf, a separate recombination current (Isr, Nr), reverse breakdown (Bv, Ibv), and both junction (Cjo, Vj, M, Fc) and diffusion (Tt) charge storage, injected as current through ddt(). Parameters are ordinary card values with their usual positive signs; Ikf, Isr, Bv, Cjo and Tt are each disabled by passing 0, and Rs must be greater than zero because R<0> is a short the primitive rejects.

The model is isothermal — Vt is passed in, so the card's Eg/Xti temperature scaling is absent. Its diffusion charge is genuinely hard to start from a zero-state guess — the source-stepping DC solve is what walks it up to a consistent value, and a deck containing one depends on that bias point being reached.

<semiconductors/bjt>

A separate import — <semiconductors> does not pull it in.

  • NPN<…>[base, collector, emitter] and PNP<…>[base, collector, emitter], both full Gummel-Poon: forward and reverse transport with Early voltages (Vaf, Var), high-injection knees (Ikf, Ikr), the two non-ideal leakage currents (Ise/Ne, Isc/Nc), current-dependent base resistance (Rb, Rbm, Irb) plus constant Re and Rc, and both depletion and transit-time charge storage on each junction.

The equations are written at intrinsic nodes bi/ci/ei behind those resistors, so Re is real series feedback rather than a fitting fudge. Not modelled: the Xtf/Itf/Vtf transit-time modulation and the excess-phase parameter Ptf.

<semiconductors/mosfet>

New in this release, and again its own import. Four modules, one file per polarity:

  • NMOS4<…>[gate, drain, source, bulk] and PMOS4<…>[gate, drain, source, bulk] — SPICE Level-1 (square-law) channel current with body effect through GAMMA/PHI and channel-length modulation through LAMBDA, drain and source ohmic resistances to intrinsic nodes di/si, bias-dependent Meyer gate capacitances plus the three overlap terms, and both bulk junctions as full diodes with their own charge storage — which is what gives the part its intrinsic body diode, with no external flyback network needed anywhere.
  • NMOS<…>[gate, drain, source] and PMOS<…>[gate, drain, source] — the three-terminal discrete form, which is the four-terminal module with the bulk tied to the source. The parameter list is identical and passed through untouched, so one part card works against either form.

The channel is physically symmetric, so on Vds < 0 the model swaps the drain and source roles the way SPICE's mode variable does. That matters in any synchronous bridge, which runs current backwards through the channel deliberately — leaving that to the body diode alone would fake a diode drop a real device shorts out. TOX ≤ 0 is read as SPICE's "no oxide information": the intrinsic Meyer capacitances are zeroed and the whole gate capacitance is carried by the overlap terms, which is the convention every discrete part card uses.

<parts>

Ready-made cards for real devices, each a zero-parameter wrapper over one of the models above with the datasheet values filled in and the fit documented in the file's header. The generics are gone, so an instantiation names a part and nothing else. Every subdirectory is its own import.

  • <parts/diode>D1N4001, D1N4007 (mains rectifiers), D1N4148 (small-signal switching, Tt = 20 ns), D1N4733A (5.1 V Zener), D1N5819 (Schottky). Ports [anode, cathode].
  • <parts/bjt/npn>Q2N2222, Q2N3904, QBC547. <parts/bjt/pnp>Q2N2907, Q2N3906, QBC557. Ports [base, collector, emitter].
  • <parts/mosfet/nmos>M2N7000, MBSS138 (logic-level), MIRF540N (100 V power). <parts/mosfet/pmos>MBSS84, MIRF9540N. Ports [gate, drain, source].

<optoelectronics/leds>

optoelectronics has no .hvr files at its own root, so import <optoelectronics>; is an error — write the subdirectory.

  • LED<Is, n, Vt, Vf_clamp, eta>[anode, cathode, light_out]. The diode equation with LED-typical parameters, using pnjlim junction limiting per iteration rather than a hard clamp, because the exponential is much steeper at turn-on. light_out is an informational third port carrying luminous intensity as a voltage, proportional to forward current — illustrative units, not calibrated photometry.
  • Ready-made wrappers: LED_RED, LED_YELLOW, LED_GREEN, LED_BLUE, LED_WHITE, each with no generic parameters.

Both were separate files before 0.8; one import <optoelectronics/leds>; now covers them, and the split is the author's business rather than yours.

<analog/opamp>

  • OpAmp<Rin, gain, Ro>[minus, plus, out] — a behavioural op-amp: an input resistance across the terminals, a VCVS for the gain, and an output resistance in series. Use it when the amplifier is a building block rather than the subject; examples/BJT/opamp.hvr is the transistor-level counterpart.

<electromechanical>

  • PMSM<Rs, Ld, Lq, flux_m, p, J, B>(output omega_m_out, output i_d_out, output i_q_out, output theta_e_out)[va, vb, vc], a permanent-magnet synchronous machine. The mechanical dynamics are modelled as circuit elements — inertia as a capacitance, friction as a conductance — so the rotor state solves in the same MNA system as the windings, and the four output arguments carry speed, the dq currents and electrical angle back out to a controller.

Browse the sources on GitHub.