blob: 9466298b3e00b95ff8fead0f6f629e533a78e33d [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
#================================================
#---------------------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