Examples
Divider
A voltage divider with a capacitor across its output: two resistors, one cap and nothing else. It is here to show the shape of a Fang program and no more than that.
The program
Section titled “The program”divider.py declares three surfaces (supply, output,
ground) and three parts, then joins them in architecture. The >> operator
is the only way parts get connected, and every connection is an entity in the
graph rather than a line in a file:
top = Resistor(resistance=10 * kOhm, package="R_0603_1608Metric")
def architecture(self): self.top.p2 >> self.bottom.p1The two constraints say what the divider is not allowed to be: a leg under 1 kOhm. They do not restate the values written above them. That is the distinction the whole language rests on. A value is a choice, and a constraint is the reason the choice is allowed.
What comes out
Section titled “What comes out”4 parts, 2 nets, 28 entities, 2 checks, none failed and none undecided. This is the only example with nothing undecided in it, because it is the only one with no missing datasheet number anywhere.
out/divider.net: the KiCad netlistout/netlist.txt: the same projection as textout/checks.txt: both checks, both decidedout/graph.txt: 28 entities, by kind
The two resistors are drawn by the name they have in the program, top and
bottom, because Resistor twice would not tell you which one is which.
Running it
Section titled “Running it”fang check examples/divider/divider.pyfang netlist examples/divider/divider.pyfang export examples/divider/divider.py -o divider.netfang view examples/divider/divider.py interconnect -o interconnect.svgThe whole program
Section titled “The whole program”"""A voltage divider with a decoupling capacitor: the smallest real board."""
from fang.lang import Electrical, System, V, kOhm, require, uFfrom fang.parts import Capacitor, Resistor
class Divider(System): """Two resistors dividing a rail, with a capacitor across the output."""
supply = Electrical() output = Electrical() ground = Electrical()
top = Resistor(resistance=10 * kOhm, package="R_0603_1608Metric") bottom = Resistor(resistance=4.7 * kOhm, package="R_0603_1608Metric") filter_cap = Capacitor( capacitance=100 * uF, voltage_rating=16 * V, package="C_0805_2012Metric" )
def architecture(self): self.top.p2 >> self.bottom.p1 self.bottom.p1 >> self.filter_cap.p1 self.bottom.p2 >> self.filter_cap.p2
def constraints(self): # A divider that draws more than a milliamp from a sensing rail is # usually a mistake; both legs stay well above that. require(self.top.resistance >= 1 * kOhm) require(self.bottom.resistance >= 1 * kOhm)The files it writes
Section titled “The files it writes”The parts, then the nets and the pads on them.
C1 100 uF Package:C_0805_2012MetricR1 4.7 kOhm Package:R_0603_1608MetricR2 10 kOhm Package:R_0603_1608MetricNet-(C1-Pad1) C1.1 R1.1 R2.2Net-(C1-Pad2) C1.2 R1.2Every check that ran, and every one left undecided.
2 checks, 0 failed, 0 undecidedWhat the elaborated graph contains, by entity kind.
1 block 3 component 6 connection 2 constraint 1 interface 6 pin 9 port 28 totalsnapshot sha256:b9a24e84abebf4babb93d22dc622212f4474a266e4aece5ab4a8ff9395205c21All of it, including the KiCad netlist, is in
examples/divider/out/. Rebuild it with:
fang build examples/divider/divider.py