MicroSpice
MicroSpice is a very simple circuit simulator that simulates an electronic circuit composed a variety of passive components. This circuit can be constructed using a subset of standard Spice netlist syntax.
As an example, here is a simple RLC circuit with in
as input and out
as output
L1 in out 100nH
R1 out gnd 50Ω
C1 out gnd 100nF
Currently the only supported components are resistors (R), inductors (L) and capacitors (C). Component values can be specified using standard SI prefixes such as k
(kilo = 1e3), M
(Mega=1e6), G
(giga=1e9), m
(milli=1e-3), μ
(micro=1e-6), n
(nano=1e-9), or p
(pico=1e-12). In addition, the non-standard forms u
(micro=1e-6) and meg
(Mega=1e6) are also allowed for Spice compatibility.
Units including H (Henry), F (Farad) and Ω (ohm) are allowed, but are optional. If you do use a unit, the unit must match the type of component. Thus, you can specify the value of a resistor as 50Ω
but claiming that is the value of a capacitor would be an error.
Component values can also be a reference to a parameter. For instance, we could modify the circuit above to parameterize the value of the inductor and capacitor:
L1 in out $L
R1 out gnd 50Ω
C1 out gnd $C
To simulate this circuit, we have to provide these values. More on how to use this later
Running a Simulation
A Netlist
describes an abstract circuit. To simulate that circuit, the circuit is turned into a matrix equation consisting of complex admittances that relate the voltages and currents in the circuit. In this conversion, the voltages for any subset of nodes can be forced to a particular value and currents can be injected into any nodes that are not set to a voltage. The result of the voltages and all of the node-to-node currents are then computed.
In normal practice, the internals of this conversion are hidden from view. All you need to do is provide a Netlist
and circuit parameters and you get a simulation function that takes a frequency, a vector of voltages and returns a vector of output voltages. You can call that simulation function repeatedly for different frequencies or different inputs.
Taking the circuit given above, if we take node in
as the input, node out
as the output and gnd
as the ground reference, we can simulate the voltage transfer function for this circuit with this code:
using MicroSpice
nl = MicroSpice.Netlist("L1 in out 100nH\nR1 out gnd 50Ω\nC1 out gnd 100nF\n",
[], [:in, :gnd], ["out"])
s = MicroSpice.solve(nl)
decibel(x) = 20 * log10(abs(x))
[decibel(only(s(f, [1, 0], []))) for f in [1.4e6, 1.5e6, 1.62e6, 1.8e6]]
# output
4-element Vector{Float64}:
12.883077832402897
18.914298710446417
27.65586909592151
11.05634871505561
Circuit parameters
If you have component values that are parameter references (such as $L
in the example above), the values of the parameters must be supplied when you solve the circuit. Even before that, though, when you construct the Netlist
, you need to provide the names of the parameters that you will be providing later as a list. This list also specifies the order in which you will provide the values later.
Here is an example with the circuit from before but with parameters for the inductor and capacitor. Note the use of a raw string for the circuit definition to avoid needing to quote the $
before the parameter names.
using MicroSpice
nl = MicroSpice.Netlist(raw"""
L1 in out $L
R1 out gnd 50Ω
C1 out gnd $C
""", ["L", "C"], [:in, :gnd], ["out"])
decibel(x) = 20 * log10(abs(x))
[
decibel(only(MicroSpice.solve(nl)(f, [1, 0], params)))
for f in [1.0e6, 1.2e6, 1.4e6, 1.62e6, 1.8e6, 2.0e6],
params in [[100e-9, 100e-9], [200e-9, 50e-9], [120e-9, 100e-9]]
]
# output
6×3 Matrix{Float64}:
4.35992 4.35431 5.57245
7.29487 7.279 9.94251
12.8831 12.8055 22.5545
27.6559 25.2887 12.2341
11.0563 10.9722 5.42304
4.73621 4.71178 0.958959
In this example, the Netlist
is defined and all parameters, inputs and outputs are bound to symbol names. The circuit parameters are passed to the solve
function to get a simulation function and that function is given the frequency of interest and the circuit inputs to get the resulting output voltages.
MicroSpice.InternalExpression
MicroSpice.Link
MicroSpice.Netlist
MicroSpice.Netlist
MicroSpice.Netlist
MicroSpice.coil
MicroSpice.decode
MicroSpice.inputImpedance
MicroSpice.raw
MicroSpice.solve
MicroSpice.toroid
MicroSpice.transfer
MicroSpice.xc
MicroSpice.xl
MicroSpice.InternalExpression
— TypeAn InternalExpression is a sum of a numerical value and references into a value vector that will be provided at simulation time.
MicroSpice.Link
— TypeA Link is a composite of pure resistance, inductance and capacitance arranged in parallel.
To simplify combining multiple links, resistance and inductance are retained in inverse form (i.e. 1/R, 1/L).
MicroSpice.Netlist
— TypeA circuit is defined as a set of nodes connected by admittances. Each node may be set to a particular voltage, or can have a current injected or it can be free-floating. This is modeled as a linear system of equations in terms of the n
nodal voltages of which m
are externally constrained, and k
injected currents. The first n
of these equations define the relationship between node voltages and injected currents and have of rank n-1
. The next m
equations define externally set voltages followed by k
equations for injected currents. We assume that imposed voltages and injected currents are on different nodes so this gives a rank of n + m + k - 1
so far. There are an additional n-m-k
equations that set all remaining injected currents to zero and a final constraint that sets the sum of all injected currents to zero.
A Netlist
is normally constructed by parsing a Spice compatible netlist that defines the ideal components that connect the nodes in the circuit. The first step in solving a circuit is to bind values to any symbolically defined component values in the circuit. The second step is to define a frequency of interest and the circuit inputs to get a vector of outputs. Because the underlying matrices are part of the Netlist
structure itself, solving a circuit is not thread-safe.
MicroSpice.Netlist
— MethodReads some input and parses that input as a netlist
MicroSpice.Netlist
— MethodA netlist is defined as a set of nodes which are connected by ideal resistors, inductors and capacitors. Such a netlist can be resolved into a ComplexCircuit at any desired frequency by replacing the inductors and capacitors by their equivalent complex impedances at that frequency.
Constructs a Netlist from a Spice circuit. As an example, here is a simple RLC circuit with in
as input and out
as output
L1 in out 100nH
R1 out gnd 50Ω
C1 out gnd 100nF
Currently the only supported components are resistors (R), inductors (L) and capacitors (C). Component values can be specified using standard SI prefixes such as k
(kilo = 1e3), M
(Mega=1e6), G
(giga=1e9), m
(milli=1e-3), μ
(micro=1e-6), n
(nano=1e-9), or p
(pico=1e-12). In addition, the non-standard forms u
(micro=1e-6) and meg
(Mega=1e6) are used for Spice compatibility.
Units including H (Henry), F (Farad) and Ω (ohm) are allowed, but are optional, but only the correct unit type is allowed.f
Solving proceeds in two steps. In the first step, any symbolically defined component values are bound to specific values to get a function to solve the bound circuit. In the second step, the circuit is solved for a specific frequency and vector of input voltages.
nl = MicroSpice.Netlist("L1 in out 100n
R1 out gnd 50
C1 out gnd 100n
", [], [:in, :gnd], [:out])
s = MicroSpice.solve(nl)
decibel(x) = 20 * log10(abs(x))
[decibel(only(s(f, [1, 0], []))) for f in [1.4e6, 1.5e6, 1.62e6, 1.8e6]]
# output
4-element Vector{Float64}:
12.883077832402897
18.914298710446417
27.65586909592151
11.05634871505561
MicroSpice.coil
— MethodInductance in nH of an air-core coil with n turns d mm in diameter and l mm long
MicroSpice.decode
— FunctionParses a numerical value with SI multiplier (and variants like u instead of μ)
MicroSpice.inputImpedance
— FunctionReturns a function that takes a frequency and computes the impedance of a circuit between the two inputs. It is assumed that there are two inputs, but ignores the outputs.
MicroSpice.raw
— MethodGiven a Netlist
return a function that will solve the circuit for all voltages and injected currents given frequency, inputs and circuit parameters.
The function that is returned takes the frequency, inputs and parameter values and returns a vector of the n output voltages and n injected currents.
MicroSpice.solve
— MethodGiven a Netlist
and the parameters defining component values in that circuit, solve
returns a function that simulates a circuit. The arguments of the returned function are frequency and the values of the circuit parameters. The returned value is a vector of the output voltages.
MicroSpice.toroid
— MethodReturns the inductance in nH for a specified core and number of turns. Throws ErrorException
if the core is unknown.
MicroSpice.transfer
— FunctionReturns a function that computes the voltage transfer function of a ciruit with an input, a reference voltage and an output at a particular frequency.
MicroSpice.xc
— MethodComplex reactance of a capacitor at a given frequency
MicroSpice.xl
— MethodComplex reactance of an inductor at a given frequency