blob: 7efb6e27363cf73d058f8385cb15370c681986ac [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------------------------
#===============================================
logger.info('Starting POLY2 derivations')
poly2_lv = poly2.not_interacting(v5_xtor).not_interacting(dualgate_2)
poly2_mv = poly2.overlapping(dualgate_2)
poly_pl_lv = poly2_lv.not(otp_mk)
poly_pl_mv = poly2_mv.not(otp_mk)
# Rule PL.1_LV: Interconnect Width is 0.18µm
logger.info('Executing rule PL.1_LV')
pl1_l1 = poly2.outside(sramcore).not_interacting(v5_xtor).not_interacting(dualgate_2).width(0.18.um, euclidian).polygons(0.001)
pl1_l1.output('PL.1_LV', 'PL.1_LV : Interconnect Width : 0.18µm')
pl1_l1.forget
# Rule PL.1_MV: Interconnect Width (outside PLFUSE). is 0.2µm
logger.info('Executing rule PL.1_5V')
pl1_l1 = poly2.outside(sramcore).not_interacting(dualgate).overlapping(dualgate_2).width(0.2.um, euclidian).polygons(0.001)
pl1_l1.output('PL.1_MV', 'PL.1_MV : Interconnect Width : 0.2µm')
pl1_l1.forget
# Rule PL.2a_LV_1.8V: Gate Width (Channel Length). is 0.18µm
logger.info('Executing rule PL.2a_LV_1.8V')
pl2a_1p8_l1 = tgate.not_interacting(dualgate.or(dualgate_2)).not(otp_mk).width(0.18.um, euclidian).polygons(0.001)
pl2a_1p8_l1.output('PL.2a_LV_1.8V', 'PL.2a_LV_1.8V : Gate Width (Channel Length). : 0.18µm')
pl2a_1p8_l1.forget
# Rule PL.2a_LV_3.3V: Gate Width (Channel Length). is 0.35µm for NMOS and 0.30 for PMOS
logger.info('Executing rule PL.2a_LV_3.3V')
pl2a_3p3_l1 = ngate.overlapping(dualgate).not_interacting(dualgate_2).not(otp_mk).width(0.35.um, euclidian).polygons(0.001)
pl2a_3p3_l2 = pgate.overlapping(dualgate).not_interacting(dualgate_2).not(otp_mk).width(0.30.um, euclidian).polygons(0.001)
pl2a_3p3_l = pl2a_3p3_l1.or(pl2a_3p3_l2)
pl2a_3p3_l.output('PL.2a_LV_3.3V', 'PL.2a_LV_3.3V : Gate Width (Channel Length). is 0.35µm for NMOS and 0.30 for PMOS')
pl2a_3p3_l1.forget
pl2a_3p3_l2.forget
pl2a_3p3_l.forget
# Rule PL.2a_MV_5V: Gate Width (Channel Length). is 0.5µm
logger.info('Executing rule PL.2a_MV_5V')
pl2a_5p0_l1 = tgate.not_interacting(dualgate).overlapping(dualgate_2).overlapping(v5_xtor).not(otp_mk).width(0.5.um, euclidian).polygons(0.001)
pl2a_5p0_l1.output('PL.2a_MV_5V', 'PL.2a_MV_5V : Gate Width (Channel Length). : 0.5µm')
pl2a_5p0_l1.forget
# Rule PL.2a_MV_6V: Gate Width (Channel Length). is 0.6µm
logger.info('Executing rule PL.2a_MV_6V')
pl2a_6p0_l1 = tgate.not_interacting(dualgate.or(v5_xtor) ).overlapping(dualgate_2).not(otp_mk).width(0.6.um, euclidian).polygons(0.001)
pl2a_6p0_l1.output('PL.2a_MV_6V', 'PL.2a_MV_6V : Gate Width (Channel Length). : 0.6µm')
pl2a_6p0_l1.forget
# Rule PL.2b_LV_3.3V : Gate width for OTP cell area (identified by OTP_MK). 0.27 for PMOS
logger.info('Executing rule PL.2b_LV_3.3V')
pl2b_3p3_l1 = pgate.overlapping(dualgate).not_interacting(dualgate_2).interacting(otp_mk).width(0.27.um, euclidian).polygons(0.001)
pl2b_3p3_l1.output('PL.2b_LV_3.3V','PL.2b_LV_3.3V : Gate width for OTP cell area (identified by OTP_MK). 0.27 for PMOS')
pl2b_3p3_l1.forget
# Rule PL.3ai_LV: Space on COMP. is 0.25µm
logger.info('Executing rule PL.3ai_LV')
pl3ai_l1 = (tgate).not(otp_mk).not_interacting(dualgate_2).space(0.25.um, euclidian).polygons(0.001)
pl3ai_l1.output('PL.3ai_LV', 'PL.3ai_LV : Space on COMP : 0.25µm')
pl3ai_l1.forget
# Rule PL.3ai_MV: Space on COMP. is 0.4µm
logger.info('Executing rule PL.3ai_MV')
pl3ai_l1 = (tgate).not(otp_mk).not_interacting(dualgate).overlapping(dualgate_2).space(0.4.um, euclidian).polygons(0.001)
pl3ai_l1.output('PL.3ai_MV', 'PL.3ai_MV : Space on COMP : 0.4µm')
pl3ai_l1.forget
# Rule PL.3aii_LV: Space on Field. is 0.25µm
logger.info('Executing rule PL.3aii_LV')
pl3aii_l1 = (poly2.not(comp)).outside(sramcore).not_interacting(dualgate_2).not(otp_mk).space(0.25.um, euclidian).polygons(0.001)
pl3aii_l1.output('PL.3aii_LV', 'PL.3aii_LV : Space on Field. : 0.25µm')
pl3aii_l1.forget
# Rule PL.3aii_MV: Space on Field. is 0.25µm
logger.info('Executing rule PL.3aii_LV')
pl3aii_l1 = (poly2.not(comp)).outside(sramcore).not_interacting(dualgate).overlapping(dualgate_2).not(otp_mk).space(0.25.um, euclidian).polygons(0.001)
pl3aii_l1.output('PL.3aii_MV', 'PL.3aii_MV : Space on Field. : 0.25µm')
pl3aii_l1.forget
# Rule PL.4_LV: Extension beyond COMP to form Poly2 end cap. is 0.22µm
logger.info('Executing rule PL.4_LV')
comp_pl = comp.not(otp_mk)
pl4_l1 = comp_pl.enclosed(poly_pl_lv, 0.22.um, euclidian)
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 = comp_pl.enclosed(poly_pl_mv, 0.22.um, euclidian)
pl4_l1.output('PL.4_MV', 'PL.4_MV : Extension beyond COMP to form Poly2 end cap. : 0.22µm')
pl4_l1.forget
poly_pl = poly2.not(otp_mk)
comp_pl = comp.not(otp_mk)
# 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.not_interacting(dualgate_2).separation(comp_pl.not_interacting(poly_pl), 0.1.um, euclidian).polygons(0.001)
pl5a_l1.output('PL.5a_LV', 'PL.5a_LV : Space from field Poly2 to 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.not_interacting(dualgate).overlapping(dualgate_2).outside(sramcore).separation(comp_pl.not_interacting(poly_pl), 0.3.um, euclidian).polygons(0.001)
pl5a_l1.output('PL.5a_MV', 'PL.5a_MV : Space from field Poly2 to 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.outside(sramcore).not_interacting(dualgate_2).separation(comp_pl.interacting(poly_pl), 0.1.um, euclidian).polygons(0.001)
pl5b_l1.output('PL.5b_LV', 'PL.5b_LV : Space from field Poly2 to related 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).not_interacting(dualgate).overlapping(dualgate_2).outside(sramcore).separation(comp_pl.interacting(poly_pl), 0.3.um, euclidian).polygons(0.001)
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
# Rule PL.7_LV_1.8V: 45 degree bent gate width is 0.2µm
logger.info('Executing rule PL.7_LV_1.8V')
nom_e1 = tgate.not_interacting(dualgate.or(dualgate_2)).edges.inside_part(comp).with_angle(45)
nom_e2 = tgate.not_interacting(dualgate.or(dualgate_2)).edges.inside_part(comp).with_angle(-45)
pl7_edges_nom = nom_e1.or(nom_e2)
pl7_l1 = pl7_edges_nom.width(0.2.um, euclidian)
pl7_l1.output('PL.7_LV_1.8V', 'PL.7_LV_1.8V : 45 degree bent gate width : 0.2µm')
pl7_l1.forget
nom_e1.forget
nom_e2.forget
pl7_edges_nom.forget
# Rule PL.7_LV_3.3V: 45 degree bent gate width is 0.4µm
logger.info('Executing rule PL.7_LV_3.3V')
nom_e1 = tgate.overlapping(dualgate).not_interacting(dualgate_2).edges.inside_part(comp).with_angle(45)
nom_e2 = tgate.overlapping(dualgate).not_interacting(dualgate_2).edges.inside_part(comp).with_angle(-45)
pl7_edges_nom = nom_e1.or(nom_e2)
pl7_l1 = pl7_edges_nom.width(0.4.um, euclidian)
pl7_l1.output('PL.7_LV_3.3V', 'PL.7_LV_3.3V : 45 degree bent gate width : 0.4µm')
pl7_l1.forget
nom_e1.forget
nom_e2.forget
pl7_edges_nom.forget
# Rule PL.7_MV: 45 degree bent gate width is 0.7µm
logger.info('Executing rule PL.7_MV')
thick_e1 = tgate.not_interacting(dualgate).overlapping(dualgate_2).edges.inside_part(comp).with_angle(25, 65)
thick_e2 = tgate.not_interacting(dualgate).overlapping(dualgate_2).edges.inside_part(comp).with_angle(-65, -25)
pl7_edges_thick = thick_e1.or(thick_e2)
pl7_l2 = pl7_edges_thick.width(0.7.um, euclidian)
pl7_l2.output('PL.7_MV', 'PL.7_MV : 45 degree bent gate width : 0.7µm')
pl7_l2.forget
thick_e1.forget
thick_e2.forget
pl7_edges_thick.forget
# Rule PL.9: V5_Xtor must enclose 5V device.
logger.info('Executing rule PL.9')
pl9_l1 = v5_xtor.not_inside(dualgate_2.or(otp_mk))
pl9_l1.output('PL.9', 'PL.9 : V5_Xtor must enclose 5V device.')
pl9_l1.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 interconnect connecting LV and MV areas (area inside and outside DV2/Dualgate) are not allowed. They shall be done though metal lines only.
logger.info('Executing rule PL.11')
pl11_l1 = poly2.interacting(poly2.not(v5_xtor).not(dualgate.or(dualgate_2))).interacting(poly2.and(dualgate.or(dualgate_2)))
pl11_l1.output('PL.11', 'PL.11 : Poly2 interconnect connecting LV and MV areas (area inside and outside DV2/Dualgate) are not allowed. They shall be done though metal lines only.')
pl11_l1.forget
# Rule PL.12: V5_Xtor enclose 5V Comp.
logger.info('Executing rule PL.12')
pl12_l1 = comp.interacting(v5_xtor).not(v5_xtor)
pl12_l1.output('PL.12', 'PL.12 : V5_Xtor enclose 5V Comp.')
pl12_l1.forget
end #FEOL