Products #

A Product is what you're testing — a PCB, module, or device. Product specs define the physical interface and electrical characteristics that need to be tested.

Product Specification #

Product specs are defined in YAML files, in products/{product_id}.yaml:

# products/power_board.yaml
id: power_board
name: "5V to 3.3V Converter"
part_number: "DPB-001"
revision: "A"
 
pins:
  VIN:
    name: "J1.1"
    net: "VIN_5V"
    role: power
  VOUT:
    name: "J1.3"
    net: "VOUT_3V3"
    role: signal
characteristics:
  input_voltage:
    direction: input       # DUT receives this
    function: dc_voltage
    units: V
    pins: [VIN]
    bands:
      - value: 5.0
        accuracy:
          pct_reading: 10  # ±10% tolerance
 
  output_voltage:
    direction: output      # DUT provides this
    function: dc_voltage
    units: V
    pins: [VOUT]
    bands:
      - value: 3.3
        accuracy:
          pct_reading: 5   # ±5% tolerance

Pins #

Pins represent physical connection points on the DUT — connectors, test points, or pads.

pins:
  VIN:
    name: "J1.1"           # Physical designator
    net: "VIN_5V"          # Schematic net name
    role: power
  VOUT:
    name: "J1.3"
    net: "VOUT_3V3"
    role: signal
  SDA:
    name: "J2.1"
    net: "I2C_SDA"
    role: signal

Pin Types #

RoleDescription
signalGeneral measured/stimulated signal (default)
groundCurrent return / reference
powerPower input/output (VIN, VOUT)
referenceVoltage reference, not driven

Characteristics #

Characteristics are measurable properties of the product. Each characteristic has:

  • Direction — Does the DUT provide or receive this?
  • Domain — What physical quantity? (voltage, current, etc.)
  • Signal types — DC, AC, pulsed?
  • Conditions — Expected values and tolerances

Direction Matters #

The direction field describes the DUT's perspective:

DirectionMeaningInstrument Needs
inputDUT receives power/signalInstrument must source
outputDUT provides power/signalInstrument must measure
bidirDUT both receives and providesInstrument must do both

Multiple Characteristics Per Pin #

A single pin can have multiple characteristics:

pins:
  VOUT:
    name: "J1.3"
    role: signal
characteristics:
  output_voltage:
    pins: [VOUT]
    direction: output
    function: dc_voltage
    units: V
    bands:
      - value: 3.3
        accuracy:
          pct_reading: 5
 
  output_ripple:
    pins: [VOUT]           # Same pin, different measurement
    direction: output
    function: ac_voltage
    units: mV
    bands:
      - value: 0
        accuracy:
          absolute: 50

Specifications with Conditions #

Each characteristic has one or more specs (SpecBands) that define expected values at specific operating conditions:

characteristics:
  output_voltage:
    direction: output
    function: dc_voltage
    units: V
    pins: [VOUT]
    bands:
      - when:
          temperature: {min: 0, max: 50}
          load: {min: 0.1, max: 0.5}
        value: 3.3
        accuracy:
          pct_reading: 5     # ±5% tolerance
 
      - when:
          temperature: {min: 50, max: 85}
          load: {min: 0.5, max: 1.0}
        value: 3.3
        accuracy:
          pct_reading: 7     # Wider tolerance at high temp

Accuracy Options #

FieldDescription
pct_readingPercentage of the measured value
pct_rangePercentage of the full range
absoluteFixed absolute tolerance value

Multiple accuracy components can be combined (e.g., pct_reading: 1.0, absolute: 0.01 means ±(1% of reading + 0.01)).

Signal Groups (Buses) #

Group related signals for protocols like I2C, SPI, or UART:

pins:
  SDA:
    name: "J2.1"
    role: signal
  SCL:
    name: "J2.2"
    role: signal
signal_groups:
  i2c_main:
    protocol: i2c
    signals:
      - pin: SDA
        role: data
      - pin: SCL
        role: clock
    parameters:
      frequency: 400000

Minimal Spec #

The simplest spec that works:

id: minimal_board
name: "Minimal Example"
 
pins:
  VOUT:
    name: "J1.1"
 
characteristics:
  output_voltage:
    direction: output
    function: dc_voltage
    units: V
    pins: [VOUT]
    bands:
      - value: 5.0
        accuracy:
          pct_reading: 10

Part Numbers #

The part_number field maps a product to its manufacturing part number. When present, it automatically populates dut_part_number in test results (dut_part_number is the operator-facing identifier — the printed/scanned part number — as opposed to the internal product_id; see how-to/traceability). Overridable via --dut-part-number on the CLI. This enables yield analytics filtering by part number.

id: power_board
part_number: "DPB-001"
name: "5V to 3.3V Converter"

Variant Inheritance #

Product families can share specs using the base field. A variant inherits all fields from its base product and overrides specific sections:

# products/power_board_industrial.yaml
id: power_board_industrial
base: power_board              # Inherits from products/power_board.yaml
part_number: "DPB-001-IND"
name: "5V to 3.3V Converter (Industrial)"
 
# Omitted sections (pins, signal_groups) are inherited from base.
# Sections that ARE present replace the base entirely:
characteristics:
  output_voltage:
    direction: output
    function: dc_voltage
    units: V
    pins: [VOUT]
    bands:
      - value: 3.3
        accuracy:
          pct_reading: 3          # Tighter tolerance for industrial

Inheritance rules:

  • Header fields (name, description, revision, part_number, datasheet, schematic) — inherited when absent in variant
  • Sections (pins, characteristics, signal_groups) — variant replaces entirely if present, otherwise inherited
  • id and base always come from the variant
  • Max inheritance depth: 5 levels. Circular references raise an error.

Loading Products #

In Python:

from litmus.store import load_product
 
product = load_product("products/power_board.yaml")
print(product.id)
# Nominal lives on each SpecBand, not on the characteristic itself.
# Resolve the right band for the current operating point:
char = product.characteristics["output_voltage"]
band = char.get_spec_at({"temperature": 25, "load": 0.5})
if band is not None:
    print(band.value)

Next Steps #