Skip to content

SPICE to pic.yml Conversion

This notebook demonstrates converting a SPICE netlist to gdsfactory's pic.yml format using the spice_to_pic_yml converter. We use the Mixer5GHz design from IHP's April 2025 tapeout as a worked example.

The converter maps each SPICE subcircuit model to its corresponding IHP PDK component and translates parameters (e.g. dimensions from metres to µm).

Requirements:

  • IHP PDK: uv pip install ihp-gdsfactory
import sys
sys.path.insert(0, '.')

from pathlib import Path

from spice_to_pic_yml import convert_file

Input: SPICE netlist

The SPICE netlist from the April 2025 tapeout describes the schematic with IHP device models (sg13_lv_nmos, rppd, cap_cmim, etc.) and their parameters.

spice_file = Path('TO_Apr2025/Mixer5GHz.spice')
print(spice_file.read_text())
** sch_path: /home/angel/Code/IHP/Mixer5GHz.sch
**.subckt Mixer5GHz RFN RFP VDC IFP IFN GND IDC OSCN OSCP VCC ICC GND
*.iopin RFN
*.iopin RFP
*.iopin VDC
*.iopin IFP
*.iopin IFN
*.iopin GND
*.iopin IDC
*.iopin OSCN
*.iopin OSCP
*.iopin VCC
*.iopin ICC
*.iopin GND
XM6 RFN LON net2 GND sg13_lv_nmos w=60.0u l=0.13u ng=10
XRL2 VDC RFN sub! rppd w=4.50e-6 l=3.20e-6 m=1 b=0
XRL1 VDC RFP sub! rppd w=4.50e-6 l=3.20e-6 m=1 b=0
XM8 RFN LOP net3 GND sg13_lv_nmos w=60.0u l=0.13u ng=10
XM7 RFP LON net3 GND sg13_lv_nmos w=60.0u l=0.13u ng=10
XM5 RFP LOP net2 GND sg13_lv_nmos w=60.0u l=0.13u ng=10
XM4 net3 IFN net1 GND sg13_lv_nmos w=90.0u l=0.13u ng=15
XM3 net2 IFP net1 GND sg13_lv_nmos w=90.0u l=0.13u ng=15
XM2 IDC IDC GND GND sg13_lv_nmos w=120.0u l=0.13u ng=20
XM1 net1 IDC GND GND sg13_lv_nmos w=120.0u l=0.13u ng=20
XM11 LOP LON net4 GND sg13_lv_nmos w=90.0u l=0.13u ng=15
XM12 LON LOP net4 GND sg13_lv_nmos w=90.0u l=0.13u ng=15
XM9 IDC IDC GND GND sg13_lv_nmos w=120.0u l=0.13u ng=20
XM10 net4 IDC GND GND sg13_lv_nmos w=120.0u l=0.13u ng=20
XC1 VDC LOP cap_cmim w=11.745e-6 l=9.445e-6
XR1 VDC LOP sub! rppd w=4.4e-6 l=1.5e-6 m=1 b=0
XC2 VDC LON cap_cmim w=11.745e-6 l=9.445e-6
XR2 VDC LON sub! rppd w=4.4e-6 l=1.5e-6 m=1 b=0
XM13 OSCP OSCN net5 GND sg13_lv_nmos w=90.0u l=0.13u ng=15
XM14 OSCN OSCP net5 GND sg13_lv_nmos w=90.0u l=0.13u ng=15
XM15 ICC ICC GND GND sg13_lv_nmos w=120.0u l=0.13u ng=20
XM16 net5 ICC GND GND sg13_lv_nmos w=120.0u l=0.13u ng=20
XC3 VCC OSCP cap_cmim w=19.1e-6 l=10.7e-6
XR3 VCC OSCP sub! rppd w=4.35e-6 l=1.5e-6 m=1 b=0
XC4 VCC OSCN cap_cmim w=19.1e-6 l=10.7e-6
XR4 VCC OSCN sub! rppd w=4.35e-6 l=1.5e-6 m=1 b=0
L3 VCC OSCP 2.006n
L1 VDC LOP 2.006n
L2 VDC LON 2.006n
L4 VCC OSCN 2.006n
**.ends
.end

Convert to pic.yml

convert_file parses the netlist, applies the IHP component mappings, and writes a pic.yml with component instances arranged on a regular grid.

output_file = Path('/tmp/Mixer5GHz.pic.yml')
convert_file(spice_file, output_file)
Parsing SPICE netlist: TO_Apr2025/Mixer5GHz.spice
Found 30 instances
Converting to pic.yml format...
Writing to /tmp/Mixer5GHz.pic.yml
✓ Conversion complete!

Summary:
  - 30 components
  - 30 placements
print(output_file.read_text())
name: circuit
instances:
  XM6:
    component: nmos
    settings:
      width: 60.0
      length: 0.13
      nf: 10
      model: sg13_lv_nmos
  XRL2:
    component: rppd
    settings:
      dx: 4.5
      dy: 3.2
      model: rppd
  XRL1:
    component: rppd
    settings:
      dx: 4.5
      dy: 3.2
      model: rppd
  XM8:
    component: nmos
    settings:
      width: 60.0
      length: 0.13
      nf: 10
      model: sg13_lv_nmos
  XM7:
    component: nmos
    settings:
      width: 60.0
      length: 0.13
      nf: 10
      model: sg13_lv_nmos
  XM5:
    component: nmos
    settings:
      width: 60.0
      length: 0.13
      nf: 10
      model: sg13_lv_nmos
  XM4:
    component: nmos
    settings:
      width: 90.0
      length: 0.13
      nf: 15
      model: sg13_lv_nmos
  XM3:
    component: nmos
    settings:
      width: 90.0
      length: 0.13
      nf: 15
      model: sg13_lv_nmos
  XM2:
    component: nmos
    settings:
      width: 120.0
      length: 0.13
      nf: 20
      model: sg13_lv_nmos
  XM1:
    component: nmos
    settings:
      width: 120.0
      length: 0.13
      nf: 20
      model: sg13_lv_nmos
  XM11:
    component: nmos
    settings:
      width: 90.0
      length: 0.13
      nf: 15
      model: sg13_lv_nmos
  XM12:
    component: nmos
    settings:
      width: 90.0
      length: 0.13
      nf: 15
      model: sg13_lv_nmos
  XM9:
    component: nmos
    settings:
      width: 120.0
      length: 0.13
      nf: 20
      model: sg13_lv_nmos
  XM10:
    component: nmos
    settings:
      width: 120.0
      length: 0.13
      nf: 20
      model: sg13_lv_nmos
  XC1:
    component: cmim
    settings:
      width: 11.745
      length: 9.445
  XR1:
    component: rppd
    settings:
      dx: 4.4
      dy: 1.5
      model: rppd
  XC2:
    component: cmim
    settings:
      width: 11.745
      length: 9.445
  XR2:
    component: rppd
    settings:
      dx: 4.4
      dy: 1.5
      model: rppd
  XM13:
    component: nmos
    settings:
      width: 90.0
      length: 0.13
      nf: 15
      model: sg13_lv_nmos
  XM14:
    component: nmos
    settings:
      width: 90.0
      length: 0.13
      nf: 15
      model: sg13_lv_nmos
  XM15:
    component: nmos
    settings:
      width: 120.0
      length: 0.13
      nf: 20
      model: sg13_lv_nmos
  XM16:
    component: nmos
    settings:
      width: 120.0
      length: 0.13
      nf: 20
      model: sg13_lv_nmos
  XC3:
    component: cmim
    settings:
      width: 19.1
      length: 10.7
  XR3:
    component: rppd
    settings:
      dx: 4.35
      dy: 1.5
      model: rppd
  XC4:
    component: cmim
    settings:
      width: 19.1
      length: 10.7
  XR4:
    component: rppd
    settings:
      dx: 4.35
      dy: 1.5
      model: rppd
  L3:
    component: inductor2
    settings:
      inductance: 2.006e-09
  L1:
    component: inductor2
    settings:
      inductance: 2.006e-09
  L2:
    component: inductor2
    settings:
      inductance: 2.006e-09
  L4:
    component: inductor2
    settings:
      inductance: 2.006e-09
placements:
  XM6:
    x: 0.0
    y: 0.0
  XRL2:
    x: 100.0
    y: 0.0
  XRL1:
    x: 200.0
    y: 0.0
  XM8:
    x: 300.0
    y: 0.0
  XM7:
    x: 400.0
    y: 0.0
  XM5:
    x: 0.0
    y: 100.0
  XM4:
    x: 100.0
    y: 100.0
  XM3:
    x: 200.0
    y: 100.0
  XM2:
    x: 300.0
    y: 100.0
  XM1:
    x: 400.0
    y: 100.0
  XM11:
    x: 0.0
    y: 200.0
  XM12:
    x: 100.0
    y: 200.0
  XM9:
    x: 200.0
    y: 200.0
  XM10:
    x: 300.0
    y: 200.0
  XC1:
    x: 400.0
    y: 200.0
  XR1:
    x: 0.0
    y: 300.0
  XC2:
    x: 100.0
    y: 300.0
  XR2:
    x: 200.0
    y: 300.0
  XM13:
    x: 300.0
    y: 300.0
  XM14:
    x: 400.0
    y: 300.0
  XM15:
    x: 0.0
    y: 400.0
  XM16:
    x: 100.0
    y: 400.0
  XC3:
    x: 200.0
    y: 400.0
  XR3:
    x: 300.0
    y: 400.0
  XC4:
    x: 400.0
    y: 400.0
  XR4:
    x: 0.0
    y: 500.0
  L3:
    x: 100.0
    y: 500.0
  L1:
    x: 200.0
    y: 500.0
  L2:
    x: 300.0
    y: 500.0
  L4:
    x: 400.0
    y: 500.0

Next steps

The generated pic.yml can be loaded with gf.read.from_yaml() once all component parameters are within the PDK's accepted ranges. The file is also a starting point for manual refinement of placements and connections before tape-out.