Understanding JITX Object Relationships#

This guide explains the relationships between key JITX objects that often confuse newcomers: Port, Pin, Pad, Component, Circuit, Net, and TopologyNet.

The Three Layers#

JITX models electronics at three distinct layers:

Layer

Purpose

Key Objects

Logical

Electrical connectivity

Port, Net, TopologyNet

Schematic

Visual representation

Symbol, Pin

Physical

PCB layout

Landpattern, Pad

Port vs Pin vs Pad#

These three objects represent the same electrical connection point at different abstraction levels:

Port (Logical Layer)#

A Port is the fundamental connectivity element. It represents an electrical signal that can be connected to other ports.

from jitx import Port

class MyComponent(Component):
    VCC = Port()      # Single signal port
    GND = Port()
    DATA = Port()

Ports can be grouped into bundles for related signals:

class I2C(Port):
    """Bundle of related signals"""
    sda = Port()
    scl = Port()

class MyComponent(Component):
    i2c = I2C()  # Bundle port containing sda and scl

Pin (Schematic Layer)#

A Pin is a connection point on a schematic Symbol. Pins define where wires connect visually in the schematic.

from jitx import Symbol, Pin

class MySymbol(Symbol):
    vcc_pin = Pin.up((0, 2), length=1)      # Pin extending upward
    gnd_pin = Pin.down((0, -2), length=1)   # Pin extending downward
    data_pin = Pin.right((2, 0), length=2)  # Pin extending right

Pad (Physical Layer)#

A Pad is a copper area on a Landpattern (footprint) where a component lead is soldered.

from jitx import Landpattern, Pad
from jitx.shapes.primitive import Circle

class MyPad(Pad):
    shape = Circle(diameter=1.0)  # 1mm circular pad

class MyLandpattern(Landpattern):
    p1 = MyPad().at(-1.27, 0)  # Pad at position (-1.27, 0)
    p2 = MyPad().at(1.27, 0)   # Pad at position (1.27, 0)

How They Connect#

A Component links all three layers together:

Component
├── Ports (logical connections)
├── Symbol (schematic representation)
│   └── Pins (visual connection points)
├── Landpattern (physical footprint)
│   └── Pads (solder points)
├── SymbolMapping (Port ↔ Pin)
└── PadMapping (Port ↔ Pad)
class Resistor(Component):
    # Logical layer: Ports
    p = Port(), Port()

    # Schematic layer: Symbol
    symbol = ResistorSymbol()

    # Physical layer: Landpattern
    landpattern = SMD0402()

    # Mappings are automatic by declaration order,
    # or explicit with PadMapping/SymbolMapping

Circuit vs Component#

Both are containers, but serve different purposes:

Component#

A Component represents a physical part that will be placed on the PCB:

  • Has a landpattern (footprint)

  • Has a symbol for schematics

  • Appears in the Bill of Materials (BOM)

  • Examples: resistor, capacitor, IC, connector

class LED(Component):
    anode = Port()
    cathode = Port()
    landpattern = SMD0603LED()
    symbol = LEDSymbol()

Circuit#

A Circuit is a logical grouping of components and sub-circuits:

  • No physical footprint of its own

  • Used for hierarchy and organization

  • Can contain other Circuits (sub-circuits)

  • Examples: power supply module, filter block, interface circuit

class PowerSupply(Circuit):
    vin = Power()   # Input port
    vout = Power()  # Output port

    regulator = VoltageRegulator()
    input_cap = Capacitor()
    output_cap = Capacitor()

    def __init__(self):
        self.nets = [
            self.vin.Vp + self.input_cap.p[1] + self.regulator.vin,
            # ... more connections
        ]

Net vs TopologyNet#

Both represent electrical connections, but with different constraints:

Net (Simple Connection)#

A Net is an unordered electrical connection. Use it for:

  • Power and ground connections

  • Connections where routing order doesn’t matter

# Using the + operator creates a Net
vcc_net = power.Vp + regulator.vin + capacitor.p[1]
gnd_net = power.Vn + regulator.gnd + capacitor.p[2]

TopologyNet (Ordered Connection)#

A TopologyNet is an ordered connection. Use it for a daisy chain whose order is part of the design, such as a DDR flyby clock or address bus that visits each memory in turn:

# Using the >> operator creates a TopologyNet
# The address line visits dram0, then dram1
a0_chain = ctrl.a0 >> dram0.a0 >> dram1.a0

High-speed signals that run from one end to the other, such as USB, Ethernet or PCIe pairs, use ordinary nets. Their timing, loss and skew constraints name the two ends of the path; see Signal Integrity Constraints.

When to Use Each#

Scenario

Use

Power rails

Net (+)

Ground connections

Net (+)

Simple GPIO

Net (+)

USB data lines

Net (+)

Ethernet pairs

Net (+)

Point-to-point high-speed clocks

Net (+)

DDR flyby clock and address bus

TopologyNet (>>)

Visual Summary#

Design
├── Board (physical outline)
├── Substrate (PCB stackup)
└── Circuit (root)
    ├── Ports (external interface)
    ├── Components
    │   ├── Ports
    │   ├── Symbol → Pins
    │   └── Landpattern → Pads
    ├── Sub-Circuits
    │   └── (recursive structure)
    └── Nets / TopologyNets (connections)

Common Patterns#

Accessing Component Pads#

# Via landpattern
component.landpattern.p[1]  # First pad
component.landpattern.p[2]  # Second pad

# For generators like SOIC
soic_component.landpattern.p[1]   # Pad 1
soic_component.landpattern.p[14]  # Pad 14

Connecting Bundles#

class MyCircuit(Circuit):
    mcu = MCU()
    sensor = Sensor()

    def __init__(self):
        # Connect entire I2C bundle at once
        i2c = self.mcu.require(I2C)
        self.i2c_bus = i2c + self.sensor.i2c

Mapping Multiple Pads to One Port#

class PowerIC(Component):
    VCC = Port()
    GND = Port()

    landpattern = QFN32()

    # Map GND port to multiple pads (thermal pad + pin)
    mapping = PadMapping({
        GND: [landpattern.p[9], landpattern.thermal_pad],
        VCC: landpattern.p[1],
    })

See Also#