Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 52 additions & 3 deletions cspdk/_schematic.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

from __future__ import annotations

from collections.abc import Callable

from kfactory.schematic import DSchematic

# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -146,6 +148,48 @@
]


def _die_ports(
ngratings: int = 14,
npads: int = 31,
with_loopback: bool = True,
grating_coupler: object = "grating_coupler_rectangular",
**_ignored: object,
) -> list[dict]:
"""Symbol ports for ``die_with_pads``, derived from its kwargs.

Side is the die edge each port sits on — opposite of the GDS orientation,
which points into the die. Within each side the order follows the
nyanlib->Mosaic bridge convention (left bottom->top, right top->bottom,
top left->right, bottom right->left) so symbol labels match the layout.

The loopback absorbs the two edge gratings, so ngratings-2 ports are
exposed per W/E edge when ``with_loopback`` is set; ``npads`` pads per
N/S edge.
"""
ports: list[dict] = []
if grating_coupler:
n = ngratings - 2 if with_loopback else ngratings
if n > 0:
# o1..o(n) right edge bottom->top, o(n+1)..o(2n) left edge top->bottom
ports += [
{"name": f"o{i}", "side": "right", "type": "photonic"}
for i in range(n, 0, -1)
]
ports += [
{"name": f"o{i}", "side": "left", "type": "photonic"}
for i in range(2 * n, n, -1)
]
ports += [
{"name": f"e{i}", "side": "bottom", "type": "electric"}
for i in range(npads, 0, -1)
]
ports += [
{"name": f"e{i}", "side": "top", "type": "electric"}
for i in range(2 * npads, npads, -1)
]
return ports


# ---------------------------------------------------------------------------
# Schematic builder
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -213,13 +257,18 @@ def _make_schematic(
def schematic(
symbol: str,
tags: list[str],
ports: list[dict],
ports: list[dict] | Callable[..., list[dict]],
models: list[dict] | None = None,
):
"""Return a ``schematic_function`` closure for use with ``@gf.cell``."""
"""Return a ``schematic_function`` closure for use with ``@gf.cell``.

``ports`` may be a static list or a callable receiving the component's
kwargs, for parameter-dependent port sets.
"""

def _schematic_fn(**kwargs) -> DSchematic:
return _make_schematic(symbol, tags, ports, models)
resolved_ports = ports(**kwargs) if callable(ports) else ports
return _make_schematic(symbol, tags, resolved_ports, models)

return _schematic_fn

Expand Down
6 changes: 6 additions & 0 deletions cspdk/si220/cband/_schematic.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
_RING_DOUBLE,
_WIRE_BEND,
_WIRE_STRAIGHT,
_die_ports,
sax_model,
schematic,
)
Expand Down Expand Up @@ -184,3 +185,8 @@
# Pads / via stacks
pad_schematic = schematic("pad", ["pad"], _PAD)
via_stack_schematic = schematic("pad", ["via", "stack"], _PAD)

# Die: symbol "die" makes editors render it as a die (no background box).
# Ports are derived from the factory kwargs; each side is the die edge the
# port sits on — opposite of the inward-pointing GDS orientation.
die_schematic = schematic("die", ["die"], _die_ports)
4 changes: 2 additions & 2 deletions cspdk/si220/cband/cells/die_with_pads.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Size,
)

from cspdk.si220.cband._schematic import pad_schematic
from cspdk.si220.cband._schematic import die_schematic, pad_schematic
from cspdk.si220.cband.tech import LAYER


Expand Down Expand Up @@ -104,7 +104,7 @@ def die(size: tuple[float, float] = (16000.0, 1 * 3000.0)) -> gf.Component:
return c


@gf.cell(tags=["die"])
@gf.cell(tags=["die"], schematic_function=die_schematic)
def die_with_pads(
size: tuple[float, float] = (11470.0, 4900.0),
ngratings: int = 14,
Expand Down
6 changes: 6 additions & 0 deletions cspdk/si220/oband/_schematic.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
_RING_DOUBLE,
_WIRE_BEND,
_WIRE_STRAIGHT,
_die_ports,
sax_model,
schematic,
)
Expand Down Expand Up @@ -171,3 +172,8 @@
# Pads / via stacks
pad_schematic = schematic("pad", ["pad"], _PAD)
via_stack_schematic = schematic("pad", ["via", "stack"], _PAD)

# Die: symbol "die" makes editors render it as a die (no background box).
# Ports are derived from the factory kwargs; each side is the die edge the
# port sits on — opposite of the inward-pointing GDS orientation.
die_schematic = schematic("die", ["die"], _die_ports)
4 changes: 2 additions & 2 deletions cspdk/si220/oband/cells/die_with_pads.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Size,
)

from cspdk.si220.oband._schematic import pad_schematic
from cspdk.si220.oband._schematic import die_schematic, pad_schematic
from cspdk.si220.oband.tech import LAYER


Expand Down Expand Up @@ -119,7 +119,7 @@ def die(size: tuple[float, float] = (16000.0, 1 * 3000.0)) -> gf.Component:
return c


@gf.cell(tags=["die"])
@gf.cell(tags=["die"], schematic_function=die_schematic)
def die_with_pads(
size: tuple[float, float] = (11470.0, 4900.0),
ngratings: int = 14,
Expand Down
Loading