Skip to content

gf180: add metal density fill rules (fill.json)#4311

Open
lanserge wants to merge 1 commit into
The-OpenROAD-Project:masterfrom
lanserge:gf180-metal-density-fill
Open

gf180: add metal density fill rules (fill.json)#4311
lanserge wants to merge 1 commit into
The-OpenROAD-Project:masterfrom
lanserge:gf180-metal-density-fill

Conversation

@lanserge

@lanserge lanserge commented Jun 25, 2026

Copy link
Copy Markdown

Summary

The gf180 platform shipped FILL_CELLS (std-cell filler) but no metal density fill: there was no FILL_CONFIG, so the density_fill step (6_1_fill) inserted nothing. gf180mcu's density rules require >30% metal coverage per layer, die-wide (M2.4 / M3.4 / M5.4 / MT.3), which sparse designs cannot meet without fill.

This adds flow/platforms/gf180/fill.json (Metal1–Metal5), points FILL_CONFIG at it, and routes the fill to the foundry dummy-metal datatype.

Details

Stripe geometry (per DRM §13.3 dummy rules). Fill is emitted as rectangular stripes — 2.0 µm in the constrained axis, extended along each layer's routing channel (H: Metal1/3/5, V: Metal2/4) — rather than squares. Square 2.0 µm tiles waste a gap on all four sides and top out ~18% coverage (Metal5 below the 30% floor); stripes only pay the gap at channel ends and reach ~30–60%. Spacing follows DM.1 (min dimension 2.0 µm), DM.2 (fill-to-fill 1.0 µm, ≥0.98), DM.3 (fill-to-circuit-metal 2.0 µm). In the default 5LM_1TM stack Metal5 is the thick top metal (MT.4 min area 0.5625 µm²); the 2.0 µm stripes give ≥4 µm².

Dummy datatype (LVS). Density fill is spaced 2.0 µm from real metal, so each shape is an electrically floating island. The edi2gds layermaps mapped Metal1..Metal5 FILL/FILLOPC to datatype 0, which merges fill with drawn circuit metal — LVS extraction would then see metal on no net. This routes FILL/FILLOPC to datatype 4 (the Metal*_Dummy layers) so fill is distinguishable and LVS-clean.

Opt-in / no behavior change

USE_FILL still defaults to 0, so density_fill stays a no-op and no existing design's results change. A chip/top-level design opts in with USE_FILL=1. Metal fill is intentionally a chip-level (die-wide) step — block / hard-macro builds keep USE_FILL=0 so fill is inserted once at the top, not per block.

Verification

Ran OpenROAD density_fill -rules flow/platforms/gf180/fill.json on a routed gf180mcu design: rules parse and stripe fill inserts on Metal1–Metal5 with no errors. Per-layer fill-only coverage was 24–29% (Metal2 26.0 / Metal3 27.1 / Metal4 23.7 / Metal5 28.6%); adding drawn routing clears the 30% floor on all checked layers.

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

Copy link
Copy Markdown
Contributor

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 metal density fill rules for the gf180 platform by adding a new fill.json configuration file and referencing it in config.mk. Feedback suggests increasing the minimum fill size and spacing for Metal5 from 0.5 to 0.6 to ensure compatibility with both the 9K and 11K thick metal options and prevent DRC violations.

Comment thread flow/platforms/gf180/fill.json Outdated
Comment on lines +71 to +74
"width": [2.00, 1.00, 0.5],
"height": [2.00, 1.00, 0.5],
"space_to_fill": 0.5,
"space_to_non_fill": 0.5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The current minimum fill size and spacing of 0.5 for Metal5 is valid for the default 9K thick metal option (KVALUE=9, where min width/spacing is 0.44 um). However, the gf180 platform also supports the 11K thick metal option (KVALUE=11), which has a minimum width and spacing requirement of 0.6 um. Using 0.5 will result in DRC violations (rules MT.1 and MT.2) when KVALUE=11 is selected.

Changing the minimum size and spacing to 0.6 makes these rules robust and compatible with both 9K and 11K metal stack options without significantly impacting density fill coverage.

Suggested change
"width": [2.00, 1.00, 0.5],
"height": [2.00, 1.00, 0.5],
"space_to_fill": 0.5,
"space_to_non_fill": 0.5
"width": [2.00, 1.00, 0.6],
"height": [2.00, 1.00, 0.6],
"space_to_fill": 0.6,
"space_to_non_fill": 0.6

@lanserge

Copy link
Copy Markdown
Author

Thanks for the review. I looked into the Metal5 0.50.6 suggestion and I'd like to keep it at 0.5. The concern appears to conflate Metal5 with MetalTop:

  • In the 5LM_1TM stack, this fill is inserted on Metal5 (GDS 81/4), a thin routing layer. Per the gf180mcu KLayout DRC deck, Metal5 minimums are M5.1 = 0.28 µm width and M5.2a = 0.28 µm spacing. 0.5 clears both with large margin.
  • The MT.1/MT.2 rules quoted apply to MetalTop (the thick top metal, GDS 53), which this fill.json deliberately does not fill. Even MetalTop's thick variant is 0.44/0.46, not 0.6.
  • KVALUE (9K vs 11K) sets the MetalTop thickness, not Metal5. The 9K and 11K tech LEFs carry identical Metal5 rules (MINWIDTH 0.440 / SPACING 0.460), and 0.5 clears even that stricter LEF value. So there's no 9K-vs-11K Metal5 difference to guard against.

0.5 (vs the 1.0 used on M1–M4) was chosen on purpose: Metal5 carries the PDN stripes and is the coverage-tight layer against M5.4 (">30% metal5 coverage die-wide"). Relaxing it to 0.6 reduces that margin without any DRC need. Verified on a routed gf180mcu design — Metal5 fill inserts with no width/spacing violations.

@lanserge

Copy link
Copy Markdown
Author

Update after checking the primary spec (GF180MCU DRM) rather than relying on the open KLayout deck:

  • The 0.6 is MT.2b — spacing between wide (>10 µm) MetalTop — so it doesn't govern small fill shapes. The fill-relevant minimums are MT.1 = 0.44 µm width / MT.2a = 0.46 µm spacing, identical for 9K and 11K, both cleared by 0.5.
  • More importantly: in the default 5LM_1TM stack, Metal5 is the thick top metal, so the open gf180mcu_fd_pr deck (which checks GDS 81 as thin M5, 0.28 µm) under-checks it. Against the real rules, fill on Metal5 also has to respect MT.4 (min area 0.5625 µm²) and the dummy-metal rules in DRM §13.3 (DM.1 ~2.0 µm shapes, DM.2 ≥0.98–1.2 µm fill-to-fill, DM.3 2.0 µm fill-to-circuit-metal). The current values predate that and would not be foundry-DM-compliant.

So I'm reworking fill.json to be DM-compliant and re-validating that the >30 % coverage floor still holds (Metal5 is PDN-stripe-tight, so sparser fill needs a coverage check). Will push an update. Thanks — the Metal5 comment pointed at a real gap, just not the 0.6 one.

The gf180 platform had no metal density fill: it shipped FILL_CELLS
(std-cell filler) but no FILL_CONFIG, so OpenROAD's density_fill step
inserted nothing. gf180mcu's density deck enforces ">30% metal coverage
per layer, die-wide" (rules M2.4 / M3.4 / M5.4 / MT.3), which a sparse
design cannot meet without metal fill.

Add flow/platforms/gf180/fill.json (Metal1-Metal5) and point FILL_CONFIG
at it. Two details matter for gf180mcu correctness:

- Fill is emitted as rectangular STRIPES (2.0um in the constrained axis,
  extended along each layer's routing channel), not squares. Square 2.0um
  tiles waste a gap on all four sides and top out ~18% coverage, leaving
  Metal5 below the 30% floor; stripes only pay the gap at channel ends and
  reach ~30-60%. Geometry follows DRM section 13.3 dummy rules: min
  dimension 2.0um (DM.1), fill-to-fill 1.0um (DM.2, >=0.98), fill-to-
  circuit-metal 2.0um (DM.3). In the default 5LM_1TM stack Metal5 is the
  thick top metal (MT.4 min area 0.5625um^2); 2.0um stripes give >=4um^2.

- Density fill streams to the foundry dummy-metal datatype 4 (the
  Metal*_Dummy layers), not datatype 0. The edi2gds layermaps mapped
  Metal1..Metal5 FILL/FILLOPC to datatype 0, which merges dummy fill with
  drawn circuit metal. Because fill is spaced 2.0um away from real metal,
  each shape is an electrically floating island; on the drawn datatype LVS
  extraction would flag it as metal on no net. Routing FILL/FILLOPC to
  datatype 4 keeps the fill distinguishable and LVS-clean.

Opt-in and no change to existing results: USE_FILL still defaults to 0, so
density_fill stays a no-op unless a chip/top-level design sets USE_FILL=1.
Block/macro builds keep USE_FILL=0 so fill is inserted once, die-wide, at
chip level rather than per block.

Verified with OpenROAD density_fill -rules on a routed gf180mcu design:
rules parse and stripe fill inserts on Metal1-Metal5 with no errors; per-
layer fill-only coverage 24-29% (plus drawn routing) clears the 30% floor.

Known limitation: in the 6LM_1TM stack Metal5 is a thin intermediate layer
and MetalTop (GDS 53) is the thick top; this fill.json fills Metal1-5 only,
so 6LM MetalTop is not yet filled.

Signed-off-by: Serge Rabyking <s.rabykin@gmail.com>
@lanserge lanserge force-pushed the gf180-metal-density-fill branch from ea43ffa to 0bceea9 Compare June 25, 2026 16:40
@lanserge

Copy link
Copy Markdown
Author

Pushed an update (force-push) that reworks the fill based on the Metal5 discussion above and a closer read of the GF180MCU DRM:

  • Stripe fill instead of squares. Square 2.0 µm tiles top out ~18% coverage and leave Metal5 under the 30% floor. Fill is now rectangular stripes (2.0 µm in the constrained axis, extended along each layer's routing channel), which reach ~30–60%. Geometry follows DRM §13.3 dummy rules (DM.1 2.0 µm min dimension, DM.2 1.0 µm fill-to-fill, DM.3 2.0 µm fill-to-circuit-metal), and in the default 5LM_1TM stack the 2.0 µm Metal5 stripes clear MT.4 (min area 0.5625 µm²).
  • Fill now streams to the dummy datatype (4). The edi2gds layermaps mapped Metal1–5 FILL/FILLOPC to datatype 0, merging dummy fill with drawn metal. Since fill is spaced 2.0 µm from real metal, each shape is a floating island and would trip LVS as metal on no net; routing it to the Metal*_Dummy datatype 4 keeps it distinguishable and LVS-clean.

Re the earlier Metal5 0.5→0.6 suggestion: that's now moot since the geometry changed, but for the record the 0.6 is MT.2b (wide-metal >10 µm spacing), not a min for fill shapes — MT.1/MT.2a (0.44/0.46) are identical for 9K and 11K.

Still opt-in (USE_FILL defaults to 0); no existing design's results change.

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