Skip to content

[SKiDL Feature Request] LLM Analysis tool #240

@shanemmattner

Description

@shanemmattner

I opened up this draft PR but I'm posting here for visibility.

I've been using LLM's to check my circuit theory and help with circuit design and PCB design in general. I thought SKiDL's python based circuit descriptions would work great with LLM's. So far the results seem to be promising, but it's clear that I need to include more information on each subcircuit, part, and connections for the LLM to give better analysis.

@devbisme if you think it's worth adding to SKiDL it'll keep working on it. I just made a basic example that I only tested with Claude so far.

Here's an example output analysis file:
subcircuits_analysis.txt
From running this code:

from skidl import *
import os

@subcircuit
def rc_filter(inp, outp, gnd):
    """RC low-pass filter"""
    r = Part("Device", 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', value='10K')
    c = Part("Device", 'C', footprint='Capacitor_SMD:C_0805_2012Metric', value='0.1uF')
    inp += r[1]
    r[2] += c[1]
    c[2] += gnd
    outp += r[2]

@subcircuit
def input_protection(inp, outp, gnd):
    """Input protection and bulk capacitance"""
    d_protect = Part("Device", 'D',
                    footprint='Diode_SMD:D_SOD-123',
                    value='1N4148W')
    c_bulk = Part("Device", 'C',
                  footprint='Capacitor_THT:CP_Radial_D10.0mm_P5.00mm',
                  value='100uF')
    
    inp += d_protect['A']
    outp += d_protect['K']
    inp += c_bulk[1]
    gnd += c_bulk[2]

@subcircuit
def voltage_regulator(inp, outp, gnd):
    """5V voltage regulator with decoupling caps"""
    reg = Part("Regulator_Linear", "LM7805_TO220",
               footprint="Package_TO_SOT_THT:TO-220-3_Vertical")
    cin = Part("Device", 'C', footprint='Capacitor_SMD:C_0805_2012Metric', value='10uF')
    cout = Part("Device", 'C', footprint='Capacitor_SMD:C_0805_2012Metric', value='10uF')
    inp += cin[1], reg['VI']
    cin[2] += gnd
    reg['GND'] += gnd
    reg['VO'] += cout[1], outp
    cout[2] += gnd

@subcircuit
def voltage_divider(inp, outp, gnd):
    """Basic voltage divider subcircuit"""
    r1 = Part("Device", 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', value='1K')
    r2 = Part("Device", 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', value='500')
    inp += r1[1]
    r1[2] += r2[1]
    r2[2] += gnd
    outp += r1[2]

@subcircuit
def output_termination(inp, gnd):
    """Output termination resistor"""
    r_term = Part("Device", 'R',
                  footprint='Resistor_SMD.pretty:R_0805_2012Metric',
                  value='100K')
    inp += r_term[1]
    gnd += r_term[2]

@subcircuit
def power_section(raw_in, reg_out, filt_out, gnd):
    """Power section with regulation and filtering"""
    protected_in = Net()
    input_protection(raw_in, protected_in, gnd)
    voltage_regulator(protected_in, reg_out, gnd)
    rc_filter(reg_out, filt_out, gnd)

@subcircuit
def double_divider(inp, outp, gnd):
    """Two voltage dividers in series with termination"""
    mid = Net()
    voltage_divider(inp, mid, gnd)
    voltage_divider(mid, outp, gnd)
    output_termination(outp, gnd)

@subcircuit
def complete_circuit():
    """Top level circuit connecting all subcircuits"""
    vin = Net()
    vreg = Net()
    vfilt = Net()
    vout = Net()
    gnd = Net()

    power_section(vin, vreg, vfilt, gnd)
    double_divider(vfilt, vout, gnd)

# Create the complete circuit
complete_circuit()

# Analyze each subcircuit separately using the new function
results = default_circuit.analyze_subcircuits_with_llm(
    api_key=os.getenv("ANTHROPIC_API_KEY"),
    output_file="subcircuits_analysis.txt"
)

# Print analysis results
if results["success"]:
    print("\nAnalysis Results:")
    for hier, analysis in results["subcircuits"].items():
        print(f"\nSubcircuit: {hier}")
        if analysis["success"]:
            print(f"Analysis completed in {analysis['request_time_seconds']:.2f} seconds")
            print(f"Tokens used: {analysis['prompt_tokens'] + analysis['response_tokens']}")
        else:
            print(f"Analysis failed: {analysis['error']}")
            
    print(f"\nTotal analysis time: {results['total_time_seconds']:.2f} seconds")
    print(f"Total tokens used: {results['total_tokens']}")
else:
    print(f"\nOverall analysis failed: {results.get('error', 'Unknown error')}")

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions