| ############################################################################################### |
| # 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 |
| |
| #================================================ |
| #---------------------NPLUS---------------------- |
| #================================================ |
| |
| # Rule NP.1: min. nplus width is 0.4µm |
| logger.info('Executing rule NP.1') |
| np1_l1 = nplus.width(0.4.um, euclidian).polygons(0.001) |
| np1_l1.output('NP.1', 'NP.1 : min. nplus width : 0.4µm') |
| np1_l1.forget |
| |
| # Rule NP.2: min. nplus spacing is 0.4µm |
| logger.info('Executing rule NP.2') |
| np2_l1 = nplus.space(0.4.um, euclidian).polygons(0.001) |
| np2_l1.output('NP.2', 'NP.2 : min. nplus spacing : 0.4µm') |
| np2_l1.forget |
| |
| # Rule NP.3a: Space to PCOMP for PCOMP Inside Nwell. is 0.16µm |
| logger.info('Executing rule NP.3a') |
| np3a_l1 = nplus.separation(pcomp.inside(nwell), 0.16.um, euclidian).polygons(0.001) |
| np3a_l1.output('NP.3a', 'NP.3a : Space to PCOMP for PCOMP Inside Nwell. : 0.16µm') |
| np3a_l1.forget |
| |
| np_3b = pcomp.edges.not(nwell.sized(0.429.um)) |
| # Rule NP.3b: Space to PCOMP for PCOMP space to Nwell >= 0.43um (outside Nwell). is 0.08µm |
| logger.info('Executing rule NP.3b') |
| np3b_l1 = nplus.outside(nwell).edges.separation(np_3b, 0.08.um, euclidian).polygons |
| np3b_l1.output('NP.3b', 'NP.3b : Space to PCOMP for PCOMP space to Nwell >= 0.43um. : 0.08µm') |
| np3b_l1.forget |
| |
| np_3b.forget |
| |
| np_3c = pcomp.edges.and(nwell.sized(0.429.um)) |
| # Rule NP.3c: Space to PCOMP for PCOMP space to Nwell < 0.43um (outside Nwell). is 0.16µm |
| logger.info('Executing rule NP.3c') |
| np3c_l1 = nplus.outside(nwell).edges.separation(np_3c, 0.16.um, euclidian).polygons |
| np3c_l1.output('NP.3c', 'NP.3c : Space to PCOMP for PCOMP space to Nwell < 0.43um. : 0.16µm') |
| np3c_l1.forget |
| |
| np_3c.forget |
| |
| # Rule NP.3d: Min/max space to a butted PCOMP. |
| logger.info('Executing rule NP.3d') |
| np3d_l1 = nplus.not_outside(pcomp) |
| np3d_l1.output('NP.3d', 'NP.3d : Min/max space to a butted PCOMP.') |
| np3d_l1.forget |
| |
| # Rule NP.3e: Space to related PCOMP edge adjacent to a butting edge. |
| logger.info('Executing rule NP.3e') |
| np3e_l1 = nplus.not_outside(pcomp) |
| np3e_l1.output('NP.3e', 'NP.3e : Space to related PCOMP edge adjacent to a butting edge.') |
| np3e_l1.forget |
| |
| # Rule NP.4a: Space to related P-channel gate at a butting edge parallel to gate. is 0.32µm |
| logger.info('Executing rule NP.4a') |
| np4a_l1 = nplus.edges.and(pcomp.edges).separation(pgate.edges, 0.32.um, projection).polygons(0.001) |
| np4a_l1.output('NP.4a', 'NP.4a : Space to related P-channel gate at a butting edge parallel to gate. : 0.32µm') |
| np4a_l1.forget |
| |
| np_4b_poly = poly2.edges.interacting(pgate.edges.not(pcomp.edges)).centers(0, 0.99).and(pgate.sized(0.32.um)) |
| # Rule NP.4b: Within 0.32um of channel, space to P-channel gate extension perpendicular to the direction of Poly2. is 0.22um |
| logger.info('Executing rule NP.4b') |
| np4b_l1 = nplus.interacting(nplus.edges.separation(np_4b_poly, 0.22.um, projection).polygons(0.001)) |
| np4b_l1.output('NP.4b', 'NP.4b : Within 0.32um of channel, space to P-channel gate extension perpendicular to the direction of Poly2. : 0.22um') |
| np4b_l1.forget |
| |
| np_4b_poly.forget |
| |
| # Rule NP.5a: Overlap of N-channel gate. is 0.23µm |
| logger.info('Executing rule NP.5a') |
| np5a_l1 = nplus.enclosing(ngate, 0.23.um, euclidian).polygons(0.001) |
| np5a_l2 = ngate.not_outside(nplus).not(nplus) |
| np5a_l = np5a_l1.or(np5a_l2) |
| np5a_l.output('NP.5a', 'NP.5a : Overlap of N-channel gate. : 0.23µm') |
| np5a_l1.forget |
| np5a_l2.forget |
| np5a_l.forget |
| |
| # Rule NP.5b: Extension beyond COMP for the COMP outside Nwell. is 0.16µm |
| logger.info('Executing rule NP.5b') |
| np5b_l1 = nplus.outside(nwell).edges.not(pplus).enclosing(comp.edges, 0.16.um, euclidian).polygons(0.001) |
| np5b_l1.output('NP.5b', 'NP.5b : Extension beyond COMP for the COMP outside Nwell. : 0.16µm') |
| np5b_l1.forget |
| |
| np_5c_background = nplus.not_outside(nwell).edges |
| np_5c_extend = nwell.not(nwell.sized(-0.429.um)) |
| np_5c_foreground = ncomp.not_outside(nwell).edges.not(pplus.edges).and(np_5c_extend) |
| # Rule NP.5c: Extension beyond COMP: inside Nwell: For Nwell overlap of Nplus < 0.43um. is 0.16µm |
| logger.info('Executing rule NP.5c') |
| np5c_l1 = np_5c_background.enclosing(np_5c_foreground, 0.16.um, projection).polygons(0.001) |
| np5c_l1.output('NP.5c', 'NP.5c : Extension beyond COMP: inside Nwell: For Nwell overlap of Nplus < 0.43um. : 0.16µm') |
| np5c_l1.forget |
| |
| np_5c_background.forget |
| np_5c_extend.forget |
| np_5c_foreground.forget |
| |
| np_5d_background = nplus.not_outside(nwell).edges.not(pplus.edges) |
| np_5d_extend = nwell.sized(-0.429.um) |
| np_5d_foreground = ncomp.not_outside(nwell).edges.not(pplus.edges).and(np_5d_extend) |
| # Rule NP.5d: Extension beyond COMP: inside Nwell: For Nwell overlap of Nplus >= 0.43um. is 0.02µm |
| logger.info('Executing rule NP.5d') |
| np5d_l1 = np_5d_background.enclosing(np_5d_foreground, 0.02.um, euclidian).polygons(0.001) |
| np5d_l1.output('NP.5d', 'NP.5d : Extension beyond COMP: inside Nwell: For Nwell overlap of Nplus >= 0.43um. : 0.02µm') |
| np5d_l1.forget |
| |
| np_5d_background.forget |
| np_5d_extend.forget |
| np_5d_foreground.forget |
| |
| # Rule NP.6: Overlap with NCOMP butted to PCOMP. is 0.22µm |
| logger.info('Executing rule NP.6') |
| np6_l1 = comp.interacting(nplus).enclosing(pcomp.interacting(nplus), 0.22.um, projection).polygons |
| np6_l1.output('NP.6', 'NP.6 : Overlap with NCOMP butted to PCOMP. : 0.22µm') |
| np6_l1.forget |
| |
| # Rule NP.7: Space to unrelated unsalicided Poly2. is 0.18µm |
| logger.info('Executing rule NP.7') |
| np7_l1 = nplus.separation(poly2.and(sab), 0.18.um, euclidian).polygons(0.001) |
| np7_l1.output('NP.7', 'NP.7 : Space to unrelated unsalicided Poly2. : 0.18µm') |
| np7_l1.forget |
| |
| # Rule NP.8a: Minimum Nplus area (um2). is 0.35µm² |
| logger.info('Executing rule NP.8a') |
| np8a_l1 = nplus.with_area(nil, 0.35.um) |
| np8a_l1.output('NP.8a', 'NP.8a : Minimum Nplus area (um2). : 0.35µm²') |
| np8a_l1.forget |
| |
| # Rule NP.8b: Minimum area enclosed by Nplus (um2). is 0.35µm² |
| logger.info('Executing rule NP.8b') |
| np8b_l1 = nplus.holes.with_area(nil, 0.35.um) |
| np8b_l1.output('NP.8b', 'NP.8b : Minimum area enclosed by Nplus (um2). : 0.35µm²') |
| np8b_l1.forget |
| |
| # Rule NP.9: Overlap of unsalicided Poly2. is 0.18µm |
| logger.info('Executing rule NP.9') |
| np9_l1 = nplus.enclosing(poly2.and(sab), 0.18.um, euclidian).polygons(0.001) |
| np9_l2 = poly2.and(sab).not_outside(nplus).not(nplus) |
| np9_l = np9_l1.or(np9_l2) |
| np9_l.output('NP.9', 'NP.9 : Overlap of unsalicided Poly2. : 0.18µm') |
| np9_l1.forget |
| np9_l2.forget |
| np9_l.forget |
| |
| # Rule NP.10: Overlap of unsalicided COMP. is 0.18µm |
| logger.info('Executing rule NP.10') |
| np10_l1 = nplus.enclosing(comp.and(sab), 0.18.um, euclidian).polygons(0.001) |
| np10_l1.output('NP.10', 'NP.10 : Overlap of unsalicided COMP. : 0.18µm') |
| np10_l1.forget |
| |
| # Rule NP.11: Butting Nplus and PCOMP is forbidden within 0.43um of Nwell edge. |
| logger.info('Executing rule NP.11') |
| np11_l1 = nplus.interacting(nplus.edges.and(pcomp.edges).and(nwell.sized(0.429.um))) |
| np11_l1.output('NP.11', 'NP.11 : Butting Nplus and PCOMP is forbidden within 0.43um of Nwell edge.') |
| np11_l1.forget |
| |
| |
| # Rule NP.12: Overlap with P-channel poly2 gate extension is forbidden within 0.32um of P-channel gate. |
| logger.info('Executing rule NP.12') |
| np12_l1 = nplus.interacting(nplus.edges.separation(pgate.edges.and(pcomp.edges), 0.32.um, euclidian).polygons(0.001)) |
| np12_l1.output('NP.12', 'NP.12 : Overlap with P-channel poly2 gate extension is forbidden within 0.32um of P-channel gate.') |
| np12_l1.forget |
| |
| end #FEOL |