Skip to content
Open
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
46 changes: 26 additions & 20 deletions src/glayout/placement/common_centroid_ab_ba.py
Original file line number Diff line number Diff line change
Expand Up @@ -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<<straight_route(pdk,a_topl.ports["multiplier_0_dummy_L_gsdcon_top_met_W"],comcentroid.ports["tap_W_top_met_W"],glayer2="met1")
except KeyError:
pass
try:
comcentroid<<straight_route(pdk,b_topr.ports["multiplier_0_dummy_R_gsdcon_top_met_W"],comcentroid.ports["tap_E_top_met_E"],glayer2="met1")
except KeyError:
pass
try:
comcentroid<<straight_route(pdk,b_botl.ports["multiplier_0_dummy_L_gsdcon_top_met_W"],comcentroid.ports["tap_W_top_met_W"],glayer2="met1")
except KeyError:
pass
try:
comcentroid<<straight_route(pdk,a_botr.ports["multiplier_0_dummy_R_gsdcon_top_met_W"],comcentroid.ports["tap_E_top_met_E"],glayer2="met1")
except KeyError:
pass
# correct pwell place, add ports, flatten, and return
comcentroid.add_ports(a_topl.get_ports_list(),prefix="tl_")
comcentroid.add_ports(b_topr.get_ports_list(),prefix="tr_")
Expand Down Expand Up @@ -213,6 +193,32 @@ def localportrename(portin):
rename_south_portb = vgateb1.ports["top_met_S"].copy()# add B_gate_S
rename_south_portb.name = "B_gate_S"
comcentroid.add_ports(ports=[rename_south_portb])
# The guard ring has to enclose the ROUTING, not just the devices. Sizing it
# off the pre-routing bbox left the ring 1um clear of the transistors while the
# gate/drain routes reach ~1.84um above them, so a met2 route ended up 0.25um
# from the ring's met2 rail -- gf180 M2.2a wants 0.28um. Placing the ring after
# all routing makes evaluate_bbox see the real extent.
# 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<<straight_route(pdk,a_topl.ports["multiplier_0_dummy_L_gsdcon_top_met_W"],comcentroid.ports["tap_W_top_met_W"],glayer2="met1")
except KeyError:
pass
try:
comcentroid<<straight_route(pdk,b_topr.ports["multiplier_0_dummy_R_gsdcon_top_met_W"],comcentroid.ports["tap_E_top_met_E"],glayer2="met1")
except KeyError:
pass
try:
comcentroid<<straight_route(pdk,b_botl.ports["multiplier_0_dummy_L_gsdcon_top_met_W"],comcentroid.ports["tap_W_top_met_W"],glayer2="met1")
except KeyError:
pass
try:
comcentroid<<straight_route(pdk,a_botr.ports["multiplier_0_dummy_R_gsdcon_top_met_W"],comcentroid.ports["tap_E_top_met_E"],glayer2="met1")
except KeyError:
pass

# rename ports and add private ports for smart route
comcentroid = rename_ports_by_orientation(comcentroid)
comcentroid.add_ports(create_private_ports(comcentroid,["".join(prtp) for prtp in product(["A_","B_"],["drain","source","gate"])]))
Expand Down
5 changes: 5 additions & 0 deletions tests/drc/run_cell_drc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
}


Expand Down
2 changes: 2 additions & 0 deletions tests/parameters/ci_drc_gf180.csv
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
2 changes: 2 additions & 0 deletions tests/parameters/ci_drc_sky130.csv
Original file line number Diff line number Diff line change
Expand Up @@ -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}"