Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding MIM-A table for GF180MCU DRC #72

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
148 changes: 148 additions & 0 deletions klayout/drc/rule_decks/mim_a.drc
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# frozen_string_literal: true

################################################################################################
# Copyright 2022 GlobalFoundries PDK Authors
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same 2023

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@atorkmabrains

I will do that for all DRC files in a separate PR after adding all tables.

Refer to #75

#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
################################################################################################

if MIM_OPTION == 'A'
#================================================
#------------MIM CAPACITOR OPTION A -------------
#================================================

logger.info('Starting MIM Capacitor Option A derivations')

m2_fusetop = metal2.interacting(fusetop)
mim_virtual = fusetop.sized(1.06.um).and(m2_fusetop)
Copy link
Member

Choose a reason for hiding this comment

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

can we add a comment about which rules are using those (also see #77)


# Rule MIM.1: Minimum MiM bottom plate spacing to the bottom plate metal
## (whether adjacent MiM or routing metal) is 1.2µm.
logger.info('Executing rule MIM.1')
mim1_l1 = metal2.separation(mim_virtual, transparent, 1.2.um)
mim1_l1.output('MIM.1', 'MIM.1 : Minimum MiM bottom plate spacing to the bottom plate metal
(whether adjacent MiM or routing metal): 1.2µm')
mim1_l1.forget

# Rule MIM.2: Minimum MiM bottom plate overlap of Via2 layer.
## [This is applicable for via2 within 1.06um oversize of FuseTop layer
## (referenced to virtual bottom plate)] is 0.4µm.
logger.info('Executing rule MIM.2')
mim2_via = via2.overlapping(mim_virtual)
mim2_l1 = mim2_via.enclosed(metal2, 0.4.um, euclidian).polygons(0.001.um)
mim2_l2 = mim2_via.not_outside(metal2).not(metal2)
Copy link
Member

Choose a reason for hiding this comment

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

can you add a comment describe this line (is that for selecting the bottom plate?), because I can't really relate this to the current wording of the rule.

mim2_l = mim2_l1.join(mim2_l2)
mim2_l.output('MIM.2', 'MIM.2 : Minimum MiM bottom plate overlap of Via2 layer.
[This is applicable for via2 within 1.06um oversize of FuseTop layer
(referenced to virtual bottom plate)]: 0.4µm')
mim2_l1.forget
mim2_l2.forget
mim2_l.forget
mim2_via.forget

# Rule MIM.3: Minimum MiM bottom plate overlap of Top plate is 0.6um.
logger.info('Executing rule MIM.3')
mim3_l1 = fusetop.enclosed(mim_virtual, 0.6.um).polygons(0.001.um)
mim3_l2 = fusetop.not_inside(mim_virtual)
Copy link
Member

Choose a reason for hiding this comment

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

same q here.

mim3_l = mim3_l1.join(mim3_l2)
mim3_l.output('MIM.3', 'MIM.3 : Minimum MiM bottom plate overlap of Top plate: 0.6um')
mim3_l1.forget
mim3_l2.forget
mim_virtual.forget

# Rule MIM.4: Minimum MiM top plate (FuseTop) overlap of Via2 is 0.4µm.
logger.info('Executing rule MIM.4')
mim4_l1 = via2.enclosed(fusetop, 0.4.um, euclidian).polygons(0.001.um)
mim4_l2 = via2.not_outside(fusetop).not(fusetop)
Copy link
Member

Choose a reason for hiding this comment

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

same q here.

mim4_l = mim4_l1.join(mim4_l2)
mim4_l.output('MIM.4', 'MIM.4 : Minimum MiM top plate (FuseTop) overlap of Via2: 0.4µm')
mim4_l1.forget
mim4_l2.forget
mim4_l.forget

# Rule MIM.5: Minimum spacing between top plate and
## the Via2 connecting to the bottom plate is 0.4µm.
logger.info('Executing rule MIM.5')
mim5_l1 = fusetop.separation(via2.interacting(metal2), 0.4.um, euclidian)
mim5_l1.output('MIM.5', 'MIM.5 : Minimum spacing between top plate and
the Via2 connecting to the bottom plate: 0.4µm')
mim5_l1.forget

# Rule MIM.6: Minimum spacing between unrelated top plates is 0.6µm.
logger.info('Executing rule MIM.6')
mim6_l1 = fusetop.space(0.6.um, euclidian)
mim6_l1.output('MIM.6', 'MIM.6 : Minimum spacing between unrelated top plates: 0.6µm')
mim6_l1.forget

# Rule MIM.7: Min FuseTop enclosure by CAP_MK is 0um.
logger.info('Executing rule MIM.7')
mim7_l1 = fusetop.not(cap_mk)
mim7_l1.output('MIM.7', 'MIM.7 : Min FuseTop enclosure by CAP_MK: 0um')
mim7_l1.forget

# Rule MIM.8a: Minimum MIM cap area (defined by FuseTop area) is 25µm².
logger.info('Executing rule MIM.8a')
mim8a_l1 = fusetop.with_area(nil, 25.um)
mim8a_l1.output('MIM.8a', 'MIM.8a : Minimum MIM cap area (defined by FuseTop area): 25µm²')
mim8a_l1.forget

# Rule MIM.8b: Maximum single MIM Cap area (Use multiple MIM caps in parallel
## connection if bigger capacitors are required) (um2) is 10000µm.
logger.info('Executing rule MIM.8b')
mim8b_l1 = fusetop.with_area(10_001.um, nil)
Copy link
Member

Choose a reason for hiding this comment

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

curious why you're not using the same thing as mim_b here?

fusetop.with_area(10_000.um, nil).not(fusetop.with_area(10_000.um))

mim8b_l1.output('MIM.8b', 'MIM.8b : Maximum single MIM Cap area (Use multiple MIM caps in parallel
connection if bigger capacitors are required) (um2): 10000µm')
mim8b_l1.forget

# Rule MIM.9: Min. via spacing for sea of via on MIM top plate is 0.5µm.
logger.info('Executing rule MIM.9')
mim9_l1 = via2.and(fusetop).space(0.5.um, euclidian)
mim9_l1.output('MIM.9', 'MIM.9 : Min. via spacing for sea of via on MIM top plate. : 0.5µm')
mim9_l1.forget

# Rule MIM.10: (a) There cannot be any Via1 touching MIM bottom plate Metal2.
## (b) MIM bottom plate Metal2 can only be connected through the higher Via (Via2).
logger.info('Executing rule MIM.10')
mim10_l1 = via1.and(m2_fusetop)
mim10_l1.output('MIM.10', 'MIM.10 : (a) There cannot be any Via1 touching MIM bottom plate Metal2.
(b) MIM bottom plate Metal2 can only be connected through the higher Via (Via2).')
mim10_l1.forget

# Rule MIM.11: Bottom plate of multiple MIM caps can be shared (for common nodes)
# as long as total MIM area with that single common plate does not exceed MIM.8b rule.
Copy link
Member

Choose a reason for hiding this comment

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

should that be MIM.8a rule here? (since we're in the mim_a.drc deck)

logger.info('Executing rule MIM.11')
mim11_large_metal2 = m2_fusetop.with_area(10_000, nil)
mim11_large_metal2_violation = polygon_layer
mim11_large_metal2.data.each do |p|
mim11_metal2_polygon_layer = polygon_layer
mim11_metal2_polygon_layer.data.insert(p)
fuse_in_polygon = fusetop.and(mim11_metal2_polygon_layer)
next unless fuse_in_polygon.area > 10_000

mim11_bad_metal2_polygon = mim11_metal2_polygon_layer.interacting(fuse_in_polygon)
mim11_bad_metal2_polygon.data.each do |b|
b.num_points.positive? && mim11_large_metal2_violation.data.insert(b)
end
end
mim11_l1 = mim11_large_metal2_violation
mim11_l1.output('MIM.11', 'MIM.11 : Bottom plate of multiple MIM caps can be shared (for common nodes)
as long as total MIM area with that single common plate does not exceed MIM.8b rule.')
mim11_l1.forget
mim11_large_metal2.forget
mim11_large_metal2_violation.forget
m2_fusetop.forget

# Rule MIM.12 is not a DRC check
## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_4_1.html

end
Binary file added klayout/drc/testing/testcases/unit/mim_a.gds
Binary file not shown.
Loading