blob: 8a2b7e60e7768b7e5bb78b8526969bb56decb076 [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
#================================================
#--------------------- SRAM----------------------
#================================================
# Rule S.DF.3: Space between COMP. is 0.26 um
logger.info('Executing rule S.DF.3')
s_df3a_l1 = comp.inside(sramcore).space(0.26.um, euclidian).polygons(0.001)
s_df3a_l1.output('S.DF.3', 'S.DF.3 : Space between COMP. : 0.26µm')
s_df3a_l1.forget
# Rule S.DF.7: Min. Nwell overlap of PCOMP inside NWELL. is 0.27µm
logger.info('Executing rule DF.7')
s_df4c_l1 = nwell.inside(sramcore).enclosing(pcomp.inside(nwell), 0.27.um, euclidian).polygons(0.001)
s_df4c_l2 = pcomp.inside(nwell).not_outside(nwell.inside(sramcore)).not(nwell.inside(sramcore))
s_df4c_l = s_df4c_l1.or(s_df4c_l2)
s_df4c_l.output('S.DF.7', 'S.DF.7 : Min. Nwell overlap of PCOMP inside NWELL. is 0.27µm')
s_df4c_l1.forget
s_df4c_l2.forget
s_df4c_l.forget
# Rule S.DF.8: Min. space from Nwell to NCOMP outside Nwell. is 0.38µm
logger.info('Executing rule S.DF.8')
s_df8_l1 = ncomp.outside(nwell).inside(sramcore).separation(nwell, 0.38.um, euclidian).polygons(0.001)
s_df8_l1.output('S.DF.8', 'S.DF.8 : Min. space from (Nwell outside DNWELL) to (NCOMP outside Nwell and DNWELL). : 0.38µm')
s_df8_l1.forget
# Rule S.PL.1: Interconnect Width . is 0.18µm
logger.info('Executing rule S.PL.1')
s_pl1_l1 = poly2.inside(sramcore).width(0.18.um, euclidian).polygons(0.001)
s_pl1_l1.output('S.PL.1', 'S.PL.1 : Interconnect Width. : 0.18µm')
s_pl1_l1.forget
# Rule S.PL.3aii:Poly2 to poly2 space on field (poly width < 0.5) is 0.2µm
s_pl_init = poly2.drc( width < 0.5.um).polygons
logger.info('Executing rule S.PL.3aii')
s_pl3aii_l1 = s_pl_init.inside(sramcore).space(0.2.um, euclidian).polygons(0.001)
s_pl3aii_l1.output('S.PL.3aii', 'S.PL.3aii :Poly2 to poly2 space on field (poly width < 0.5) : 0.2µm')
s_pl3aii_l1.forget
# Rule S.PL.4: Extension beyond COMP to form Poly2 end cap. is 0.22µm (parallel to channel length direction)
logger.info('Executing rule S.PL.4')
s_pl4_l1 = poly2.inside(sramcore).enclosing(comp, 0.22.um, euclidian).with_internal_angle(0).polygons(0.001)
s_pl4_l1.output('S.PL.4', 'S.PL.4 : Extension beyond COMP to form Poly2 end cap. : 0.22µm')
s_pl4_l1.forget
# Rule S.PL.4i: Min width of chopped end cap (parallel to channel length direction). is 0.1µm
logger.info('Executing rule S.PL.4i')
s_pl4i_l1 = poly2.inside(sramcore).interacting(comp).edges.not_interacting(comp).with_length(nil,0.1.um)
s_pl4i_l1.output('S.PL.4i', 'S.PL.4i : Min width of chopped end cap (parallel to channel length direction). : 0.1m')
s_pl4i_l1.forget
# Rule S.PL.5b: Space from field Poly2 to related COMP. is 0.04µm
logger.info('Executing rule S.PL.5b')
s_pl5b_l1 = poly2.inside(sramcore).separation(comp, 0.04.um, euclidian).polygons(0.001)
s_pl5b_l1.output('S.PL.5b', 'S.PL.5b : Space from field Poly2 to related COMP. : 0.04µm')
s_pl5b_l1.forget
# Rule S.CO.1: Min/max contact size. is 0.22µm
logger.info('Executing rule S.CO.1')
s_co1_l1 = contact.inside(sramcore).edges.without_length(0.22.um).extended(0, 0, 0.001, 0.001)
s_co1_l1.output('S.CO.1', 'S.CO.1 : Min/max contact size. : 0.22µm')
s_co1_l1.forget
# Rule S.CO.1i: Min. contact area (um2). is 0.0484µm²
logger.info('Executing rule S.CO.1i')
s_co_1i_l1 = contact.inside(sramcore).with_area(nil, 0.0484.um)
s_co_1i_l1.output('S.CO.1i', 'S.CO.1i : Min. contact area (um2). : 0.0484µm²')
s_co_1i_l1.forget
# Rule S.CO.1ii: Max. contact area (um2). is 0.0486µm²
logger.info('Executing rule S.CO.1ii')
s_co_1ii_l1 = contact.inside(sramcore).with_area(0.04861 .um, nil)
s_co_1ii_l1.output('S.CO.1ii', 'S.CO.1ii : Max. contact area (um2). : 0.04861µm²')
s_co_1ii_l1.forget
# Rule S.CO.3: Poly2 overlap of contact. is 0µm
logger.info('Executing rule S.CO.3')
s_co3_l = contact.inside(sramcore).interacting(poly2).not(poly2)
s_co3_l.output('S.CO.3', 'S.CO.3 : Poly2 overlap of contact. : 0µm')
s_co3_l.forget
s_co3i_1 = contact.inside(sramcore).edges.interacting(contact.drc(enclosed(poly2, projection) < 0.06.um).edges.centers(0, 0.5))
s_co3i_2 = contact.inside(sramcore).edges.interacting(contact.drc(0.04.um <= enclosed(poly2, projection) < 0.06.um).centers(0, 0.5))
s_co3i_3 = s_co3i_1.extended(0, 0, 0, 0.001, joined).corners(90)
# Rule S.CO.3i: If Poly2 overlap of contact by < 0.06um on one side, adjacent Poly2 edges’ overlap is 0.06µm
logger.info('Executing rule S.CO.3i')
s_co3i_l1 = s_co3i_2.not_in(s_co3i_1).interacting(s_co3i_1).or(s_co3i_1.interacting(s_co3i_3)).enclosed(poly2.inside(sramcore).edges, 0.06.um).polygons(0.001)
s_co3i_l1.output('S.CO.3i', 'S.CO.3i : If Poly2 overlap of contact by < 0.06um on one side, adjacent Poly2 edges’ overlap : 0.06µm')
s_co3i_l1.forget
s_co3i_1.forget
s_co3i_2.forget
s_co3i_3.forget
# Rule S.CO.4: COMP overlap of contact. is 0µm
logger.info('Executing rule S.CO.4')
s_co4_l = contact.inside(sramcore).interacting(comp).not(comp)
s_co4_l.output('S.CO.4', 'S.CO.4 : COMP overlap of contact. : 0µm')
s_co4_l.forget
s_co4i_1 = contact.inside(sramcore).edges.interacting(contact.drc(enclosed(comp, projection) < 0.06.um).edges.centers(0, 0.5))
s_co4i_2 = contact.inside(sramcore).edges.interacting(contact.drc(0.04.um <= enclosed(comp, projection) < 0.06.um).centers(0, 0.5))
s_co4i_3 = s_co4i_1.extended(0, 0, 0, 0.001, joined).corners(90)
# Rule S.CO.4i: If COMP overlap of contact by < 0.06um on one side, adjacent COMP edges’ overlap is 0.06µm
logger.info('Executing rule S.CO.4i')
s_co4i_l1 = s_co4i_2.not_in(s_co4i_1).interacting(s_co4i_1).or(s_co4i_1.interacting(s_co4i_3)).enclosed(comp.inside(sramcore).edges, 0.06.um).polygons(0.001)
s_co4i_l1.output('S.CO.4i', 'S.CO.4i : If COMP overlap of contact by < 0.06um on one side, adjacent COMP edges’ overlap : 0.06µm')
s_co4i_l1.forget
s_co4i_1.forget
s_co4i_2.forget
s_co4i_3.forget
# Rule S.CO.6: Metal1 overlap of contact. is 0µm
logger.info('Executing rule S.CO.6')
s_co6_l = contact.inside(sramcore).interacting(metal1).not(metal1)
s_co6_l.output('S.CO.6', 'S.CO.6 : Metal1 overlap of contact. : 0µm')
s_co6_l.forget
# Rule S.CO.7: Space from COMP contact to Poly2 on COMP. is 0.14µm
logger.info('Executing rule S.CO.7')
s_co7_l1 = contact.inside(sramcore).not_outside(comp).separation(tgate, 0.14.um, euclidian).polygons(0.001)
s_co7_l1.output('S.CO.7', 'S.CO.7 : Space from COMP contact to Poly2 on COMP. : 0.16µm')
s_co7_l1.forget
# Rule S.CO.8: Space from Poly2 contact to COMP. is 0.17µm
logger.info('Executing rule S.CO.8')
s_co8_l1 = contact.inside(sramcore).not_outside(poly2).separation(comp, 0.17.um, euclidian).polygons(0.001)
s_co8_l1.output('S.CO.8', 'S.CO.8 : Space from Poly2 contact to COMP. : 0.17µm')
s_co8_l1.forget
# Rule S.M1.1: Metal1 width in parallel direction is 0.23µm
logger.info('Executing rule S.M1.1')
s_m11_l1 = metal1.inside(sramcore).width(0.23.um, euclidian).polygons(0.001)
s_m11_l1.output('S.M1.1', 'S.M1.1 : Metal1 width in parallel direction : 0.23µm')
s_m11_l1.forget
end #FEOL