The Netlist (.cnl) Format
A circuitRF netlist is a human-readable text description of a circuit and what to simulate. It's the same thing the schematic editor produces internally, and it's what the engine actually runs.
What a netlist is, and why you'd use one
Most users never write a netlist by hand — you draw a schematic and press Run, and circuitRF
extracts the netlist for you. But the .cnl file is worth understanding because:
It is human-readable and diff-friendly — you can read, review, and version-control a design as text.
It is the engine's input contract: the schematic, the CLI, and the engine all meet here. The headless CLI runs a
.cnldirectly — every verb butemtakes one.It's the clearest way to see exactly what got simulated — components, parameter values after resolution, analyses, and measurements, all in one place.
Syntax basics: one statement per line; ; begins a comment (to end of line); whitespace separates
tokens; values may carry a unit (50 Ohm, 2 GHz, 1 mF); and expressions may reference
variables and parameters.
A complete example
This is a single-FET GaN power-amplifier test bench: a harmonic-balance power sweep, swept again over frequency, with measurements for gain, efficiency, and return loss. We'll walk through every line below.
; netlist.cnl — generated from TestBench "HBTest.csch"
define MyFET (gate drain)
parameters Periphery_mm=1
Sv = -0.837
Sc = 0.71
TV0 = 4.268
TC = 1.507
th = 0.001
a = 0.176
g = 0.089
lam = 0.0012
B = 1130
SDD:X1 gate 0 drain 0 I[1,0]=_v1/50 I[2,0]=Periphery_mm*(B*TC*tanh(_v2*a*(tanh(g*(TV0 - _v1 + _v2*th + Sc*ln(exp(-(Sv - _v1)/Sc) + 1)))+1))*ln(exp(-(2*TV0 - 2*_v1 +2*_v2*th + 2*Sc*ln(exp(-(Sv - _v1)/Sc) + 1))/TC) + 1) * (_v2*lam + 1))/2
end MyFET
Pin = 0
RFfreq = 2 GHz
C:C1 Vin n1 C=1 mF
L:L1 n2 n3 L=1 mH
L:L2 n4 Vout L=1 mH
R:R2 n5 0 R=80 Ohm
C:C2 n5 n6 C=1 mF
P1Tone:P1 n1 0 Pavl=Pin dBm Z=50 Ohm Freq=RFfreq Phase=0 deg Z[0]=1 Ohm Z[2]=30 Ohm
Vdc:V1 n2 0 Vdc=-3.05 V
Vdc:V2 VDD 0 Vdc=48 V
MyFET:X1 n3 Vout Periphery_mm=1
IProbe:Iout Vout n6
IProbe:Iin Vin n3
IProbe:IDC VDD n4
C:C3 Vout 0 C=0.3 pF
analysis HB1 type=hb Tone="RFfreq" ToneUnit=MHz MaxHarm=5 FFTOverSample=1 Tol=1e-6 DriveStepping=IfNecessary GuardHarmonic=0 Lambda=1 MaxIter=100
analysis HB1_sweep_Pin type=parametric_sweep Var=Pin Start=0 Stop=30 Step=1 Inner=HB1
analysis HB1_sweep_RFfreq type=parametric_sweep Var=RFfreq Start=1 Stop=3 Npts=3 Unit=GHz Inner=HB1_sweep_Pin
measure Pin_avail_dBm = Pin
measure Pin_deliv_W = real(0.5*HB1.V("Vin",1)*conj(HB1.I("Iin",1)))
measure Pin_deliv_dBm = 10*log10(Pin_deliv_W*1000)
measure IRL_dB = Pin_deliv_dBm - Pin_avail_dBm; input return loss
measure Pout_W = real(0.5*HB1.V("Vout",1)*conj(HB1.I("Iout",1)))
measure Pout_dBm = 10*log10(Pout_W*1000)
measure Gp_dB = Pout_dBm - Pin_deliv_dBm ; power
measure Gt_dB = Pout_dBm - Pin_avail_dBm ; transducer
measure PDC_W = real(HB1.V("VDD",0)*HB1.I("IDC",0))
measure Eff = Pout_W/PDC_W*100
labelednets VDD Vin Vout
Line-by-line walkthrough
1 · Header comment
; netlist.cnl — generated from TestBench "HBTest.csch"
Any line starting with ; is a comment. When circuitRF generates the netlist from a schematic it
stamps a provenance line naming the source test bench. Comments are ignored by the engine.
2 · Cell definition (define … end)
define MyFET (gate drain)
parameters Periphery_mm=1
Sv = -0.837
...
SDD:X1 gate 0 drain 0 I[1,0]=_v1/50 I[2,0]=Periphery_mm*(...)
end MyFET
A define block declares a reusable cell — here a GaN FET model named MyFET with two ports,
gate and drain. Inside:
parameters Periphery_mm=1— the cell's parameter interface with a default. An instance can override it (andX1below does). Parameters pass top-down: the override is evaluated in the parent's scope, then used inside the cell.Sv = -0.837,Sc = 0.71, … — local variables (model coefficients) scoped to this cell. They feed the device equations.SDD:X1 gate 0 drain 0 …— a Symbolically-Defined Device: you write the port currents as equations and circuitRF differentiates them automatically for the solver. The four nets are two differential ports: port 1 =gate–0, port 2 =drain–0. In the equations, _v1 and _v2 are those two port voltages.I[1,0]=_v1/50— the current into port 1 (a simple 50 Ω gate input);I[2,0]=…— the drain current, the GaN I–V law scaled byPeriphery_mm. The index notation isI[port, weight]— weight0is the current itself. (The SDD equation grammar is covered under Components › SDD.)
Everything inside define … end is a template. It isn't simulated until it's
instanced at the top level (see MyFET:X1 below). The lines outside any
define block are the top-level test bench.
3 · Global variables
Pin = 0
RFfreq = 2 GHz
Top-level global variables, usable anywhere a value is expected. They're also sweepable —
and both are swept by the analyses below (Pin is the drive level, RFfreq the fundamental). A
variable may carry a unit (2 GHz, 48 V, 10 dBm, 50 Ohm); when it does, that unit wins
wherever the variable is referenced.
Both kinds work here: the ones that scale a number (GHz, mF,
pH) and the ones that only name a quantity (V, A,
W, dBm, Ohm, deg). Before circuitRF 1.0
VDS = 48 V was a parse error while RFfreq = 2 GHz was fine; the two
are the same thing now.
The unit is only ever read off the end of something that is not already a valid
expression, so an expression whose last token happens to spell a unit is left alone —
x = 2 * f is a multiplication, not two femtoseconds.
4 · Components & instances
C:C1 Vin n1 C=1 mF
L:L1 n2 n3 L=1 mH
...
P1Tone:P1 n1 0 Pavl=Pin dBm Z=50 Ohm Freq=RFfreq Phase=0 deg Z[0]=1 Ohm Z[2]=30 Ohm
Vdc:V1 n2 0 Vdc=-3.05 V
Vdc:V2 VDD 0 Vdc=48 V
MyFET:X1 n3 Vout Periphery_mm=1
IProbe:Iout Vout n6
...
Each line is Type:Name net1 net2 … key=value …. The first tokens after the name are the nets
the component's pins connect to (order = the component's pin order); the key=value tokens are
parameters. Nets named 0 are ground. Reading the key lines:
C:C1 Vin n1 C=1 mF— a capacitor between netsVinandn1. The large1 mFcaps and1 mHchokes here are DC-block / bias-feed elements.P1Tone:P1 …— the RF power source driving the input.Pavl=Pin dBmsets the available power from the sweptPinvariable;Freq=RFfreqtakes the fundamental fromRFfreq;Z=50 Ohmis the fundamental source impedance.Z[0]=1 OhmandZ[2]=30 Ohmset the source termination at the baseband (DC) and 2nd-harmonic zones — harmonic source-pull terminations.Vdc:V1 n2 0 Vdc=-3.05 VandVdc:V2 VDD 0 Vdc=48 V— the gate and drain DC bias supplies (fed to the device through theLchokes).MyFET:X1 n3 Vout Periphery_mm=1— an instance of theMyFETcell: gate→n3, drain→Vout, with thePeriphery_mmparameter overridden (here to the same value as the default).IProbe:Iout Vout n6— a 0 V series current probe (ammeter). Its instance name (Iout,Iin,IDC) is how measurements read its branch current, e.g.I("Iout", 1)below.VProbe:Vg n3— a one-terminal voltage probe. It stamps nothing: the elaborator reads the one net it names and publishes that net's voltage under the probe's own instance name, soV("Vg")reads it and the trace picker lists it. On a net the schematic never named, extraction has already written the probe's name as the NET's name — you will seeVProbe:Vg Vg— and there is one row in the results; on a net a label already named, the probe's name is a second name for it and both appear. Its name must not collide with a net name or with another VProbe: either refuses the run. A VProbe naming a net nothing else reaches reports nothing and says so.
5 · Analyses (HB + parametric sweeps)
analysis HB1 type=hb Tone="RFfreq" ToneUnit=MHz MaxHarm=5 FFTOverSample=1 Tol=1e-6 DriveStepping=IfNecessary GuardHarmonic=0 Lambda=1 MaxIter=100
analysis HB1_sweep_Pin type=parametric_sweep Var=Pin Start=0 Stop=30 Step=1 Inner=HB1
analysis HB1_sweep_RFfreq type=parametric_sweep Var=RFfreq Start=1 Stop=3 Npts=3 Unit=GHz Inner=HB1_sweep_Pin
The first line is the harmonic-balance analysis; the next two wrap it in swept variables. Each
analysis line is analysis Name type=… key=value …. The HB settings:
| Setting | Meaning |
|---|---|
| Tone | The fundamental tone — here the variable RFfreq. |
| ToneUnit | Unit applied to the tone value when it doesn't carry its own (a unit on the variable wins). |
| MaxHarm | Highest harmonic order kept in the spectrum (5 → DC + 5 harmonics). |
| FFTOverSample | Time-grid oversampling factor for the nonlinear FFT (1 = minimum). |
| Tol | Newton convergence tolerance on the harmonic-balance residual. |
| DriveStepping | Power/source continuation: IfNecessary ramps the drive only when a direct solve won't converge. |
| GuardHarmonic | Extra guard harmonic(s) beyond MaxHarm for aliasing safety (0 = none). |
| Lambda | Newton damping factor (1 = full step). |
| MaxIter | Maximum Newton iterations per solve point. |
The two parametric_sweep lines compose by Inner=: HB1_sweep_Pin runs HB1 at each Pin
from 0 to 30 dBm in 1-dB steps (31 points); HB1_sweep_RFfreq runs that whole power sweep at
each of 3 frequencies from 1 to 3 GHz (Npts=3, Unit=GHz). The result is a 3-frequency ×
31-power harmonic-balance sweep — frequency is the outer (slow) axis, power the inner.
A parametric_sweep never changes the inner analysis; it re-runs it across a variable.
Nest them with Inner= to sweep more than one variable. The innermost non-sweep analysis
(HB1) is what each point actually solves.
What a directive may say
type= takes one of six tokens, and each one has a fixed set of keys:
type= |
Verb that runs it | Keys it must have |
|---|---|---|
dc |
dc |
(none) |
sparam |
sparam |
start, stop |
hb |
hb |
Tone, or Tone[1] for a multi-tone run |
loadpull |
lp |
Tone, LoadTuner, SourceTuner, Grid |
loadpull_pursuit |
lpp |
Tone, LoadTuner, SourceTuner |
parametric_sweep |
(the inner analysis's) | Var, Inner, and either Values or Start+Stop |
A key circuitRF does not recognise is refused, by name, with the legal ones listed — and so is a
type= token it does not recognise. Every missing required key is reported at once rather than one
per run. Before 1.0 an unrecognised key was accepted and thrown away in silence, so a directive could
check clean and then run something quite different from what it said.
The schematic editor's own key names are accepted as aliases, since a natural way to write a
directive is to copy them out of a saved .csch: an Lp/Lpp/Psa prefix and an
Expr/Name/Path suffix are stripped, so LpLoadTunerName= is LoadTuner= and PsaVarName= is
Var=. So are the editor's short type tags — sp, lp, lpp, sweep.
Frequency units on a sparam directive
A frequency may state its unit three ways, and they mean the same thing:
analysis SP1 type=sparam start=0.5 GHz stop=6 GHz npts=551
analysis SP1 type=sparam start=0.5 stop=6 npts=551 Unit=GHz
analysis SP1 type=sparam start="0.5" startUnit=GHz stop="6" stopUnit=GHz npts=551
Unit= sets startUnit, stopUnit and stepUnit together; any of the three given individually
wins over it. A bare number with no unit anywhere is hertz.
Unit= used to be read by parametric_sweep and silently ignored by
sparam, so the second line above swept 0.5 Hz to 6 Hz. It reported
no error at any stage, and the S11 it produced was flat and entirely plausible-looking — the
terminations' DC reflection coefficient, nine orders of magnitude from the band that was asked
for. If you have a .cnl written against the old behaviour that deliberately relied
on the unit being dropped, it will now sweep the band it states.
An exported Touchstone file's declared unit follows its data, so a header saying # GHz above a
first column reading 5E-10 is no longer possible. A file that was read keeps the unit its own
option line declared.
Wiring, and how many nets a part takes
The nets on an instance line come before the first key=value, and the count has to match the
part. A line with the wrong number is refused, naming the type, the instance and both counts:
Tuner:T1 is wired to 1 net, and a Tuner takes 2. Add the missing net before the
first 'name=value' on the line.
A part's net count is not always the pin count its schematic symbol draws — several parts have an
implicit reference terminal. Port, Term and Tuner each take two nets (signal and reference)
where the glyph shows one pin; SDD and Z_Port take two per port; an ideal system block such as
Atten or Coupler takes two per RF port. circuitrf reference components states the net count for
each part beside its pin count.
A short instance line used to produce either Index was outside the bounds of the
array — which named nothing — or, on a Tuner, no error at all: the run
completed, reported ok, and gave a circuit whose bias tee delivered nothing.
Yes-and-no parameters
A parameter that is a switch — BiasTee, RefPin, RefNode, IncludeCapacitance, GroundPlane,
OpVars — accepts on/true/yes/1 and off/false/no/0, in any case. Anything else is
refused by name. Before 1.0 BiasTee accepted the literal on and nothing else, so BiasTee=true
was read as off without a word.
6 · Measurements
measure Pin_avail_dBm = Pin
measure Pin_deliv_W = real(0.5*HB1.V("Vin",1)*conj(HB1.I("Iin",1)))
measure Pout_W = real(0.5*HB1.V("Vout",1)*conj(HB1.I("Iout",1)))
measure PDC_W = real(HB1.V("VDD",0)*HB1.I("IDC",0))
measure Eff = Pout_W/PDC_W*100
measure IRL_dB = Pin_deliv_dBm - Pin_avail_dBm; input return loss
A measure line computes a named result from an expression, evaluated at every sweep point.
Expressions use the same engine as everywhere else, plus accessors into the run's data:
HB1.V("Vin", 1)— the voltage at netVinfrom analysisHB1, at harmonic 1 (the fundamental).HB1.I("Iin", 1)is the current through probeIinat the fundamental. Harmonic0is DC — used forPDC_W.real(0.5·V·conj(I))is average power into a port;Pout_W/Pin_deliv_Wapply it at the output and input.Effis drain efficiency in percent.Measurements can reference earlier measurements (
IRL_dBusesPin_deliv_dBmandPin_avail_dBm).A trailing
; texton a measure line is a comment/label (e.g.; input return loss).
Results land in the run dataset and plot like any other signal. (Authored on a schematic, these come from a MEAS component — see Components › MEAS.)
7 · Labeled nets
labelednets VDD Vin Vout
Records which nets the user explicitly named (versus auto-numbered nodes like n1). The Data
Display uses this to default its node picker to the meaningful nets, so you see VDD, Vin, and
Vout first rather than every internal node.
See also: Simulations for the full analysis settings and algorithms · Components for each part and its parameters · New User's Guide for a gentler introduction.