blob: 1a3bdd4630151dbb7fd52d94e9d22f83bb72a2df [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
#================================================
#---------------------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: (1) Inside Nwell (2) Outside LVPWELL but inside DNWELL. is 0.16µm
logger.info('Executing rule NP.3a')
np3a_l1 = nplus.separation((pcomp.inside(nwell)).or(pcomp.outside(lvpwell).inside(dnwell)), 0.16.um, euclidian).polygons(0.001)
np3a_l1.output('NP.3a', 'NP.3a : Space to PCOMP for PCOMP: (1) Inside Nwell (2) Outside LVPWELL but inside DNWELL. : 0.16µm')
np3a_l1.forget
np_3bi_extend = lvpwell.inside(dnwell).sized(-0.429.um)
np_3bi = pcomp.edges.and(lvpwell.inside(dnwell).not(np_3bi_extend))
# Rule NP.3bi: Space to PCOMP: For Inside DNWELL, inside LVPWELL:(i) For PCOMP overlap by LVPWELL < 0.43um. is 0.16µm
logger.info('Executing rule NP.3bi')
np3bi_l1 = nplus.not_outside(lvpwell).inside(dnwell).edges.separation(np_3bi, 0.16.um, euclidian).polygons(0.001)
np3bi_l1.output('NP.3bi', 'NP.3bi : Space to PCOMP: For Inside DNWELL, inside LVPWELL:(i) For PCOMP overlap by LVPWELL < 0.43um. : 0.16µm')
np3bi_l1.forget
np_3bi_extend.forget
np_3bi.forget
np_3bii_extend = lvpwell.inside(dnwell).sized(-0.429.um)
np_3bii = pcomp.edges.and(np_3bii_extend)
# Rule NP.3bii: Space to PCOMP: For Inside DNWELL, inside LVPWELL:(ii) For PCOMP overlap by LVPWELL >= 0.43um. is 0.08µm
logger.info('Executing rule NP.3bii')
np3bii_l1 = nplus.not_outside(lvpwell).inside(dnwell).edges.separation(np_3bii, 0.08.um, euclidian).polygons(0.001)
np3bii_l1.output('NP.3bii', 'NP.3bii : Space to PCOMP: For Inside DNWELL, inside LVPWELL:(ii) For PCOMP overlap by LVPWELL >= 0.43um. : 0.08µm')
np3bii_l1.forget
np_3bii_extend.forget
np_3bii.forget
np_3ci = pcomp.edges.and(nwell.outside(dnwell).sized(0.429.um))
# Rule NP.3ci: Space to PCOMP: For Outside DNWELL:(i) For PCOMP space to Nwell < 0.43um. is 0.16µm
logger.info('Executing rule NP.3ci')
np3ci_l1 = nplus.outside(dnwell).edges.separation(np_3ci, 0.16.um, euclidian).polygons
np3ci_l1.output('NP.3ci', 'NP.3ci : Space to PCOMP: For Outside DNWELL:(i) For PCOMP space to Nwell < 0.43um. : 0.16µm')
np3ci_l1.forget
np_3ci.forget
np_3cii = pcomp.edges.not(nwell.outside(dnwell).sized(0.429.um))
# Rule NP.3cii: Space to PCOMP: For Outside DNWELL:(ii) For PCOMP space to Nwell >= 0.43um. is 0.08µm
logger.info('Executing rule NP.3cii')
np3cii_l1 = nplus.outside(dnwell).edges.separation(np_3cii, 0.08.um, euclidian).polygons
np3cii_l1.output('NP.3cii', 'NP.3cii : Space to PCOMP: For Outside DNWELL:(ii) For PCOMP space to Nwell >= 0.43um. : 0.08µm')
np3cii_l1.forget
np_3cii.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.
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.')
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 (1) inside LVPWELL (2) outside Nwell and DNWELL. is 0.16µm
logger.info('Executing rule NP.5b')
np5b_l1 = nplus.not_outside(lvpwell).or(nplus.outside(nwell).outside(dnwell)).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 (1) inside LVPWELL (2) outside Nwell and DNWELL. : 0.16µm')
np5b_l1.forget
np_5ci_background = nplus.not_inside(lvpwell).inside(dnwell).edges
np_5ci_foreground = ncomp.not_inside(lvpwell).inside(dnwell).edges.not(pplus.edges).and(lvpwell.inside(dnwell).sized(0.429.um))
# Rule NP.5ci: Extension beyond COMP: For Inside DNWELL: (i)For Nplus < 0.43um from LVPWELL edge for Nwell or DNWELL tap inside DNWELL. is 0.16µm
logger.info('Executing rule NP.5ci')
np5ci_l1 = np_5ci_background.enclosing(np_5ci_foreground, 0.16.um, projection).polygons(0.001)
np5ci_l1.output('NP.5ci', 'NP.5ci : Extension beyond COMP: For Inside DNWELL: (i)For Nplus < 0.43um from LVPWELL edge for Nwell or DNWELL tap inside DNWELL. : 0.16µm')
np5ci_l1.forget
np_5ci_background.forget
np_5ci_foreground.forget
np_5cii_background = nplus.not_inside(lvpwell).inside(dnwell).edges
np_5cii_foreground = ncomp.not_inside(lvpwell).inside(dnwell).edges.not(pplus.edges).not(lvpwell.inside(dnwell).sized(0.429.um))
# Rule NP.5cii: Extension beyond COMP: For Inside DNWELL: (ii) For Nplus >= 0.43um from LVPWELL edge for Nwell or DNWELL tap inside DNWELL. is 0.02µm
logger.info('Executing rule NP.5cii')
np5cii_l1 = np_5cii_background.enclosing(np_5cii_foreground, 0.02.um, projection).polygons(0.001)
np5cii_l1.output('NP.5cii', 'NP.5cii : Extension beyond COMP: For Inside DNWELL: (ii) For Nplus >= 0.43um from LVPWELL edge for Nwell or DNWELL tap inside DNWELL. : 0.02µm')
np5cii_l1.forget
np_5cii_background.forget
np_5cii_foreground.forget
np_5di_background = nplus.not_outside(nwell).outside(dnwell).edges
np_5di_extend = nwell.outside(dnwell).not(nwell.outside(dnwell).sized(-0.429.um))
np_5di_foreground = ncomp.not_outside(nwell).outside(dnwell).edges.not(pplus.edges).and(np_5di_extend)
# Rule NP.5di: Extension beyond COMP: For Outside DNWELL, inside Nwell: (i) For Nwell overlap of Nplus < 0.43um. is 0.16µm
logger.info('Executing rule NP.5di')
np5di_l1 = np_5di_background.enclosing(np_5di_foreground, 0.16.um, projection).polygons(0.001)
np5di_l1.output('NP.5di', 'NP.5di : Extension beyond COMP: For Outside DNWELL, inside Nwell: (i) For Nwell overlap of Nplus < 0.43um. : 0.16µm')
np5di_l1.forget
np_5di_background.forget
np_5di_extend.forget
np_5di_foreground.forget
np_5dii_background = nplus.not_outside(nwell).outside(dnwell).edges.not(pplus.edges)
np_5dii_extend = nwell.outside(dnwell).sized(-0.429.um)
np_5dii_foreground = ncomp.not_outside(nwell).outside(dnwell).edges.not(pplus.edges).and(np_5dii_extend)
# Rule NP.5dii: Extension beyond COMP: For Outside DNWELL, inside Nwell: (ii) For Nwell overlap of Nplus >= 0.43um. is 0.02µm
logger.info('Executing rule NP.5dii')
np5dii_l1 = np_5dii_background.enclosing(np_5dii_foreground, 0.02.um, euclidian).polygons(0.001)
np5dii_l1.output('NP.5dii', 'NP.5dii : Extension beyond COMP: For Outside DNWELL, inside Nwell: (ii) For Nwell overlap of Nplus >= 0.43um. : 0.02µm')
np5dii_l1.forget
np_5dii_background.forget
np_5dii_extend.forget
np_5dii_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
np_11_in_dnwell = nplus.interacting(nplus.edges.and(pcomp.edges).and(lvpwell.inside(dnwell).not(lvpwell.inside(dnwell).sized(-0.429.um))))
np_11_out_dnwell = nplus.interacting(nplus.edges.and(pcomp.edges).and(nwell.outside(dnwell).sized(0.429.um)))
# Rule NP.11: Butting Nplus and PCOMP is forbidden within 0.43um of Nwell edge (for outside DNWELL) and of LVPWELL edge (for inside DNWELL case).
logger.info('Executing rule NP.11')
np11_l1 = np_11_in_dnwell.or(np_11_out_dnwell)
np11_l1.output('NP.11', 'NP.11 : Butting Nplus and PCOMP is forbidden within 0.43um of Nwell edge (for outside DNWELL) and of LVPWELL edge (for inside DNWELL case).')
np11_l1.forget
np_11_in_dnwell.forget
np_11_out_dnwell.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