| ################################################################################################ |
| # 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 |