Skip to main content
Built-in Elements

<breakout />

Overview

A <breakout /> is similar to a <group /> but is meant for situations where you want to guide the autorouter on where connections should exit the group. Inside a breakout you can place <breakoutpoint /> elements to define explicit exit locations, or let tscircuit generate breakout points for connections that leave the breakout.

This 100-pin BGA keeps two 8-bit buses on contiguous outer columns and assigns each bus an explicit fanout direction. Eight center-region balls connect to GND and VCC pours on separate inner layers.

const buses = [
{
name: "DATA",
signals: [
"DATA0",
"DATA1",
"DATA2",
"DATA3",
"DATA4",
"DATA5",
"DATA6",
"DATA7",
],
pins: [20, 30, 40, 50, 60, 70, 80, 90],
targetX: 5.275,
},
{
name: "ADDRESS",
signals: [
"ADDR0",
"ADDR1",
"ADDR2",
"ADDR3",
"ADDR4",
"ADDR5",
"ADDR6",
"ADDR7",
],
pins: [11, 21, 31, 41, 51, 61, 71, 81],
targetX: -5.275,
},
]

const powerDrops = [
{ pin: 44, name: "GND_44", net: "GND" },
{ pin: 45, name: "VCC_45", net: "VCC" },
{ pin: 46, name: "GND_46", net: "GND" },
{ pin: 47, name: "VCC_47", net: "VCC" },
{ pin: 54, name: "VCC_54", net: "VCC" },
{ pin: 55, name: "GND_55", net: "GND" },
{ pin: 56, name: "VCC_56", net: "VCC" },
{ pin: 57, name: "GND_57", net: "GND" },
]

const fanoutExitYs = [
-1.2, -0.625, -0.375, -0.125, 0.125, 0.375, 0.625, 1.2,
]

const bgaPinLabels = Object.fromEntries([
...buses.flatMap((bus) =>
bus.signals.map((signal, index) => [
"pin" + bus.pins[index],
signal,
]),
),
...powerDrops.map((drop) => ["pin" + drop.pin, drop.name]),
])

export default () => (
<board
width="18mm"
height="12mm"
layers={6}
minTraceWidth="0.1mm"
defaultTraceWidth="0.1mm"
minTraceToPadEdgeClearance="0.1mm"
minViaEdgeToPadEdgeClearance="0.1mm"
minViaHoleDiameter="0.2mm"
minViaPadDiameter="0.5mm"
>
<copperpour layer="inner1" connectsTo="net.GND" />
<copperpour layer="inner2" connectsTo="net.VCC" />
<breakout name="BGA_BREAKOUT" width="14mm" height="11mm">
<autoroutingphase
autorouter="fanout"
fanoutRoutingLayers={["top"]}
fanoutBoundaryPadding="1.5mm"
busFanoutDirections={{
DATA: "center_right",
ADDRESS: "center_left",
GND_44: "center_left",
VCC_45: "bottom_center",
GND_46: "bottom_center",
VCC_47: "center_right",
VCC_54: "center_left",
GND_55: "top_center",
VCC_56: "top_center",
GND_57: "center_right",
}}
/>
<chip
name="U1"
footprint="bga100_grid10x10_p0.8mm_pad0.35mm_circularpads"
pinLabels={bgaPinLabels}
/>
{buses.map((bus) => (
<chip
key={"EDGE_" + bus.name}
name={"EDGE_" + bus.name}
pcbX={bus.targetX}
pinLabels={Object.fromEntries(
bus.signals.map((signal, index) => [
"pin" + (index + 1),
signal,
]),
)}
footprint={
<footprint>
{fanoutExitYs.map((pcbY, index) => (
<smtpad
key={"pin" + (index + 1)}
portHints={["pin" + (index + 1)]}
pcbX={0}
pcbY={pcbY}
width="0.4mm"
height="0.1mm"
shape="rect"
/>
))}
</footprint>
}
/>
))}
{buses.map((bus) => (
<bus
key={bus.name}
name={bus.name}
connections={bus.signals.map(
(signal) => bus.name + "_" + signal,
)}
/>
))}
{buses.flatMap((bus) =>
bus.signals.map((signal) => (
<trace
key={signal}
name={bus.name + "_" + signal}
from={"U1." + signal}
to={"EDGE_" + bus.name + "." + signal}
/>
)),
)}
{powerDrops.map((drop) => (
<trace
key={drop.name}
name={drop.name}
from={"U1." + drop.name}
to={"net." + drop.net}
/>
))}
</breakout>
</board>
)
PCB Circuit Preview

The explicit <autoroutingphase /> is needed here because the advanced fanout controls live on the phase. busFanoutDirections sends each named bus toward a specific side and can also guide an individual source trace, as shown for the power balls.

fanoutRoutingLayers={["top"]} reserves the top layer for signal escape. The GND and VCC traces have only one component endpoint, so the fanout router infers their destination layers from the matching <copperpour /> elements and drops them to inner1 and inner2. Those pour layers do not need to appear in fanoutRoutingLayers.

If a net has pours on multiple layers, disambiguate the plane destination with an explicit map:

<autoroutingphase
autorouter="fanout"
fanoutRoutingLayers={["top"]}
fanoutPourNetMap={{ inner1: "GND", inner2: "VCC" }}
/>

Auto-Generated Breakout Points

When traces connect from components inside a <breakout /> to components outside of it, tscircuit can create the needed breakout points automatically. This keeps the breakout local to the component cluster while still letting board-level traces connect to headers and other surrounding parts.

The example below routes a QFP16 controller inside a breakout to an external pin header and nearby passives without adding any manual <breakoutpoint /> elements.

export default () => (
<board width="20mm" height="16mm">
<breakout name="MCU_BREAKOUT" padding="1mm">
<chip
footprint="qfp16"
name="U1"
pinLabels={{
pin1: "GPIO1",
pin2: "GPIO2",
pin3: "GPIO3",
pin4: "GPIO4",
pin5: "VCC",
pin6: "GND",
pin7: "SDA",
pin8: "SCL",
pin9: "RESET",
pin10: "BOOT",
pin11: "GPIO5",
pin12: "GPIO6",
pin13: "GPIO7",
pin14: "GPIO8",
pin15: "GPIO9",
pin16: "GPIO10",
}}
pcbX={0}
pcbY={0}
/>
<capacitor
name="C1"
capacitance="100nF"
footprint="0402"
pcbX={-3.5}
pcbY={2.4}
/>
<trace from="C1.1" to="U1.GPIO1" />
<trace from="C1.2" to="U1.GPIO3" />
</breakout>
<pinheader
name="J1"
pinCount={4}
footprint="pinrow4"
pinLabels={["VCC", "GND", "SDA", "SCL"]}
pcbX={7}
pcbY={0}
pcbRotation={90}
/>
<resistor
name="R1"
resistance="10k"
footprint="0402"
pcbX={-5}
pcbY={-2.4}
connections={{ pin1: "U1.RESET", pin2: "net.VCC" }}
/>
<trace from="J1.VCC" to="U1.VCC" />
<trace from="J1.GND" to="U1.GND" />
<trace from="J1.SDA" to="U1.SDA" />
<trace from="J1.SCL" to="U1.SCL" />
</board>
)
PCB Circuit Preview

Properties

<breakout /> accepts all the layout properties of <group /> plus a few extras:

PropertyDescription
paddingUniform padding around the breakout region.
paddingLeft / paddingRight / paddingTop / paddingBottomControl padding for each side individually.
autorouterAutorouter used to escape components inside the breakout. Defaults to fanout.
fanoutBoundaryPaddingPadding between the source pads and the shared boundary where fanout traces terminate.