JITX Component Generation Skill
Generate JITX Python component code from datasheets and specifications.
Environment
Environment setup is handled by the base jitx skill. Ensure it has been invoked first.
Datasheet Handling
ALWAYS save datasheets locally before reading.
When user provides a URL or asks to download a datasheet:
- •Download the PDF using WebFetch
- •Save to
datasheets/<mpn>.pdfin the project (create folder if needed) - •Then use the extraction process in Step 0
This ensures:
- •Datasheet is available for future reference
- •Consistent file paths for extraction scripts
- •No repeated downloads
AVOID REDUNDANT WEB SEARCHES
Once you have the datasheet PDF, extract pinout, package dimensions, and pin descriptions from it using Step 0. Do NOT search for info that's already in the datasheet.
When additional searches ARE appropriate:
- •Datasheet lacks package mechanical drawings (common for simple parts)
- •Complex packages (200+ pins) where cross-referencing helps catch errors
- •Need separate package drawing document (e.g., TI's MPDS files)
When searching:
- •Use manufacturer sites: ti.com, analog.com, st.com, nxp.com, microchip.com, infineon.com, onsemi.com
- •Search pattern:
"<MPN> datasheet" site:<manufacturer>.com - •Avoid distributor sites, random aggregators, or unverified PDFs
Output Location
ALWAYS place components in a components/ folder, even for single components.
Standard Structure
project/
└── src/<namespace>/
└── components/
├── __init__.py
├── <category>/
│ ├── __init__.py
│ └── <manufacturer>_<mpn>.py
└── <category>/
└── ...
If src/<namespace>/ doesn't exist, use:
project/
└── components/
├── __init__.py
└── <manufacturer>_<mpn>.py
Category examples: mcus, connectors, power_linear_regulators, opamp, flash, crystals, leds, logic, timers, buttons, transceivers, diodes_tvs, isolators, power_switchmode
File naming: <manufacturer>_<mpn>.py - lowercase, underscores for spaces/special chars
- •
texas_instruments_NE555.py - •
raspberry_pi_RP2040.py - •
renesas_DA14705.py
Instructions
When generating a JITX component from a datasheet or specification, follow this structured approach:
Step 0: Handle Datasheets (CRITICAL)
NEVER read a full datasheet PDF directly. Even 50-page PDFs consume excessive context.
Always extract relevant pages first using scripts/extract_pages.py:
# Find pages containing keywords python scripts/extract_pages.py datasheet.pdf --find "pinout" "pin description" "dimension" "package" "ball map" "mechanical" # Extract matched pages to a smaller PDF python scripts/extract_pages.py datasheet.pdf --pages 10 11 12 -o datasheet_extract.pdf
Then read only the extracted PDF.
Key pages to find:
- •Pin assignment / ball map (usually pages 10-20)
- •Pin description table
- •Package mechanical drawing (usually near end)
- •Ordering information
If pymupdf not available, ask user to provide:
- •Pin count and package type
- •Screenshot of pinout/ball map
- •Package dimensions (body size, pitch, ball/lead size)
Do NOT just read the PDF and hope for the best - this will exhaust context.
Step 1: Extract Key Information
IMPORTANT: Multiple Packages/Variants
If the datasheet covers multiple package options or component variants, use AskUserQuestion to ask the user which one to model:
Example: "The datasheet shows 3 package options for this part: - SOIC-8 (NE555DR) - PDIP-8 (NE555P) - VSSOP-8 (NE555DGKR) Which package would you like me to model?"
Do NOT assume or pick one arbitrarily. Ask first.
From the datasheet (or extracted pages), extract:
- •Component identification: Manufacturer, MPN, description
- •Package type: SOIC, SOT, QFN, BGA, SON, etc.
- •Pin count: Total number of pins
- •Pin functions: Pin names and functions from pinout table (see Pin Naming below)
- •Package dimensions:
- •Body width/length (D, E dimensions)
- •Body height (A dimension)
- •Lead span (E1/D1 or terminal span)
- •Lead pitch (e dimension)
- •Lead width (b dimension)
- •Lead length (L dimension)
Step 2: Select Package Generator
Use this decision tree to select the appropriate generator:
Is it a 2-sided package?
├── Yes, ≤6 pins → SOT23_3, SOT23_5, or SOT23_6
├── Yes, >6 pins with gull-wing leads → SOIC
├── Yes, >6 pins with flat leads (no-lead) → SON
└── No (4-sided or array)
├── 4-sided gull-wing leads → QFP
├── 4-sided flat/no-lead → QFN
├── Bottom ball array → BGA
└── Custom/unusual → Manual Landpattern
Step 3: Generate Component Code
Use this template structure:
"""
{Manufacturer} {MPN} - {Description}
Component definition for the {full description}.
"""
import jitx
from jitx import PadMapping
from jitx.net import Port
from jitx.toleranced import Toleranced
from jitxlib.symbols.box import BoxSymbol, PinGroup, Row, Column
# Import appropriate landpattern generator:
# from jitxlib.landpatterns.generators.soic import SOIC, SOIC_DEFAULT_LEAD_PROFILE
# from jitxlib.landpatterns.generators.sot import SOT23_3, SOT23_5, SOT23_6, SOTLeadProfile
# from jitxlib.landpatterns.generators.qfn import QFN, QFNLead
# from jitxlib.landpatterns.generators.son import SON, SONLead
# from jitxlib.landpatterns.generators.bga import BGA
from jitxlib.landpatterns.leads import LeadProfile
from jitxlib.landpatterns.package import RectanglePackage
class {ComponentClassName}(jitx.Component):
"""Brief description of the component."""
mpn = "{MPN}"
manufacturer = "{Manufacturer}"
reference_designator_prefix = "U" # or "Q" for transistors, etc.
datasheet = "{datasheet_url}"
# Define ports for each pin
# Single pins:
VCC = Port()
GND = Port()
# Pin arrays (for many similar pins):
GPIO = [Port() for _ in range(N)]
# Landpattern definition
landpattern = (
{Generator}(num_leads=N)
.lead_profile(...)
.package_body(...)
# Optional: .thermal_pad(...)
)
# Symbol definition
symbol = BoxSymbol(
rows=Row(
left=PinGroup(...),
right=PinGroup(...),
),
columns=Column(
up=PinGroup(...), # Power pins typically go up
down=PinGroup(...), # Ground pins typically go down
),
)
# For non-standard pin ordering, add explicit mapping in __init__:
def __init__(self):
lp = self.landpattern
self.mappings = [PadMapping({
self.PIN1: [lp.p[1]],
self.PIN2: [lp.p[2]],
# ...
})]
Device: type[{ComponentClassName}] = {ComponentClassName}
Package-Specific Examples
For complete examples of each package type (SOIC, SON, QFN, BGA), including thermal pads, port arrays, inactive positions, and non-uniform BGA grids, see references/package-examples.md.
Dimension Mapping Reference
| Datasheet Symbol | Description | JITX Parameter |
|---|---|---|
| D | Package length | RectanglePackage.length |
| E | Package width | RectanglePackage.width |
| A | Package height | RectanglePackage.height |
| E1 / D1 | Lead span | LeadProfile.span |
| e | Lead pitch | LeadProfile.pitch |
| b | Lead width | SMDLead.width / QFNLead.width |
| L | Lead length | SMDLead.length / QFNLead.length |
| D2 / E2 | Thermal pad size | .thermal_pad(rectangle(D2, E2)) |
Common Patterns
Toleranced Values
Toleranced.min_max(3.8, 4.0) # Min-max range (most common) Toleranced(5.0, 0.1) # Nominal ± tolerance Toleranced.min_typ_max(0.13, 0.18, 0.23) # Asymmetric Toleranced.exact(7.0) # BSC = Basic
Thermal Pad with Paste Subdivision
from jitx.shapes.composites import rectangle
from jitxlib.landpatterns.pads import SMDPadConfig, WindowSubdivide
.thermal_pad(
shape=rectangle(3.0, 3.0),
config=SMDPadConfig(paste=WindowSubdivide(padding=0.25)),
)
Reference Designator Prefixes
- •
U- Integrated circuits - •
Q- Transistors (MOSFETs, BJTs) - •
D- Diodes - •
R- Resistors - •
C- Capacitors - •
L- Inductors - •
J- Connectors - •
Y- Crystals/oscillators
Multi-Unit Symbols
Multiple BoxSymbol attributes = separate visual boxes:
def __init__(self):
self.symbol_a = BoxSymbol(rows=Row(
left=PinGroup(self.INp[0], self.INn[0]),
right=PinGroup(self.OUT[0]),
))
self.symbol_b = BoxSymbol(rows=Row(
left=PinGroup(self.INp[1], self.INn[1]),
right=PinGroup(self.OUT[1]),
))
# Power unit: use horizontal layout (left=supplies, right=grounds)
self.symbol_power = BoxSymbol(
rows=Row(
left=PinGroup(self.VCC, self.VBAT),
right=PinGroup(self.VSS, self.GND),
),
)
Pin Naming Best Practices
Use real functional names from the datasheet, not generic placeholders:
# GOOD - from datasheet OQSPIF_D0 = Port() # Octal QSPI Flash data bit 0 eMMC_CMD = Port() # eMMC command line V18F = Port() # 1.8V flash supply # BAD - generic P0 = Port() # What does P0 do? VDD1 = Port() # Which power domain?
PadMapping Requirements
- •Automatic mapping (no PadMapping needed): Ports mapped to pads in declaration order.
- •Explicit PadMapping required when:
- •Thermal pad exists (map to
lp.thermal_pads[0]) - •Ports declared out of pin order
- •Multiple ports map to same pad
- •Pin 1 is not the first declared port
- •Thermal pad exists (map to
Verification Process
Test Harness
import jitx
from jitx.container import inline
from jitx.sample import SampleDesign
from .component import Device
class TestDesign(SampleDesign):
@inline
class circuit(jitx.Circuit):
dut = Device()
Build Command
python -m jitx build <module>.TestDesign
Success: status: ok
Failure: Python traceback or status: error
Output files (in designs/<design_name>/):
- •
cache/netlist.json- Verify net connections - •
design-info/stable.design- Design snapshot
Common Build Errors
| Error | Fix |
|---|---|
port X not mapped to symbol pin | Add port to BoxSymbol |
port X not mapped to pad | Check port count = pad count |
No pad configuration specified | BGA needs .pad_config(SMDPadConfig()) |
Verification Report
After generating code, provide:
## Verification Report ### Pin Count - Datasheet: N pins - Generated: N ports - Status: ✓ MATCH / ✗ MISMATCH ### Pad Count - Landpattern: N pads + M thermal - Ports requiring pads: N + M - Status: ✓ MATCH / ✗ MISMATCH ### Dimensions | Parameter | Datasheet | Generated | Status | |-----------|-----------|-----------|--------| | Width | 3.8-4.0mm | min_max(3.8, 4.0) | ✓ | ### Issues Found - [List any discrepancies or assumptions made]
Step 6: Capture Application Circuit (Optional)
After generating component code, check the datasheet for "Typical Application", "Reference Design", or "Application Circuit" sections. These provide valuable circuit templates.
When to offer:
- •Datasheet includes a schematic with the component
- •User is creating a power IC, amplifier, or other circuit-centric component
- •Application circuit shows passive values and connections
Process:
- •
Ask user if they want to capture the application circuit:
code"The datasheet includes a Typical Application circuit (Figure X). Would you like me to also generate the application circuit code?"
- •
If yes, invoke the
jitx-circuit-builderskill to generate circuit code - •
Pass context to circuit-builder:
- •Component class name and import path
- •Datasheet figure reference
- •Component values from schematic (cap values, resistor values, inductor specs)
- •Pin connections shown in the schematic
Example application circuit output:
"""
Texas Instruments TPS62933DRLR Application Circuit
From datasheet Figure 23 - Typical Application
3.8-V to 30-V input, 3.3V 3A output buck converter.
"""
from jitx import Circuit, Net
from jitx.common import Power
from jitxlib.parts import Capacitor, CapacitorQuery, Resistor, Inductor, ResistorQuery
from jitxlib.voltage_divider import VoltageDividerConstraints, voltage_divider_from_constraints
from .texas_instruments_TPS62933DRLR import TPS62933DRLR
class TPS62933DRLRCircuit(Circuit):
"""Buck converter application circuit per datasheet Figure 23."""
vin = Power() # Input power (3.8V-30V)
vout = Power() # Output power (3.3V)
def __init__(self, output_voltage=3.3):
self.GND = Net(name="GND")
self.VOUT = Net(name="VOUT")
self.VIN = Net(name="VIN")
# Main IC
self.buck = TPS62933DRLR()
# Power connections
self.VIN += self.vin.Vp + self.buck.VIN
self.GND += self.buck.GND + self.vin.Vn + self.vout.Vn
# Input capacitors (C1, C2 - 10µF each per schematic)
with CapacitorQuery.refine(type="ceramic", case="0805"):
for _ in range(2):
Capacitor(capacitance=10e-6, rated_voltage=50.0).insert(
self.buck.VIN, self.GND, short_trace=True
)
# Feedback voltage divider
vdiv_cons = VoltageDividerConstraints(
v_in=output_voltage, v_out=0.8, current=0.8/10e3,
base_query=ResistorQuery(case=["0402"])
)
self.fb_div = voltage_divider_from_constraints(vdiv_cons)
self.VOUT += self.fb_div.hi + self.vout.Vp
self.GND += self.fb_div.lo
self.nets = [self.fb_div.out + self.buck.FB]
# Output inductor and capacitors
self.L = Inductor(inductance=4.7e-6, current_rating=3.9)
# ... complete circuit per datasheet
File location: Save application circuits alongside the component:
components/ ├── power_switchmode/ │ ├── texas_instruments_TPS62933DRLR.py # Component │ └── texas_instruments_TPS62933DRLR_circuit.py # Application circuit
Output Format
When generating a component, provide:
- •Complete Python source code in a code block
- •Verification report (using format above)
- •Any assumptions or decisions made
- •Known limitations or items requiring manual review
- •Offer to capture application circuit if datasheet includes one