| ############################################################################################### |
| # 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 |
| |
| #================================================ |
| #---------------------PPLUS---------------------- |
| #================================================ |
| |
| # Rule PP.1: min. pplus width is 0.4µm |
| logger.info('Executing rule PP.1') |
| pp1_l1 = pplus.width(0.4.um, euclidian).polygons(0.001) |
| pp1_l1.output('PP.1', 'PP.1 : min. pplus width : 0.4µm') |
| pp1_l1.forget |
| |
| # Rule PP.2: min. pplus spacing is 0.4µm |
| logger.info('Executing rule PP.2') |
| pp2_l1 = pplus.space(0.4.um, euclidian).polygons(0.001) |
| pp2_l1.output('PP.2', 'PP.2 : min. pplus spacing : 0.4µm') |
| pp2_l1.forget |
| |
| # Rule PP.3a: Space to NCOMP for NCOMP outside NWELL. is 0.16µm |
| logger.info('Executing rule PP.3a') |
| pp3a_l1 = pplus.separation(ncomp.outside(nwell), 0.16.um, euclidian).polygons(0.001) |
| pp3a_l1.output('PP.3a', 'PP.3a : Space to NCOMP for NCOMP outside NWELL. : 0.16µm') |
| pp3a_l1.forget |
| |
| |
| pp_3b_extend = nwell.sized(-0.429.um) |
| pp_3b = ncomp.edges.and(pp_3b_extend) |
| # Rule PP.3b: Space to NCOMP: For inside Nwell: NWELL Overlap of NCOMP >= 0.43um. is 0.08µm |
| logger.info('Executing rule PP.3b') |
| pp3b_l1 = pplus.inside(nwell).edges.separation(pp_3b, 0.08.um, euclidian).polygons(0.001) |
| pp3b_l1.output('PP.3b', 'PP.3b : Space to NCOMP: For inside Nwell: NWELL Overlap of NCOMP >= 0.43um. : 0.08µm') |
| pp3b_l1.forget |
| |
| pp_3b_extend.forget |
| pp_3b.forget |
| |
| pp_3c_extend = nwell.not(nwell.sized(-0.429.um)) |
| pp_3c = ncomp.edges.and(pp_3c_extend) |
| # Rule PP.3c: Space to NCOMP: For inside Nwell: NWELL Overlap of NCOMP 0.43um. is 0.16µm |
| logger.info('Executing rule PP.3c') |
| pp3c_l1 = pplus.inside(nwell).edges.separation(pp_3c, 0.16.um, euclidian).polygons(0.001) |
| pp3c_l1.output('PP.3c', 'PP.3c : Space to NCOMP: For inside Nwell: NWELL Overlap of NCOMP 0.43um. : 0.16µm') |
| pp3c_l1.forget |
| |
| pp_3c_extend.forget |
| pp_3c.forget |
| |
| # Rule PP.3d: Min/max space to a butted NCOMP. |
| logger.info('Executing rule PP.3d') |
| pp3d_l1 = pplus.not_outside(ncomp) |
| pp3d_l1.output('PP.3d', 'PP.3d : Min/max space to a butted NCOMP.') |
| pp3d_l1.forget |
| |
| # Rule PP.3e: Space to NCOMP edge adjacent to a butting edge. |
| logger.info('Executing rule PP.3e') |
| pp3e_l1 = pplus.not_outside(ncomp) |
| pp3e_l1.output('PP.3e', 'PP.3e : Space to NCOMP edge adjacent to a butting edge.') |
| pp3e_l1.forget |
| |
| # Rule PP.4a: Space related to N-channel gate at a butting edge parallel to gate. is 0.32µm |
| logger.info('Executing rule PP.4a') |
| pp4a_l1 = pplus.edges.and(ncomp.edges).separation(ngate.edges, 0.32.um, projection).polygons(0.001) |
| pp4a_l1.output('PP.4a', 'PP.4a : Space related to N-channel gate at a butting edge parallel to gate. : 0.32µm') |
| pp4a_l1.forget |
| |
| pp_4b_poly = poly2.edges.interacting(ngate.edges.not(ncomp.edges)).centers(0, 0.99).and(ngate.sized(0.32.um)) |
| # Rule PP.4b: Within 0.32um of channel, space to N-channel gate extension perpendicular to the direction of Poly2. |
| logger.info('Executing rule PP.4b') |
| pp4b_l1 = pplus.interacting(pplus.edges.separation(pp_4b_poly, 0.22.um, projection).polygons(0.001)) |
| pp4b_l1.output('PP.4b', 'PP.4b : Within 0.32um of channel, space to N-channel gate extension perpendicular to the direction of Poly2.') |
| pp4b_l1.forget |
| |
| pp_4b_poly.forget |
| |
| # Rule PP.5a: Overlap of P-channel gate. is 0.23µm |
| logger.info('Executing rule PP.5a') |
| pp5a_l1 = pplus.enclosing(pgate, 0.23.um, euclidian).polygons(0.001) |
| pp5a_l2 = pgate.not_outside(pplus).not(pplus) |
| pp5a_l = pp5a_l1.or(pp5a_l2) |
| pp5a_l.output('PP.5a', 'PP.5a : Overlap of P-channel gate. : 0.23µm') |
| pp5a_l1.forget |
| pp5a_l2.forget |
| pp5a_l.forget |
| |
| # Rule PP.5b: Extension beyond COMP Inside NWELL. is 0.16µm |
| logger.info('Executing rule PP.5b') |
| pp5b_l1 = pplus.not_outside(nwell).edges.enclosing(comp.not_outside(nwell).edges, 0.16.um, euclidian).polygons(0.001) |
| pp5b_l1.output('PP.5b', 'PP.5b : Extension beyond COMP for COMP Inside NWELL. is 0.16µm') |
| pp5b_l1.forget |
| |
| |
| pp_5c_background = pplus.edges.and(nwell.sized(0.429.um)) |
| # Rule PP.5c: Extension beyond COMP: For Pplus to NWELL space < 0.43um for Pfield or PWELL tap. is 0.16µm |
| logger.info('Executing rule PP.5c') |
| pp5c_l1 = pp_5c_background.enclosing(pcomp.edges, 0.16.um, projection).polygons(0.001) |
| pp5c_l1.output('PP.5c', 'PP.5c : Extension beyond COMP: For Pplus to NWELL space < 0.43um for Pfield or PWELL tap. : 0.16µm') |
| pp5c_l1.forget |
| pp_5c_background.forget |
| |
| pp_5d_background = pplus.edges |
| pp_5d_foreground = pcomp.edges.not(nwell.sized(0.429.um)) |
| # Rule PP.5d: Extension beyond COMP: For Pplus to NWELL space >= 0.43um for Pfield or PWELL tap. is 0.02µm |
| logger.info('Executing rule PP.5d') |
| pp5d_l1 = pp_5d_background.enclosing(pp_5d_foreground, 0.02.um, projection).polygons(0.001) |
| pp5d_l1.output('PP.5d', 'PP.5d : Extension beyond COMP: For Pplus to NWELL space >= 0.43um for Pfield or PWELL tap. : 0.02µm') |
| pp5d_l1.forget |
| |
| pp_5d_background.forget |
| pp_5d_foreground.forget |
| |
| # Rule PP.6: Overlap with PCOMP butted to NCOMP. is 0.22µm |
| logger.info('Executing rule PP.6') |
| pp6_l1 = comp.interacting(pplus).enclosing(ncomp.interacting(pplus), 0.22.um, projection).polygons |
| pp6_l1.output('PP.6', 'PP.6 : Overlap with PCOMP butted to NCOMP. : 0.22µm') |
| pp6_l1.forget |
| |
| # Rule PP.7: Space to unrelated unsalicided Poly2. is 0.18µm |
| logger.info('Executing rule PP.7') |
| pp7_l1 = pplus.separation(poly2.and(sab), 0.18.um, euclidian).polygons(0.001) |
| pp7_l1.output('PP.7', 'PP.7 : Space to unrelated unsalicided Poly2. : 0.18µm') |
| pp7_l1.forget |
| |
| # Rule PP.8a: Minimum Pplus area (um2). is 0.35µm² |
| logger.info('Executing rule PP.8a') |
| pp8a_l1 = pplus.with_area(nil, 0.35.um) |
| pp8a_l1.output('PP.8a', 'PP.8a : Minimum Pplus area (um2). : 0.35µm²') |
| pp8a_l1.forget |
| |
| # Rule PP.8b: Minimum area enclosed by Pplus (um2). is 0.35µm² |
| logger.info('Executing rule PP.8b') |
| pp8b_l1 = pplus.holes.with_area(nil, 0.35.um) |
| pp8b_l1.output('PP.8b', 'PP.8b : Minimum area enclosed by Pplus (um2). : 0.35µm²') |
| pp8b_l1.forget |
| |
| # Rule PP.9: Overlap of unsalicided Poly2. is 0.18µm |
| logger.info('Executing rule PP.9') |
| pp9_l1 = pplus.enclosing(poly2.not_interacting(resistor).and(sab), 0.18.um, euclidian).polygons(0.001) |
| pp9_l2 = poly2.not_interacting(resistor).and(sab).not_outside(pplus).not(pplus) |
| pp9_l = pp9_l1.or(pp9_l2) |
| pp9_l.output('PP.9', 'PP.9 : Overlap of unsalicided Poly2. : 0.18µm') |
| pp9_l1.forget |
| pp9_l2.forget |
| pp9_l.forget |
| |
| # Rule PP.10: Overlap of unsalicided COMP. is 0.18µm |
| logger.info('Executing rule PP.10') |
| pp10_l1 = pplus.enclosing(comp.and(sab), 0.18.um, euclidian).polygons(0.001) |
| pp10_l1.output('PP.10', 'PP.10 : Overlap of unsalicided COMP. : 0.18µm') |
| pp10_l1.forget |
| |
| # Rule PP.11: Butting Pplus and NCOMP is forbidden within 0.43um of Nwell edge. |
| logger.info('Executing rule PP.11') |
| pp11_l1 = pplus.interacting(pplus.edges.and(ncomp.edges).and(nwell.not(nwell.sized(-0.429.um)))) |
| pp11_l1.output('PP.11', 'PP.11 : Butting Pplus and NCOMP is forbidden within 0.43um of Nwell edge.') |
| pp11_l1.forget |
| |
| # Rule PP.12: Overlap with N-channel Poly2 gate extension is forbidden within 0.32um of N-channel gate. |
| logger.info('Executing rule PP.12') |
| pp12_l1 = pplus.interacting(pplus.edges.separation(ngate.edges.and(ncomp.edges), 0.32.um, euclidian).polygons(0.001)) |
| pp12_l1.output('PP.12', 'PP.12 : Overlap with N-channel Poly2 gate extension is forbidden within 0.32um of N-channel gate.') |
| pp12_l1.forget |
| |
| end #FEOL |