blob: 0ced59d7ce4b15743c6c15eba571f44d43b8924b [file] [log] [blame]
################################################################################################
# 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
#================================================
#---------------------POLY2----------------------
#================================================
# Rule PL.1_LV: Min Interconnect Width (outside PLFUSE). is 0.18µm
logger.info('Executing rule PL.1_LV')
pl1_l1 = poly2.outside(plfuse).width(0.18.um, euclidian).polygons(0.001).not_interacting(v5_xtor).not_interacting(dualgate2_d)
pl1_l1.output('PL.1_LV', 'PL.1_LV : Min. Interconnect Width (outside PLFUSE). : 0.18µm')
pl1_l1.forget
# Rule PL.1_MV Min Interconnect Width (outside PLFUSE). is 0.2µm
logger.info('Executing rule PL.1_MV')
pl1_l1 = poly2.outside(plfuse).width(0.2.um, euclidian).polygons(0.001).overlapping(dualgate2_d)
pl1_l1.output('PL.1_MV', 'PL.1_MV : Min Interconnect Width (outside PLFUSE). : 0.2µm')
pl1_l1.forget
# Rule PL.1a_LV: Interconnect Width (inside PLFUSE). is 0.18µm
logger.info('Executing rule PL.1a_LV')
pl1a_l1 = poly2.inside(plfuse).width(0.18.um, euclidian).polygons(0.001).not_interacting(v5_xtor).not_interacting(dualgate2_d)
pl1a_l1.output('PL.1a_LV', 'PL.1a_LV : Interconnect Width (inside PLFUSE). : 0.18µm')
pl1a_l1.forget
# Rule PL.1a_MV: Interconnect Width (inside PLFUSE). is 0.18µm
logger.info('Executing rule PL.1a_MV')
pl1a_l1 = poly2.inside(plfuse).width(0.18.um, euclidian).polygons(0.001).overlapping(dualgate2_d)
pl1a_l1.output('PL.1a_MV', 'PL.1a_MV : Interconnect Width (inside PLFUSE). : 0.18µm')
pl1a_l1.forget
# Rule PL.2a_LV: Min. Gate Width (Channel Length). is 0.18µm
logger.info('Executing rule PL.2a_LV')
pl2_l1 = poly2.edges.and(tgate.edges).not(otp_mk).width(0.18.um, euclidian).polygons(0.001).not_interacting(v5_xtor).not_interacting(dualgate2_d)
pl2_l1.output('PL.2a_LV', 'PL.2a_LV : Min. Gate Width (Channel Length). : 0.18µm')
pl2_l1.forget
# Rule PL.2a_5V: Min. Gate Width (Channel Length). is 0.5µm
logger.info('Executing rule PL.2a_5V')
pl2_l1 = poly2.edges.and(tgate.edges).not(otp_mk).width(0.5.um, euclidian).polygons(0.001).overlapping(dualgate2_d).interacting(v5_xtor).not_interacting(mos_mk_type1)
pl2_l1.output('PL.2a_5V', 'PL.2a_5V : Min. Gate Width (Channel Length). : 0.5µm')
pl2_l1.forget
# Rule PL.2a_5V_Sub_nominal : Min. Gate Width (Channel Length). is 0.4µm
logger.info('Executing rule PL.2a_5V_Sub_nominal')
pl2_l1 = poly2.edges.and(tgate.edges).not(otp_mk).width(0.4.um, euclidian).polygons(0.001).overlapping(dualgate2_d).interacting(v5_xtor).interacting(mos_mk_type1)
pl2_l1.output('PL.2a_5V_Sub_nominal', 'PL.2a_MV_5V_Sub_nominal : Min. Gate Width (Channel Length). : 0.4µm')
pl2_l1.forget
# Rule PL.2a_6V: Min. Gate Width (Channel Length). is 0.6µm
logger.info('Executing rule PL.2a_6V')
pl2_l1 = poly2.edges.and(tgate.edges).not(otp_mk).width(0.6.um, euclidian).polygons(0.001).overlapping(dualgate2_d).not_interacting(v5_xtor)
pl2_l1.output('PL.2a_6V', 'PL.2a_6V : Min. Gate Width (Channel Length). : 0.6µm')
pl2_l1.forget
# Rule PL.2b_6V: Min. Gate Width (Channel Length) for OTP cell . is 0.45µm
logger.info('Executing rule PL.2b_6V')
pl2_l1 = poly2.edges.and(tgate.edges).width(0.45.um, euclidian).polygons(0.001).interacting(otp_mk).overlapping(dualgate2_d).not_interacting(v5_xtor)
pl2_l1.output('PL.2b_6V', 'PL.2b_6V : Min. Gate Width (Channel Length). : 0.45µm')
pl2_l1.forget
# Rule PL.3a_LV: Space on COMP/Field. is 0.25µm
logger.info('Executing rule PL.3a_LV')
pl3a_l1 = (tgate).or(poly2.not(comp)).not(otp_mk).space(0.25.um, euclidian).polygons(0.001).not_interacting(v5_xtor).not_interacting(dualgate2_d)
pl3a_l1.output('PL.3a_LV', 'PL.3a_LV : Space on COMP/Field. : 0.25µm')
pl3a_l1.forget
# Rule PL.3a_MV_comp: Space on COMP. is 0.4µm
logger.info('Executing rule PL.3a_MV_comp')
pl3a_l1 = (tgate).not(otp_mk).space(0.4.um, euclidian).polygons(0.001).overlapping(dualgate2_d)
pl3a_l1.output('PL.3a_MV_comp', 'PL.3a_MV_comp : Space on COMP. : 0.4µm')
pl3a_l1.forget
# Rule PL.3a_MV_field: Space on Field. is 0.25µm
logger.info('Executing rule PL.3a_MV_field')
pl3a_l1 = (poly2.not(comp)).not(otp_mk).space(0.25.um, euclidian).polygons(0.001).overlapping(dualgate2_d)
pl3a_l1.output('PL.3a_MV_field', 'PL.3a_MV_field : Space on Field. : 0.25µm')
pl3a_l1.forget
# # rule PL.3b_LV is not a DRC check
# # rule PL.3b_MV is not a DRC check
poly_pl = poly2.not(otp_mk).not(mvsd).not(mvpsd)
comp_pl = comp.not(otp_mk).not(mvsd).not(mvpsd)
# Rule PL.4_LV: Extension beyond COMP to form Poly2 end cap. is 0.22µm
logger.info('Executing rule PL.4_LV')
pl4_l1 = poly_pl.enclosing(comp.not(otp_mk), 0.22.um, euclidian).polygons(0.001).not_interacting(v5_xtor).not_interacting(dualgate2_d)
pl4_l1.output('PL.4_LV', 'PL.4_LV : Extension beyond COMP to form Poly2 end cap. : 0.22µm')
pl4_l1.forget
# Rule PL.4_MV: Extension beyond COMP to form Poly2 end cap. is 0.22µm
logger.info('Executing rule PL.4_MV')
pl4_l1 = poly_pl.enclosing(comp.not(otp_mk), 0.22.um, euclidian).polygons(0.001).overlapping(dualgate2_d)
pl4_l1.output('PL.4_MV', 'PL.4_MV : Extension beyond COMP to form Poly2 end cap. : 0.22µm')
pl4_l1.forget
# Rule PL.5a_LV: Space from field Poly2 to unrelated COMP Spacer from field Poly2 to Guard-ring. is 0.1µm
logger.info('Executing rule PL.5a_LV')
pl5a_l1 = poly_pl.separation(comp_pl, 0.1.um, euclidian).polygons(0.001).not_interacting(v5_xtor).not_interacting(dualgate2_d)
pl5a_l1.output('PL.5a_LV', 'PL.5a_LV : Space from field Poly2 to related/unrelated COMP Spacer from field Poly2 to Guard-ring. : 0.1µm')
pl5a_l1.forget
# Rule PL.5a_MV: Space from field Poly2 to unrelated COMP Spacer from field Poly2 to Guard-ring. is 0.3µm
logger.info('Executing rule PL.5a_MV')
pl5a_l1 = poly_pl.outside(sramcore).separation(comp_pl, 0.3.um, euclidian).polygons(0.001).overlapping(dualgate2_d)
pl5a_l1.output('PL.5a_MV', 'PL.5a_MV : Space from field Poly2 to related/unrelated COMP Spacer from field Poly2 to Guard-ring. : 0.3µm')
pl5a_l1.forget
# Rule PL.5b_LV: Space from field Poly2 to related COMP. is 0.1µm
logger.info('Executing rule PL.5b_LV')
pl5b_l1 = poly_pl.separation(comp_pl, 0.1.um, euclidian).polygons(0.001).not_interacting(v5_xtor).not_interacting(dualgate2_d)
pl5b_l1.output('PL.5b_LV', 'PL.5b_LV : Space from field Poly2 to related/unrelated COMP. : 0.1µm')
pl5b_l1.forget
# Rule PL.5b_MV: Space from field Poly2 to related COMP. is 0.3µm
logger.info('Executing rule PL.5b_MV')
pl5b_l1 = poly_pl.outside(sramcore).separation(comp_pl.interacting(poly_pl), 0.3.um, euclidian).polygons(0.001).overlapping(dualgate2_d)
pl5b_l1.output('PL.5b_MV', 'PL.5b_MV : Space from field Poly2 to related COMP. : 0.3µm')
pl5b_l1.forget
poly_pl.forget
comp_pl.forget
poly_90deg = tgate.corners(90.0).sized(0.1)
# Rule PL.6: 90 degree bends on the COMP are not allowed.
logger.info('Executing rule PL.6')
pl6_l1 = poly_90deg.inside(comp)
pl6_l1.output('PL.6', 'PL.6 : 90 degree bends on the COMP are not allowed.')
pl6_l1.forget
poly_90deg.forget
poly_45deg = poly2.edges.with_angle(-45).or(poly2.edges.with_angle(45))
# Rule PL.7_LV: 45 degree bent gate width is 0.2µm
logger.info('Executing rule PL.7_LV')
pl7_l1 = poly_45deg.width(0.2.um, euclidian).polygons(0.001).not_interacting(v5_xtor).not_interacting(dualgate2_d)
pl7_l1.output('PL.7_LV', 'PL.7_LV : 45 degree bent gate width : 0.2µm')
pl7_l1.forget
# Rule PL.7_MV: 45 degree bent gate width is 0.7µm
logger.info('Executing rule PL.7_MV')
pl7_l1 = poly_45deg.width(0.7.um, euclidian).polygons(0.001).overlapping(dualgate2_d)
pl7_l1.output('PL.7_MV', 'PL.7_MV : 45 degree bent gate width : 0.7µm')
pl7_l1.forget
poly_45deg.forget
# Rule PL.10 : Minimum DNWELL overlap of Poly2 is 0.5µm
logger.info('Executing rule PL.10')
pl10_l1 = dnwell.enclosing(poly2,0.5.um).polygons(0.001)
pl10_l2 = poly2.not_outside(dnwell).not_inside(dnwell)
pl10_l = pl10_l1.or(pl10_l2)
pl10_l.output('PL.10','PL.10 : Minimum DNWELL overlap of Poly2 is 0.5µm ')
pl10_l1.forget
pl10_l2.forget
pl10_l.forget
# Rule PL.11: Poly2 inter-connect connecting LV and MV areas are not allowed
logger.info('Executing rule PL.11')
pl11_l1 = poly2.not_outside(dualgate2_d).not_inside(dualgate2_d)
pl11_l1.output('PL.11','PL.11 : Poly2 inter-connect connecting LV and MV areas are not allowed ')
pl11_l1.forget
# # rule PL.12a_LV is not a DRC check
#Rule PL.12a: V5_Xtor enclose 5V Comp.
logger.info('Executing rule PL.12a')
pl12_l1 = comp.interacting(v5_xtor).not(v5_xtor)
pl12_l1.output('PL.12a', 'PL.12a : V5_Xtor enclose 5V Comp.')
pl12_l1.forget
# Rule PL.12b: MOS_MK_TYPE1 enclose subnominal 5V Comp
logger.info('Executing rule PL.12b')
pl12_l2 = comp.interacting(mos_mk_type1).not(mos_mk_type1)
pl12_l2.output('PL.12b','PL.12b : MOS_MK_TYPE1 enclose subnominal 5V Comp ')
pl12_l2.forget
end #FEOL