Skip to content

feat: add new cells and GSG cross-section#46

Open
joamatab wants to merge 3 commits into
mainfrom
feat/add-new-cells-and-gsg-xs
Open

feat: add new cells and GSG cross-section#46
joamatab wants to merge 3 commits into
mainfrom
feat/add-new-cells-and-gsg-xs

Conversation

@joamatab

@joamatab joamatab commented Jun 13, 2026

Copy link
Copy Markdown

Summary

  • Add wrapper cells: straight, bend_euler, double_linear_inverse_taper_mirror, text_rectangular, pad, pad_gsg
  • Add die_phix_rf die floorplan with east/west edge couplers and north/south RF pads
  • Add gsg (ground-signal-ground) cross-section in tech.py

Test plan

  • Run make test to verify no regressions
  • Build cells with build_cells and inspect GDS output
  • Verify new cells appear in the PDK cell list

Summary by Sourcery

Add new photonic and RF layout cells and a corresponding ground-signal-ground cross-section to support edge-coupled dies with RF pad layouts.

New Features:

  • Introduce wrapper cells for straight waveguides, Euler bends, mirrored double linear inverse tapers, and rectangular text labels.
  • Add pad and RF GSG pad cells for electrical interconnect layout.
  • Add a die_phix_rf floorplan cell with edge couplers and RF pad arrangements on north and south edges.
  • Define a gsg cross-section for ground-signal-ground transmission line routing in the technology stack.

…cross-section

Add commonly used wrapper cells and a die_phix_rf floorplan with RF pads.
@sourcery-ai

sourcery-ai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds wrapper cells for common photonic components (straight waveguide, Euler bends, tapers, text, and pads), introduces a parametrized RF-focused die floorplan with edge couplers and RF pads, and defines a new ground-signal-ground (GSG) cross-section used by the new RF pad cell.

File-Level Changes

Change Details Files
Introduce wrapper cells for standard waveguide and taper components to expose them as PDK cells with consistent tags and defaults.
  • Add public straight cell wrapper around gf.components.straight with default xs_rwg1000 cross-section and cells tag
  • Add bend_euler cell wrapper around gf.c.bend_euler with waveguides tag and default xs_rwg1000
  • Add double_linear_inverse_taper_mirror cell that reuses double_linear_inverse_taper and returns a mirrored version via gf.functions.mirror
lnoi400/cells.py
Add reusable text and pad primitives wired to PDK layers and cross-sections for use in die-level layouts.
  • Add text_rectangular cell wrapper around gf.c.text_rectangular with LN_RIDGE default layer and text tag
  • Add pad cell wrapper around gf.c.pad configured with LAYER.TL and die tag
  • Add pad_gsg RF pad cell implemented as a straight waveguide using the new gsg cross-section
lnoi400/cells.py
Create a parametrized RF-oriented die floorplan with edge couplers, DC pads, and GSG RF pads.
  • Add die_phix_rf cell that builds a die_frame and passes it to gf.c.die_frame_phix_rf with configurable fiber, pad, and RF pad counts and pitches
  • Compute default npads from die size, pad pitch, and edge_coupler_keepout with an upper bound for DC pads
  • Expose numerous layout and labeling knobs (offsets, layers, text component) to customize the die layout while defaulting to existing PDK cross-sections and components
lnoi400/cells.py
Define a new ground-signal-ground cross-section for RF routing and pads.
  • Add gsg @xsection function that constructs a CrossSection with one central signal Section and two ground Sections offset by gap+width on TL layer
  • Set default radius to a function of trace_width and gap to ensure reasonable bend radius for RF lines
lnoi400/tech.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In double_linear_inverse_taper_mirror, gf.functions.mirror(c) uses the default mirror axis and component naming; consider passing the mirror axis explicitly (e.g., p1/p2) and setting a distinct name to guarantee the taper is mirrored as described in the docstring and to avoid potential name clashes with the original component.
  • The text_rectangular wrapper hardcodes position=(0.0, 0.0); exposing position as a parameter and forwarding it to gf.c.text_rectangular would make the wrapper more generally usable and consistent with the underlying API.
  • For the new gsg cross-section, you might want to accept a LayerSpec and default to LAYER.TL (as in the pad cell) instead of a plain string to keep layer specification consistent across the tech and cells.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `double_linear_inverse_taper_mirror`, `gf.functions.mirror(c)` uses the default mirror axis and component naming; consider passing the mirror axis explicitly (e.g., `p1`/`p2`) and setting a distinct name to guarantee the taper is mirrored as described in the docstring and to avoid potential name clashes with the original component.
- The `text_rectangular` wrapper hardcodes `position=(0.0, 0.0)`; exposing `position` as a parameter and forwarding it to `gf.c.text_rectangular` would make the wrapper more generally usable and consistent with the underlying API.
- For the new `gsg` cross-section, you might want to accept a `LayerSpec` and default to `LAYER.TL` (as in the `pad` cell) instead of a plain string to keep layer specification consistent across the tech and cells.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several new components and cross-sections to the LNOI400 PDK, including wrappers for straight waveguides, Euler bends, mirrored double linear inverse tapers, pads, and Phix RF die frames, as well as a new GSG (Ground-Signal-Ground) cross-section. Feedback on these changes highlights a runtime error in the GSG cross-section where port_names and port_types are incorrectly passed to Section instead of CrossSection. Additionally, it is recommended to use LayerSpec and LAYER.TL instead of raw strings for layer parameters, and to add a return type annotation to the pad_gsg cell for consistency.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread lnoi400/tech.py
Comment on lines +286 to +297
sections = [
Section(
width=width,
layer=layer,
offset=0,
port_names=port_names_electrical,
port_types=port_types_electrical,
),
Section(width=width, layer=layer, offset=-gap - width),
Section(width=width, layer=layer, offset=+gap + width),
]
return CrossSection(sections=tuple(sections), radius=radius or 3 * width + 2 * gap)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

In gdsfactory, the Section class does not accept port_names and port_types arguments. Passing them to Section will result in a validation/runtime error. Instead, these arguments should be passed to the CrossSection constructor.

Suggested change
sections = [
Section(
width=width,
layer=layer,
offset=0,
port_names=port_names_electrical,
port_types=port_types_electrical,
),
Section(width=width, layer=layer, offset=-gap - width),
Section(width=width, layer=layer, offset=+gap + width),
]
return CrossSection(sections=tuple(sections), radius=radius or 3 * width + 2 * gap)
sections = [
Section(
width=width,
layer=layer,
offset=0,
),
Section(width=width, layer=layer, offset=-gap - width),
Section(width=width, layer=layer, offset=+gap + width),
]
return CrossSection(
sections=tuple(sections),
radius=radius or 3 * width + 2 * gap,
port_names=port_names_electrical,
port_types=port_types_electrical,
)

Comment thread lnoi400/tech.py
Comment on lines +277 to +283
def gsg(
trace_width: float = 100,
layer: str = "TL",
gap: float = 50,
radius: float | None = None,
**kwargs,
) -> CrossSection:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency and robustness, use LayerSpec and LAYER.TL instead of a raw string "TL" for the layer parameter. This ensures that the layer is correctly resolved using the PDK's layer map.

Suggested change
def gsg(
trace_width: float = 100,
layer: str = "TL",
gap: float = 50,
radius: float | None = None,
**kwargs,
) -> CrossSection:
def gsg(
trace_width: float = 100,
layer: LayerSpec = LAYER.TL,
gap: float = 50,
radius: float | None = None,
**kwargs,
) -> CrossSection:

Comment thread lnoi400/cells.py
Comment on lines +1569 to +1570
@gf.cell(tags=["die"])
def pad_gsg(length: float = 100):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Add the return type annotation -> gf.Component to pad_gsg for consistency with other cell definitions in this file, and use a float literal 100.0 to match the type annotation of length.

Suggested change
@gf.cell(tags=["die"])
def pad_gsg(length: float = 100):
@gf.cell(tags=["die"])
def pad_gsg(length: float = 100.0) -> gf.Component:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant