"""VLSIR-Compatible Components, Generated with Claude Code"""
import gdsfactory as gf
from gdsfactory.typings import CrossSectionSpec
# Common port layer for schematic-only elements
SCHEM_LAYER = (250, 0)
@gf.cell
def resistor(resistance: float = 1e3, model: str = "rpoly") -> gf.Component:
c = gf.Component()
c.add_port(name="p", center=(0, 0), width=0.1, orientation=180, layer=SCHEM_LAYER)
c.add_port(name="n", center=(1, 0), width=0.1, orientation=0, layer=SCHEM_LAYER)
c.info["model"] = "resistor"
c.info["vlsir"] = {
"model": model,
"spice_type": "RESISTOR",
"spice_lib": None,
"port_order": ["p", "n"],
"port_map": {},
"params": {"r": resistance},
}
return c
@gf.cell
def capacitor(capacitance: float = 1e-12, model: str = "cpoly") -> gf.Component:
c = gf.Component()
c.add_port(name="p", center=(0, 0), width=0.1, orientation=180, layer=SCHEM_LAYER)
c.add_port(name="n", center=(1, 0), width=0.1, orientation=0, layer=SCHEM_LAYER)
c.info["model"] = "capacitor"
c.info["vlsir"] = {
"model": model,
"spice_type": "CAPACITOR",
"spice_lib": None,
"port_order": ["p", "n"],
"port_map": {},
"params": {"c": capacitance},
}
return c
@gf.cell
def inductor(inductance: float = 1e-9, model: str = "lind") -> gf.Component:
c = gf.Component()
c.add_port(name="p", center=(0, 0), width=0.1, orientation=180, layer=SCHEM_LAYER)
c.add_port(name="n", center=(1, 0), width=0.1, orientation=0, layer=SCHEM_LAYER)
c.info["model"] = "inductor"
c.info["vlsir"] = {
"model": model,
"spice_type": "INDUCTOR",
"spice_lib": None,
"port_order": ["p", "n"],
"port_map": {},
"params": {"l": inductance},
}
return c
@gf.cell
def mos(
w: float = 1e-6,
length: float = 100e-9,
nf: int = 1,
model: str = "nmos",
spice_lib: str | None = None,
) -> gf.Component:
c = gf.Component()
c.add_port(name="D", center=(0, 1), width=0.1, orientation=180, layer=SCHEM_LAYER)
c.add_port(name="G", center=(-1, 0), width=0.1, orientation=270, layer=SCHEM_LAYER)
c.add_port(name="S", center=(0, -1), width=0.1, orientation=0, layer=SCHEM_LAYER)
c.add_port(name="B", center=(1, 0), width=0.1, orientation=90, layer=SCHEM_LAYER)
c.info["model"] = "mos"
c.info["vlsir"] = {
"model": model,
"spice_type": "MOS",
"spice_lib": spice_lib,
"port_order": ["D", "G", "S", "B"],
"port_map": {},
"params": {"w": w, "l": length, "nf": nf},
}
return c
@gf.cell
def diode(model: str = "diol", area: float = 1e-12, pj: float = 1e-6) -> gf.Component:
c = gf.Component()
c.add_port(name="p", center=(0, 0), width=0.1, orientation=180, layer=SCHEM_LAYER)
c.add_port(name="n", center=(1, 0), width=0.1, orientation=0, layer=SCHEM_LAYER)
c.info["model"] = "diode"
c.info["vlsir"] = {
"model": model,
"spice_type": "DIODE",
"spice_lib": None,
"port_order": ["p", "n"],
"port_map": {},
"params": {"area": area, "pj": pj},
}
return c
@gf.cell
def bipolar(
model: str = "npn",
spice_lib: str | None = None,
area: float = 1.0,
) -> gf.Component:
c = gf.Component()
c.add_port(name="C", center=(0, 1), width=0.1, orientation=90, layer=SCHEM_LAYER)
c.add_port(name="B", center=(-1, 0), width=0.1, orientation=180, layer=SCHEM_LAYER)
c.add_port(name="E", center=(0, -1), width=0.1, orientation=270, layer=SCHEM_LAYER)
c.add_port(
name="S", center=(1, 0), width=0.1, orientation=0, layer=SCHEM_LAYER
) # substrate
c.info["model"] = "bipolar"
c.info["vlsir"] = {
"model": model,
"spice_type": "BIPOLAR",
"spice_lib": spice_lib,
"port_order": ["C", "B", "E", "S"],
"port_map": {},
"params": {"area": area},
}
return c
@gf.cell
def vsource(dc: float = 0.0, ac: float = 0.0) -> gf.Component:
"""Voltage Source"""
c = gf.Component()
c.add_port(name="p", center=(0, 0), width=0.1, orientation=180, layer=SCHEM_LAYER)
c.add_port(name="n", center=(1, 0), width=0.1, orientation=0, layer=SCHEM_LAYER)
c.info["model"] = "vsource"
c.info["vlsir"] = {
"model": "vsource",
"spice_type": "VSOURCE",
"spice_lib": None,
"port_order": ["p", "n"],
"port_map": {},
"params": {"dc": dc, "ac": ac},
}
return c
@gf.cell
def isource(dc: float = 0.0, ac: float = 0.0) -> gf.Component:
"""Current Source"""
c = gf.Component()
c.add_port(name="p", center=(0, 0), width=0.1, orientation=180, layer=SCHEM_LAYER)
c.add_port(name="n", center=(1, 0), width=0.1, orientation=0, layer=SCHEM_LAYER)
c.info["model"] = "isource"
c.info["vlsir"] = {
"model": "isource",
"spice_type": "ISOURCE",
"spice_lib": None,
"port_order": ["p", "n"],
"port_map": {},
"params": {"dc": dc, "ac": ac},
}
return c
@gf.cell
def vcvs(gain: float = 1.0) -> gf.Component:
"""Voltage-controlled voltage source."""
c = gf.Component()
c.add_port(
name="p_out", center=(0, 1), width=0.1, orientation=90, layer=SCHEM_LAYER
)
c.add_port(
name="n_out", center=(0, -1), width=0.1, orientation=270, layer=SCHEM_LAYER
)
c.add_port(
name="p_ctrl", center=(-1, 0), width=0.1, orientation=180, layer=SCHEM_LAYER
)
c.add_port(
name="n_ctrl", center=(1, 0), width=0.1, orientation=0, layer=SCHEM_LAYER
)
c.info["model"] = "vcvs"
c.info["vlsir"] = {
"model": "vcvs",
"spice_type": "VCVS",
"spice_lib": None,
"port_order": ["p_out", "n_out", "p_ctrl", "n_ctrl"],
"port_map": {},
"params": {"gain": gain},
}
return c
@gf.cell
def vccs(gm: float = 1e-3) -> gf.Component:
"""Voltage-controlled current source."""
c = gf.Component()
c.add_port(
name="p_out", center=(0, 1), width=0.1, orientation=90, layer=SCHEM_LAYER
)
c.add_port(
name="n_out", center=(0, -1), width=0.1, orientation=270, layer=SCHEM_LAYER
)
c.add_port(
name="p_ctrl", center=(-1, 0), width=0.1, orientation=180, layer=SCHEM_LAYER
)
c.add_port(
name="n_ctrl", center=(1, 0), width=0.1, orientation=0, layer=SCHEM_LAYER
)
c.info["model"] = "vccs"
c.info["vlsir"] = {
"model": "vccs",
"spice_type": "VCCS",
"spice_lib": None,
"port_order": ["p_out", "n_out", "p_ctrl", "n_ctrl"],
"port_map": {},
"params": {"gm": gm},
}
return c
@gf.cell
def cccs(gain: float = 1.0) -> gf.Component:
"""Current-controlled current source."""
c = gf.Component()
c.add_port(
name="p_out", center=(0, 1), width=0.1, orientation=90, layer=SCHEM_LAYER
)
c.add_port(
name="n_out", center=(0, -1), width=0.1, orientation=270, layer=SCHEM_LAYER
)
c.add_port(
name="p_ctrl", center=(-1, 0), width=0.1, orientation=180, layer=SCHEM_LAYER
)
c.add_port(
name="n_ctrl", center=(1, 0), width=0.1, orientation=0, layer=SCHEM_LAYER
)
c.info["model"] = "cccs"
c.info["vlsir"] = {
"model": "cccs",
"spice_type": "CCCS",
"spice_lib": None,
"port_order": ["p_out", "n_out", "p_ctrl", "n_ctrl"],
"port_map": {},
"params": {"gain": gain},
}
return c
@gf.cell
def ccvs(rm: float = 1e3) -> gf.Component:
"""Current-controlled voltage source."""
c = gf.Component()
c.add_port(
name="p_out", center=(0, 1), width=0.1, orientation=90, layer=SCHEM_LAYER
)
c.add_port(
name="n_out", center=(0, -1), width=0.1, orientation=270, layer=SCHEM_LAYER
)
c.add_port(
name="p_ctrl", center=(-1, 0), width=0.1, orientation=180, layer=SCHEM_LAYER
)
c.add_port(
name="n_ctrl", center=(1, 0), width=0.1, orientation=0, layer=SCHEM_LAYER
)
c.info["model"] = "ccvs"
c.info["vlsir"] = {
"model": "ccvs",
"spice_type": "CCVS",
"spice_lib": None,
"port_order": ["p_out", "n_out", "p_ctrl", "n_ctrl"],
"params": {"rm": rm},
}
return c
@gf.cell
def tline(z0: float = 50.0, td: float = 1e-9) -> gf.Component:
"""Transmission line."""
c = gf.Component()
c.add_port(name="p1", center=(0, 0), width=0.1, orientation=180, layer=SCHEM_LAYER)
c.add_port(name="n1", center=(0, -1), width=0.1, orientation=180, layer=SCHEM_LAYER)
c.add_port(name="p2", center=(2, 0), width=0.1, orientation=0, layer=SCHEM_LAYER)
c.add_port(name="n2", center=(2, -1), width=0.1, orientation=0, layer=SCHEM_LAYER)
c.info["model"] = "tline"
c.info["vlsir"] = {
"model": "tline",
"spice_type": "TLINE",
"spice_lib": None,
"port_order": ["p1", "n1", "p2", "n2"],
"params": {"z0": z0, "td": td},
}
return c
@gf.cell
def subckt(
model: str,
ports: list[str],
spice_lib: str | None = None,
params: dict | None = None,
) -> gf.Component:
"""Generic subcircuit wrapper."""
c = gf.Component()
c.info["model"] = model
for i, port_name in enumerate(ports):
c.add_port(
name=port_name,
center=(i, 0),
width=0.1,
orientation=0 if i % 2 else 180,
layer=SCHEM_LAYER,
)
c.info["vlsir"] = {
"model": model,
"spice_type": "SUBCKT",
"spice_lib": spice_lib,
"port_order": ports,
"params": params or {},
}
return c
[docs]
@gf.cell
def tline1(
length: float = 100,
width: float = 14,
signal_cross_section: CrossSectionSpec = "topmetal2_routing",
ground_cross_section: CrossSectionSpec = "metal3_routing",
npoints: int = 2,
) -> gf.Component:
"""Returns a straight coplanar transmission line.
Creates a signal straight and a wider ground straight aligned around it.
Args:
length: length of the signal line (um).
width: signal line width (um).
signal_cross_section: cross-section for the signal line.
ground_cross_section: cross-section for the ground line.
npoints: number of points used to draw the straights.
"""
c = gf.Component()
signal = c.add_ref(
gf.c.straight(
length=length,
cross_section=signal_cross_section,
width=width,
npoints=npoints,
)
)
c.add_ports(signal.ports)
ground = c.add_ref(
gf.c.straight(
length=length + 6 * width,
cross_section=ground_cross_section,
width=7 * width,
npoints=npoints,
)
)
ground.move((-3 * width, 0))
return c
[docs]
@gf.cell
def branch_line_coupler(
width: float = 10,
width_coupled: float = 14,
quarter_wave_length: float = 500,
connection_length: float = 100,
signal_cross_section: CrossSectionSpec = "topmetal2_routing",
ground_cross_section: CrossSectionSpec = "metal3_routing",
) -> gf.Component:
"""Returns a branch line coupler using coplanar transmission lines.
Creates a four-port rectangular coupler from quarter-wave transmission
line sections connected at corners.
Args:
width: width of the through lines (um).
width_coupled: width of the coupled (branch) lines (um).
quarter_wave_length: quarter wavelength at the design frequency (um).
connection_length: length of the input/output feed lines (um).
signal_cross_section: cross-section for the signal line.
ground_cross_section: cross-section for the ground line.
"""
c = gf.Component()
signal_layer = gf.get_cross_section(signal_cross_section).layer
corner = gf.Component()
corner.add_polygon(
points=[
(0, 0),
(0, width),
(width - (width_coupled - width), width),
(width, width_coupled),
(width, 0),
],
layer=signal_layer,
)
corner.add_port(
name="e1",
center=(width / 2, 0),
width=width,
orientation=270,
port_type="electrical",
layer=signal_layer,
)
corner.add_port(
name="e2",
center=(width, width_coupled / 2),
width=width_coupled,
orientation=0,
port_type="electrical",
layer=signal_layer,
)
corner.add_port(
name="e3",
center=(0, width / 2),
width=width,
orientation=180,
port_type="electrical",
layer=signal_layer,
)
# top-left corner
corner_nw = c.add_ref(corner)
# top coupled line
tline_top = c.add_ref(
tline1(
length=quarter_wave_length - width,
signal_cross_section=signal_cross_section,
ground_cross_section=ground_cross_section,
width=width_coupled,
)
)
tline_top.connect("e1", corner_nw.ports["e2"])
# top-right corner
corner_ne = c.add_ref(corner).mirror(p1=(0, 0), p2=(0, 1))
corner_ne.connect("e2", tline_top.ports["e2"])
# left through line
tline_left = c.add_ref(
tline1(
length=quarter_wave_length - width_coupled,
signal_cross_section=signal_cross_section,
ground_cross_section=ground_cross_section,
width=width,
)
)
tline_left.connect("e1", corner_nw.ports["e1"])
# bottom-left corner
corner_sw = c.add_ref(corner).mirror(p1=(0, 0), p2=(1, 0))
corner_sw.connect("e1", tline_left.ports["e2"])
# bottom coupled line
tline_bottom = c.add_ref(
tline1(
length=quarter_wave_length - width,
signal_cross_section=signal_cross_section,
ground_cross_section=ground_cross_section,
width=width_coupled,
)
)
tline_bottom.connect("e1", corner_sw.ports["e2"])
# bottom-right corner
corner_se = (
c.add_ref(corner).mirror(p1=(0, 0), p2=(1, 0)).mirror(p1=(0, 0), p2=(0, 1))
)
corner_se.connect("e2", tline_bottom.ports["e2"])
# right through line
tline_right = c.add_ref(
tline1(
length=quarter_wave_length - width_coupled,
signal_cross_section=signal_cross_section,
ground_cross_section=ground_cross_section,
width=width,
)
)
tline_right.connect("e1", corner_ne.ports["e1"])
# input/output feed lines
for port, name in [
(corner_nw.ports["e3"], "e1"),
(corner_ne.ports["e3"], "e2"),
(corner_se.ports["e3"], "e3"),
(corner_sw.ports["e3"], "e4"),
]:
feed = c.add_ref(
tline1(
length=connection_length,
signal_cross_section=signal_cross_section,
ground_cross_section=ground_cross_section,
width=width,
)
)
feed.connect("e1", port)
c.add_port(name=name, port=feed.ports["e2"])
c.move((0, -width))
return c