From 65fd2b1b82518edabe198401865296e5466e7b51 Mon Sep 17 00:00:00 2001 From: jeffhsu3 Date: Sun, 30 Aug 2026 06:58:09 -0700 Subject: [PATCH 1/2] tests: cover the placement helpers in DRC CI two_transistor_interdigitized and common_centroid_ab_ba consume the multiplier's inter-finger top-metal ports (*sd_top_met_*), which no other registered cell touches. Without coverage here a change to inter_finger_topmet breaks them silently. Lands after the two fixes above so the new cells start green. Co-Authored-By: Claude Opus 5 (1M context) --- tests/drc/run_cell_drc.py | 5 +++++ tests/parameters/ci_drc_gf180.csv | 2 ++ tests/parameters/ci_drc_sky130.csv | 2 ++ 3 files changed, 9 insertions(+) diff --git a/tests/drc/run_cell_drc.py b/tests/drc/run_cell_drc.py index 2fb9369d..55529366 100644 --- a/tests/drc/run_cell_drc.py +++ b/tests/drc/run_cell_drc.py @@ -57,6 +57,11 @@ class CellSpec: # channel (CO.4 in gf180), so these exercise the dogbone path in fet.py. "nmos_narrow": "glayout.primitives.fet:nmos", "pmos_narrow": "glayout.primitives.fet:pmos", + # Placement helpers. These consume the multiplier's inter-finger top-metal + # ports (`*sd_top_met_*`), which no other cell touches, so without coverage + # here a change to `inter_finger_topmet` breaks them silently. + "two_transistor_interdigitized": "glayout.placement:two_transistor_interdigitized", + "common_centroid_ab_ba": "glayout.placement:common_centroid_ab_ba", } diff --git a/tests/parameters/ci_drc_gf180.csv b/tests/parameters/ci_drc_gf180.csv index 00f4b6ca..5086a3dd 100644 --- a/tests/parameters/ci_drc_gf180.csv +++ b/tests/parameters/ci_drc_gf180.csv @@ -10,3 +10,5 @@ low_voltage_cmirror,"{""width"": [4.0, 1.5], ""length"": 2.0, ""fingers"": [2, 1 opamp,"{""half_diffpair_params"": [5.0, 1.0, 1], ""diffpair_bias"": [5.0, 2.0, 1], ""half_common_source_params"": [7.0, 1.0, 10, 5], ""half_common_source_bias"": [6.0, 2.0, 8, 4], ""half_pload"": [6.0, 1.0, 5], ""add_output_stage"": false, ""with_antenna_diode_on_diffinputs"": 0, ""rmult"": 1}" nmos_narrow,"{""width"": 0.22, ""length"": 0.28}" pmos_narrow,"{""width"": 0.22, ""length"": 0.28}" +two_transistor_interdigitized,"{""device"": ""nfet"", ""numcols"": 2}" +common_centroid_ab_ba,"{""width"": 3, ""fingers"": 4, ""n_or_p_fet"": true}" diff --git a/tests/parameters/ci_drc_sky130.csv b/tests/parameters/ci_drc_sky130.csv index 5c61030c..140b2741 100644 --- a/tests/parameters/ci_drc_sky130.csv +++ b/tests/parameters/ci_drc_sky130.csv @@ -10,3 +10,5 @@ low_voltage_cmirror,"{""width"": [4.0, 1.5], ""length"": 2.0, ""fingers"": [2, 1 opamp,"{""half_diffpair_params"": [6, 1, 4], ""diffpair_bias"": [6, 2, 4], ""half_common_source_params"": [7, 1, 10, 3], ""half_common_source_bias"": [6, 2, 8, 2], ""output_stage_params"": [5, 1, 16], ""output_stage_bias"": [6, 2, 4], ""half_pload"": [6, 1, 6], ""mim_cap_size"": [12, 12], ""mim_cap_rows"": 3, ""rmult"": 2, ""with_antenna_diode_on_diffinputs"": 0, ""add_output_stage"": false}" nmos_narrow,"{""width"": 0.15, ""length"": 0.15}" pmos_narrow,"{""width"": 0.15, ""length"": 0.15}" +two_transistor_interdigitized,"{""device"": ""nfet"", ""numcols"": 2}" +common_centroid_ab_ba,"{""width"": 3, ""fingers"": 4, ""n_or_p_fet"": true}" From 54684324ba9a6d24b359e4c3cd68817cf8d64530 Mon Sep 17 00:00:00 2001 From: jeffhsu3 Date: Sun, 30 Aug 2026 06:58:09 -0700 Subject: [PATCH 2/2] common_centroid_ab_ba: size the guard ring around the routing, not the devices The tapring was placed before the gate/drain routes existed, so evaluate_bbox saw only the transistors. The ring ended up ~1um clear of the devices while the routes reach ~1.84um above them, leaving a met2 route 0.25um from the ring's met2 rail -- gf180 M2.2a requires 0.28um. Moving the ring placement after all routing makes evaluate_bbox see the real extent. No change to the ring's construction, only when it is built. Co-Authored-By: Claude Opus 5 (1M context) --- .../placement/common_centroid_ab_ba.py | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/glayout/placement/common_centroid_ab_ba.py b/src/glayout/placement/common_centroid_ab_ba.py index af688ba0..b940b23d 100644 --- a/src/glayout/placement/common_centroid_ab_ba.py +++ b/src/glayout/placement/common_centroid_ab_ba.py @@ -76,26 +76,6 @@ def common_centroid_ab_ba( a_botr.movex(fetLdims[0]/2+min_spacing_x/2).movey(pdk.snap_to_2xgrid(-fetLdims[1]/2-min_spacing_y/2)) b_botl.movex(0-fetLdims[0]/2-min_spacing_x/2).movey(pdk.snap_to_2xgrid(-fetLdims[1]/2-min_spacing_y/2)) comcentroid.add_padding(default=0,layers=[pdk.get_glayer(well)]) - # if substrate tap place substrate tap, and route dummy to substrate tap - if substrate_tap: - tapref = comcentroid << tapring(pdk,evaluate_bbox(comcentroid,padding=1))#,horizontal_glayer="met1") - comcentroid.add_ports(tapref.get_ports_list(),prefix="tap_") - try: - comcentroid<