Skip to content

Commit

Permalink
Merge pull request #48 from efabless/otp_mk_google
Browse files Browse the repository at this point in the history
Adding otp_mk table for GF180MCU DRC
  • Loading branch information
proppy authored Mar 30, 2023
2 parents a7d9c01 + 7a6d669 commit f4fac8b
Show file tree
Hide file tree
Showing 3 changed files with 1,683 additions and 0 deletions.
153 changes: 153 additions & 0 deletions klayout/drc/rule_decks/otp_mk.drc
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# frozen_string_literal: true

################################################################################################
# Copyright 2022 GlobalFoundries PDK Authors
#
# 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 FEOL
#================================================
#---------------------OTP_MK---------------------
#================================================

logger.info('Starting OTP_MK derivations')

comp_otp = comp.and(otp_mk)
poly_otp = poly2.and(otp_mk)
sab_otp = sab.and(otp_mk)
tgate_edges = tgate.edges

# Rule O.DF.3a: Min. COMP Space. P-substrate tap (PCOMP outside NWELL) can be butted
## for different voltage devices as the potential is same. is 0.24µm
logger.info('Executing rule O.DF.3a')
odf3a_l1 = comp_otp.space(0.24.um, euclidian)
odf3a_l1.output('O.DF.3a', 'O.DF.3a : Min. COMP Space. P-substrate tap (PCOMP outside NWELL)
can be butted for different voltage devices as the potential is same. : 0.24µm')
odf3a_l1.forget

# Rule O.DF.6: Min. COMP extend beyond poly2 (it also means source/drain overhang). is 0.22µm
logger.info('Executing rule O.DF.6')
odf6_l1 = poly_otp.enclosed(comp_otp, 0.22.um, projection)
odf6_l1.output('O.DF.6', 'O.DF.6 : Min. COMP extend beyond poly2 (it also means source/drain overhang). : 0.22µm')
odf6_l1.forget

# Rule O.DF.9: Min. COMP area (um2). is 0.1444µm²
logger.info('Executing rule O.DF.9')
odf9_l1 = comp_otp.with_area(nil, 0.1444.um)
odf9_l1.output('O.DF.9', 'O.DF.9 : Min. COMP area (um2). : 0.1444µm²')
odf9_l1.forget

# Rule O.PL.2: Min. poly2 width. is 0.22µm
logger.info('Executing rule O.PL.2')
opl2_l1 = poly_otp.edges.and(tgate_edges).width(0.22.um, euclidian)
opl2_l1.output('O.PL.2', 'O.PL.2 : Min. poly2 width. : 0.22µm')
opl2_l1.forget

# Rule O.PL.3a: Min. poly2 Space on COMP. is 0.18µm
logger.info('Executing rule O.PL.3a')
opl3a_l1 = tgate.join(poly2.not(comp)).and(otp_mk).space(0.18.um, euclidian)
opl3a_l1.output('O.PL.3a', 'O.PL.3a : Min. poly2 Space on COMP. : 0.18µm')
opl3a_l1.forget

# Rule O.PL.4: Min. extension beyond COMP to form Poly2 end cap. is 0.14µm
logger.info('Executing rule O.PL.4')
opl4_l1 = comp_otp.enclosed(poly_otp, 0.14.um, euclidian)
opl4_l1.output('O.PL.4', 'O.PL.4 : Min. extension beyond COMP to form Poly2 end cap. : 0.14µm')
opl4_l1.forget

# Rule O.PL.5a is not a DRC check
## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_10.html

# Rule O.PL.5b is not a DRC check
## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_10.html

# Rule O.SB.2: Min. salicide Block Space. is 0.28µm
logger.info('Executing rule O.SB.2')
osb2_l1 = sab_otp.space(0.28.um, euclidian)
osb2_l1.output('O.SB.2', 'O.SB.2 : Min. salicide Block Space. : 0.28µm')
osb2_l1.forget

# Rule O.SB.3: Min. space from salicide block to unrelated COMP. is 0.09µm
logger.info('Executing rule O.SB.3')
osb3_l1 = sab.outside(comp).and(otp_mk).separation(comp.outside(sab), 0.09.um, euclidian)
osb3_l1.output('O.SB.3', 'O.SB.3 : Min. space from salicide block to unrelated COMP. : 0.09µm')
osb3_l1.forget

# Rule O.SB.4: Min. space from salicide block to contact.
logger.info('Executing rule O.SB.4')
osb4_l1 = sab_otp.separation(contact, 0.03.um, euclidian).polygons(0.001.um).or(sab_otp.and(contact))
osb4_l1.output('O.SB.4', 'O.SB.4 : Min. space from salicide block to contact.')
osb4_l1.forget

# Rule O.SB.5a is not a DRC check
## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_10.html

# Rule O.SB.5b_LV: Min. space from salicide block to unrelated Poly2 on COMP. is 0.1µm
logger.info('Executing rule O.SB.5b_LV')
sab_otp_lv = sab_otp.not_interacting(v5_xtor).not_interacting(dualgate)
osb5b_l1 = sab_otp_lv.outside(tgate).separation(tgate.outside(sab), 0.1.um, euclidian)
osb5b_l1.output('O.SB.5b_LV', 'O.SB.5b_LV : Min. space from salicide block to unrelated Poly2 on COMP. : 0.1µm')
osb5b_l1.forget
sab_otp_lv.forget

# Rule O.SB.5b_MV is not a DRC check
## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_10.html

# Rule O.SB.9: Min. salicide block extension beyond unsalicided Poly2. is 0.1µm
logger.info('Executing rule O.SB.9')
osb9_l1 = poly_otp.enclosed(sab_otp, 0.1.um, euclidian)
osb9_l1.output('O.SB.9', 'O.SB.9 : Min. salicide block extension beyond unsalicided Poly2. : 0.1µm')
osb9_l1.forget

# Rule O.SB.11: Min. salicide block overlap with COMP. is 0.04µm
logger.info('Executing rule O.SB.11')
osb11_l1 = sab_otp.overlap(comp, 0.04.um, euclidian)
osb11_l1.output('O.SB.11', 'O.SB.11 : Min. salicide block overlap with COMP. : 0.04µm')
osb11_l1.forget

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

# Rule O.SB.13_LV: Min. area of silicide block (um2). is 1.488µm²
logger.info('Executing rule O.SB.13_LV')
osb13_l1 = sab_otp.with_area(nil, 1.488.um).not_interacting(v5_xtor).not_interacting(dualgate)
osb13_l1.output('O.SB.13_LV', 'O.SB.13_LV : Min. area of silicide block (um2). : 1.488µm²')
osb13_l1.forget

# Rule O.SB.13_MV: Min. area of silicide block (um2). is 2µm²
logger.info('Executing rule O.SB.13_MV')
osb13_l1 = sab_otp.and(v5_xtor).with_area(nil, 2.um)
osb13_l1.output('O.SB.13_MV', 'O.SB.13_MV : Min. area of silicide block (um2). : 2µm²')
osb13_l1.forget

# Rule O.SB.15b is not a DRC check
## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_10.html

# Rule O.CO.7: Min. space from COMP contact to Poly2 on COMP. is 0.13µm
logger.info('Executing rule O.CO.7')
oco7_l1 = contact.not_outside(comp_otp).separation(tgate.and(otp_mk), 0.13.um, euclidian)
oco7_l1.output('O.CO.7', 'O.CO.7 : Min. space from COMP contact to Poly2 on COMP. : 0.13µm')
oco7_l1.forget

# Rule O.PL.ORT: Orientation-restricted gates must have the gate width
## aligned along the X-axis (poly line running horizontally)
## in reference to wafer notch down.
logger.info('Executing rule O.PL.ORT')
oplort_l1 = comp_otp.not(poly_otp).edges.and(tgate_edges).without_angle(0.um).not_interacting(v5_xtor)
oplort_l1.output('O.PL.ORT', 'O.PL.ORT : Orientation-restricted gates must have the gate width
aligned along the X-axis (poly line running horizontally)
in reference to wafer notch down.')
oplort_l1.forget
tgate_edges.forget
end
Binary file added klayout/drc/testing/testcases/unit/otp_mk.gds
Binary file not shown.
Loading

0 comments on commit f4fac8b

Please sign in to comment.