Skip to content

gf180 opamp: route the mimcap on the PDK's own layers, and three cell fixes - #110

Closed
carloscl03 wants to merge 2 commits into
ReaLLMASIC:mainfrom
carloscl03:gf180-opamp-lvs
Closed

gf180 opamp: route the mimcap on the PDK's own layers, and three cell fixes#110
carloscl03 wants to merge 2 commits into
ReaLLMASIC:mainfrom
carloscl03:gf180-opamp-lvs

Conversation

@carloscl03

@carloscl03 carloscl03 commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Four cell fixes that together take the gf180 opamp to a clean DRC and a
matching netlist. Depends on #103 for no_pin_labels, which two of these fixes use, and
on #108 and #109 for the runner and the mimcap model. The branch is now
stacked on #103, so the diff shows both until that one merges.

The mimcap routing was hardcoded for sky130. __add_mimcap_arr carried
the comment "V2 (cap_metalbottom) is glayout met4, V1 (cap_metaltop) is
met5"
. True there; on gf180 option A the MIM sits on met2/met3. The routes
landed two levels above the plates with no via to step down, so the whole
compensation cap array was floating -- via3 count was zero anywhere near
it. The layers now come from pdk.get_grule("capmet"), so both PDKs work.

diff_to_single described an internal node the cell does not build. Its
netlist gave TOP1 and BOT1 a node of their own, V1. In the layout that node
and the output are one net, which the extractor reports with five terminals.
This is the cell's structure rather than a stray overlap: deleting the entire
strip where the two rails run over each other still leaves them connected,
whereas cutting an accidental short separates the nodes. VSS2, the
counterpart node, already matched the netlist exactly on all three terminals.

The comp fill between the centre multipliers sat outside the implant. The
gap fill uses the plusdoped ports, which are on the implant layer, so at
their own width the fill's edges came out level with the implant instead of
inside it -- 0.01um of extension where PP.5b/PP.5dii ask for 0.16. Insetting
it by the implant enclosure clears all eight violations in the opamp and the
four in the converter, and still covers the 0.17um comp gap it exists for.

The output stage's well was not tied to its source, and
diff_pair_ibias's pin labels could not be suppressed the way diff_pair's
can, so they leaked into the parent as extra top-level pins.

before   LVS 5/8 cells    opamp 19 mismatches, DRC 8
after    LVS 8/8          opamp matches, DRC 0 on all 11 cells

@LuighiV

LuighiV commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Hi @carloscl03

Thanks for the fixes in the cells. This will be very helpful. Just a reminder to update the commit messages to English, and if you have comments in the source code also they should be in English.

Thanks,
Luighi

@carloscl03
carloscl03 force-pushed the gf180-opamp-lvs branch 3 times, most recently from 4e8c7d9 to 08896fb Compare August 17, 2026 01:46
@carloscl03

Copy link
Copy Markdown
Contributor Author

Done. Commit message and source comments are in English.

@msaligane
msaligane requested a review from AL-255 August 18, 2026 02:34
Three things kept diff_pair and diff_pair_ibias from matching on gf180.

Pin labels landed off metal. gf180 maps met*_pin and met*_label to the
same non-conducting label layer, and the markers were aligned ('c','b'),
which puts them tangent to the port edge rather than on it. Only VDD1 and
VDD2 extracted, because they happen to sit over drain metal; VTAIL, VN, VP
and B came out as unnamed nets and LVS reported four missing pins.
current_mirror already centres its bulk label for this exact reason.

Dummy source/drain net was chosen by PDK name. The cell routes its dummies
to the tap ring whenever substrate_tap is on, so both extractors put them
on bulk -- the choice follows the layout, not the process. The composite
already had to override it back to 'B', with a comment saying so.

Sub-cell labels leaked into diff_pair_ibias. VTAIL is a top-level pin of a
standalone diff_pair but an internal net there, so the inherited label
extracted as an extra pin. Wrapped the build in a no_pin_labels() context
manager (new in port_utils, replacing the copy-pasted env var dance) and
dropped the cmirror dummies' "HACK ... likely incorrect" PDK check for the
same layout-driven rule.

gf180: LVS 5/8 -> 7/8, DRC 9/9. sky130: no change, LVS 8/8, DRC 9/9.
__add_mimcap_arr hardcoded met4/met5 for the cap plates, which is where
sky130 puts the MIM. On gf180 option A it sits on met2/met3, so the routes
landed two levels above the plates with no via to step down and the whole
compensation array floated -- zero via3 anywhere near it. The layers now
come from pdk.get_grule("capmet"), so both PDKs work.

diff_to_single described an internal node the cell does not build. Its
netlist gave TOP1 and BOT1 a node of their own, V1; in the layout that
node and the output are one net, which the extractor reports with five
terminals. Deleting the whole strip where the two rails overlap still
leaves them connected, so this is the cell's structure rather than a stray
short. VSS2, the counterpart node, already matched on all three terminals.

The comp fill between the centre multipliers used the plusdoped ports,
which are on the implant layer, so at their own width the fill's edges
came out level with the implant instead of inside it: 0.01um of extension
where PP.5b/PP.5dii ask for 0.16. Insetting it by the implant enclosure
clears all eight violations in the opamp and four in the converter, and
still covers the 0.17um comp gap it exists for.

The output stage's well was not tied to its source, and diff_pair_ibias's
pin labels could not be suppressed the way diff_pair's can, so they leaked
into the parent as extra top-level pins.
@carloscl03

Copy link
Copy Markdown
Contributor Author

The three failing checks were an ImportError, not a DRC problem: this branch used no_pin_labels in two files but the definition lives in #103, which it did not include. Every cell import failed, so both DRC jobs and the notebook job died before running anything.

Rebased onto #103, which is itself now rebased onto current main. Content is unchanged in both, and the only conflict was a comment that this branch shortens.

Until #103 merges the diff here shows both changes; it will narrow to this PR's own five files once that one lands.

@AL-255

AL-255 commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Hi Carlos,
I see your recent PRs, and we're in the process of merging them. Sorry for the delay, but we've been busy recently.
We have a recurring development meeting every Friday morning EDT. It would be great if you could join and chat with us.
Time: Every Friday Morning 09:30 – 10:00 (U.S. Eastern Time)
Link: https://umich.zoom.us/j/97910900637

Best,
Anhang

@msaligane

Copy link
Copy Markdown
Member

there are some merge conflicts. can you please take a look.

@msaligane

Copy link
Copy Markdown
Member

Please address the CI and conflicts issues.

@carloscl03

Copy link
Copy Markdown
Contributor Author

Status update after looking at what rebasing this onto current main involves — it needs rework rather than conflict resolution, so I would rather say why than push something speculative.

The pin-label half is superseded. #105 landed with_pin_labels on diff_pair, and #112 takes the general case: the LVS runner drops labels the reference netlist does not declare as pins, which covers VTAIL inside diff_pair_ibias and opamp without any cell having to cooperate. Verified on a real build — [diff_pair_ibias] dropped 1 inherited label(s) not declared as pins: VTAIL. So no_pin_labels() comes out of this PR and it stops depending on #103.

The mimcap half needs redoing. #106 rewrote mimcap() and the array's ports changed with it:

row0_col0_top_met_E       exists
row0_col0_bottom_met_E    gone

This PR routes to bottom_met_E, so that line cannot work as written any more. The underlying point still stands — main still hardcodes vglayer="met5", hglayer="met4" for the mimcap routes, which is correct for option B and wrong for option A — but adapting it means re-deriving the routing against the new ports and layers, and that has to be verified by building the opamp rather than by reading.

I cannot build gf180 cells on gdstk locally until #102 lands (KeyError: 'bl_multiplier_0_source_S'), so I would rather do this once #112 and #102 are in and the result can actually be checked.

The other three fixes here are unaffected: diff_to_single's phantom V1 node, the comp fill outside the implant, and the output stage's well tie.

@carloscl03

Copy link
Copy Markdown
Contributor Author

Closing this in favour of #115, which carries the part of it that is still worth having.

Both commits on this branch have been overtaken since it was opened:

The mimcap routing fix is moot. The complaint was that __add_mimcap_arr hardcoded sky130's layers. main now routes the array with vglayer="met5", hglayer="met4", and on gf180 capmet resolves to exactly that — capmettop (81,0) -> met5, capmetbottom (46,0) -> met4. So the hardcoded layers already agree with what the PDK rule would give. Deriving them would still be tidier for a PDK configured on option A, but it is no longer a fix for anything that is broken.

The pin-label fix is superseded by #105 on diff_pair and by #112 for the general case, where the LVS runner drops labels the reference netlist does not declare as pins.

That leaves the three cell fixes, which never made it onto this branch and are now #115: the phantom V1 node in diff_to_single's netlist, the comp fill landing outside the implant, and the output stage's floating well. Measured there — differential_to_single_ended_converter 8 -> 4 DRC violations, opamp 126 -> 118, and the netlist node corrected in both.

@msaligane — apologies for the delay on the conflict requests. The honest answer turned out to be that there was no conflict worth resolving here, only a PR that had stopped applying. #115 is main plus three commits with no dependencies.

@carloscl03 carloscl03 closed this Aug 23, 2026
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.

4 participants