| ################################################################################################ |
| # 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 CORE CELLS---------------- |
| #================================================ |
| |
| # Rule S.DF.1a: Minimum COMP width inside SramCore AND OPC_drc marking layers is 0.02 µm |
| logger.info('Executing rule S.DF.1a') |
| s_df_1a = comp.and(sramcore).and(opc_drc).width(0.02.um, euclidian) |
| s_df_1a.output('S.DF.1a','S.DF.1a: Minimum COMP width inside SramCore AND OPC_drc marking layers is 0.02 µm') |
| |
| s_df_1a.forget |
| |
| # Rule S.DF.3a.i : Space between COMP inside SRAM is 0.26 µm |
| logger.info('Executing rule S.DF.3a.i') |
| s_df_3ai = comp.inside(sramcore).outside(opc_drc).space(0.26.um).polygons(0.001) |
| s_df_3ai.output('S.DF.3a.i','S.DF.3a.i : Space between COMP inside SRAM is 0.26 µm') |
| |
| s_df_3ai.forget |
| |
| # Rule S.DF.3a.ii : Space between COMP (inside SramCore making) to COMP (outside SramCore marking) is 0.28µm |
| logger.info('Executing rule S.DF.3a.ii') |
| s_df_3aii = comp.and(sramcore).separation(comp.not(sramcore),0.28.um).polygons(0.001) |
| s_df_3aii.output('S.DF.3a.ii', 'S.DF.3a.ii : Space between COMP (inside SramCore making) to COMP (outside SramCore marking) is 0.28µm') |
| |
| s_df_3aii.forget |
| |
| # Rule S.DF.3a.iii : Space between COMP inside SramCore AND OPC_drc marking layers is 0.02µm |
| logger.info('Executing rule S.DF.3a.iii') |
| s_df_3aiii = comp.inside(sramcore).inside(opc_drc).space(0.02.um).polygons(0.001) |
| s_df_3aiii.output('S.DF.3a.iii','S.DF.3a.iii : Space between COMP inside SramCore AND OPC_drc marking layers is 0.02µm') |
| |
| s_df_3aiii.forget |
| |
| # Rule S.DF.4c : Nwell enclose PCOMP inside Nwell is 0.25µm |
| logger.info('Executing rule S.DF.4c') |
| s_df_4a = nwell.inside(sramcore).enclosing(pcomp.inside(sramcore),0.25.um).polygons(0.001) |
| s_df_4a.output('S.DF.4c','S.DF.4c : Nwell enclose PCOMP inside Nwell is 0.25µm') |
| |
| s_df_4a.forget |
| |
| # Rule S.DF.6 : Extension beyond gate or source/drain overhang inside SramCore AND OPC_drc marking layers is 0.03µm |
| logger.info('Executing rule S.DF.6') |
| s_df_6 = comp.interacting(poly2).inside(sramcore).inside(opc_drc).enclosing(poly2.inside(sramcore).inside(opc_drc),0.03.um).polygons(0.001) |
| s_df_6.output('S.DF.6','S.DF.6 : Extension beyond gate or source/drain overhang inside SramCore AND OPC_drc marking layers is 0.03µm') |
| |
| s_df_6.forget |
| |
| # Rule S.DF.7 : Space from LVPWELL to PCOMP inside DNWELL is 0.25µm |
| logger.info('Executing rule S.DF.7') |
| s_df_7 = pcomp.inside(dnwell).inside(sramcore).separation(lvpwell.inside(dnwell).inside(sramcore),0.25.um).polygons(0.001) |
| s_df_7.output('S.DF.7','S.DF.7 : Space from LVPWELL to PCOMP inside DNWELL is 0.25µm') |
| |
| s_df_7.forget |
| |
| # Rule S.DF.8 : LVPWELL enclose NCOMP inside LVPWELL is 0.355 µm |
| logger.info('Executing rule S.DF.8') |
| s_df_8_l1 = lvpwell.inside(sramcore).enclosing(ncomp.inside(sramcore),0.355.um).polygons(0.001) |
| s_df_8_l2 = ncomp.inside(sramcore).interacting(lvpwell.inside(sramcore)).not_inside(lvpwell.inside(sramcore)) |
| s_df_8 = s_df_8_l1.or(s_df_8_l2) |
| s_df_8.output('S.DF.8','S.DF.8 : LVPWELL enclose NCOMP inside LVPWELL is 0.355 µm') |
| |
| s_df_8_l1.forget |
| s_df_8_l2.forget |
| s_df_8.forget |
| |
| # Rule S.PL.1i : Poly2 interconnect width in parallel direction is 0.18 µm |
| logger.info('Executing rule S.PL.1i') |
| s_pl_1i = poly2.inside(sramcore).outside(opc_drc).width(0.18.um, projection) |
| s_pl_1i.output('S.PL.1i','S.PL.1i : Poly2 interconnect width in parallel direction is 0.18 µm') |
| |
| s_pl_1i.forget |
| |
| # Rule S.PL.1ii : Inside SramCore AND OPC_drc marking layers, Poly2 interconnect width in parallel direction is 0.05µm |
| logger.info('Executing rule S.PL.1ii') |
| s_pl_1ii = poly2.and(sramcore).and(opc_drc).width(0.05.um, projection) |
| s_pl_1ii.output('S.PL.1ii','S.PL.1ii : Inside SramCore AND OPC_drc marking layers, Poly2 interconnect width in parallel direction is 0.05µm') |
| |
| s_pl_1ii.forget |
| |
| # Rule S.PL.3a.ii : Poly2 to Poly2 space on field (Poly2 width < 0.5) is 0.19µm |
| logger.info('Executing rule S.PL.3a.ii') |
| s_pl_3aii = poly2.not(comp).inside(sramcore).outside(opc_drc).width(0.5.um).polygons(0.0001).space(0.19.um).polygons(0.0001) |
| s_pl_3aii.output('S.PL.3a.ii','S.PL.3a.ii : Poly2 to Poly2 space on field (Poly2 width < 0.5) is 0.19µm') |
| |
| s_pl_3aii.forget |
| |
| # Rule S.PL.3a.iii : Poly2 (inside SramCore making) to Poly2 (outside SramCore making) space on field is 0.25µm |
| logger.info('Executing rule S.PL.3a.iii') |
| s_pl_3aiii = poly2.not(comp).inside(sramcore).separation(poly2.not(comp).outside(sramcore),0.25.um).polygons(0.001) |
| s_pl_3aiii.output('S.PL.3a.iii','S.PL.3a.iii : Poly2 (inside SramCore making) to Poly2 (outside SramCore making) space on field is 0.25µm') |
| |
| s_df_3aiii.forget |
| |
| # Rule S.PL.3a.iv : Inside SramCore AND OPC_drc marking layers, Poly2 to Poly2 space on field (Poly2 width < 0.5) is 0.03µm |
| logger.info('Executing rule S.PL.3a.iv') |
| s_pl_3aiv = poly2.not(comp).inside(sramcore).inside(opc_drc).width(0.5.um).polygons(0.0001).space(0.03.um).polygons(0.0001) |
| s_pl_3aiv.output('S.PL.3a.iv','S.PL.3a.iv : Inside SramCore AND OPC_drc marking layers, Poly2 to Poly2 space on field (Poly2 width < 0.5) is 0.03µm') |
| |
| s_pl_3aiv.forget |
| |
| # Rule S.PL.4 : Poly2 end cap (width parallel to COMP) is 0.22µm |
| logger.info('Executing rule S.PL.4') |
| s_pl_4 = poly2.inside(sramcore).outside(opc_drc).enclosing(comp.interacting(poly2).inside(sramcore).outside(opc_drc),0.22.um, projection) |
| s_pl_4.output('S.PL.4','S.PL.4 : Poly2 end cap (width parallel to COMP) is 0.22µm') |
| |
| s_pl_4.forget |
| |
| # Rule S.PL.4i : Min width of chopped end cap (parallel to channel length direction) is 0.10µm |
| logger.info('Executing rule S.PL.4i') |
| s_pl_4i = poly2.inside(sramcore).interacting(comp).edges.not_interacting(comp).interacting(poly2.edges.interacting(comp)).with_length(nil,0.1) |
| s_pl_4i.output('S.PL.4i','S.PL.4i : Min width of chopped end cap (parallel to channel length direction) is 0.10µm') |
| |
| s_pl_4i.forget |
| |
| # Rule S.PL.4ii : Inside SramCore AND OPC_drc marking layers, Poly2 end cap (width parallel to COMP) is 0.03µm |
| logger.info('Executing rule S.PL.4ii') |
| s_pl_4ii = poly2.inside(sramcore).inside(opc_drc).enclosing(comp.interacting(poly2).inside(sramcore).inside(opc_drc),0.03.um, projection) |
| s_pl_4ii.output('S.PL.4ii','S.PL.4ii : Inside SramCore AND OPC_drc marking layers, Poly2 end cap (width parallel to COMP) is 0.03µm') |
| |
| s_pl_4ii.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.NP.12: Overlap with P-channel poly2 gate extension is forbidden within 0.25um of P-channel gate. |
| logger.info('Executing rule S.NP.12') |
| s_np12_l1 = nplus.and(sramcore).and(pgate.and(sramcore).sized(0.25.um)) |
| s_np12_l1.output('S.NP.12', 'S.NP.12 : Overlap with P-channel poly2 gate extension is forbidden within 0.25um of P-channel gate.') |
| s_np12_l1.forget |
| |
| # Rule S.CO.1: Min/max contact size. is 0.21µm |
| logger.info('Executing rule S.CO.1') |
| s_co1_l1 = contact.inside(sramcore).edges.without_length(0.21.um).extended(0, 0, 0.001, 0.001) |
| s_co1_l1.output('S.CO.1', 'S.CO.1 : Min/max contact size. : 0.21µm') |
| s_co1_l1.forget |
| |
| # Rule S.CO.1i: Min. contact area (um2). is 0.0483µm² |
| logger.info('Executing rule S.CO.1i') |
| s_co_1i_l1 = contact.inside(sramcore).with_area(nil, 0.0483.um) |
| s_co_1i_l1.output('S.CO.1i', 'S.CO.1i : Min. contact area (um2). : 0.0483µm²') |
| s_co_1i_l1.forget |
| |
| # Rule S.CO.1ii: Max. contact area (um2). is 0.0638µm² |
| logger.info('Executing rule S.CO.1ii') |
| s_co_1ii_l1 = contact.inside(sramcore).with_area(0.0638 .um, nil) |
| s_co_1ii_l1.output('S.CO.1ii', 'S.CO.1ii : Max. contact area (um2). : 0.0638µm²') |
| s_co_1ii_l1.forget |
| |
| # Rule S.CO.2a : Contact to Contact space inside SramCore marking is 0.21µm |
| logger.info('Executing rule S.CO.2a') |
| s_co_2a = contact.inside(sramcore).space(0.21.um).polygons(0.001) |
| s_co_2a.output('S.CO.2a','S.CO.2a : Contact to Contact space inside SramCore marking is 0.21µm') |
| |
| s_co_2a.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 |
| |
| # Rule S.CO.3i: If Poly2 enclose 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_cont = contact.and(sramcore).not(opc_drc) |
| s_co3i_cond_edges = s_co3i_cont.edges.not_outside(s_co3i_cont.enclosed(poly2.and(sramcore), 0.06.um, projection).edges) |
| s_co3i_check_corner = s_co3i_cond_edges.extended_in(0.002.um) |
| s_co3i_check = s_co3i_cont.edges.interacting(s_co3i_check_corner).not(s_co3i_cond_edges) |
| s_co3i_cond_corner = s_co3i_cond_edges.width(0.002.um, angle_limit(135)).polygons |
| s_co3i_l1 = s_co3i_check.enclosed(poly2.and(sramcore).edges, 0.06.um, projection).polygons |
| s_co3i_l2 = s_co3i_cont.interacting(s_co3i_cond_corner) |
| s_co3i_l = s_co3i_l1.or(s_co3i_l2) |
| s_co3i_l.output('S.CO.3i', 'S.CO.3i : If Poly2 enclose of contact by < 0.06um on one side, adjacent Poly2 edges’ overlap is 0.06µm') |
| s_co3i_l.forget |
| s_co3i_l2.forget |
| s_co3i_l1.forget |
| s_co3i_cond_edges.forget |
| s_co3i_check_corner.forget |
| s_co3i_cond_corner.forget |
| s_co3i_check.forget |
| s_co3i_cont.forget |
| |
| # Rule S.CO.3ii: Inside SramCore AND OPC_drc If Poly2 enclose of contact by < 0.06um on one side, adjacent Poly2 edges’ overlap is 0.01µm |
| logger.info('Executing rule S.CO.3ii') |
| s_co3ii_cont = contact.and(sramcore).and(opc_drc) |
| s_co3ii_cond_edges = s_co3ii_cont.edges.not_outside(s_co3ii_cont.enclosed(poly2.and(sramcore), 0.01.um, projection).edges) |
| s_co3ii_check_corner = s_co3ii_cond_edges.extended_in(0.002.um) |
| s_co3ii_check = s_co3ii_cont.edges.interacting(s_co3ii_check_corner).not(s_co3ii_cond_edges) |
| s_co3ii_cond_corner = s_co3ii_cond_edges.width(0.002.um, angle_limit(135)).polygons |
| s_co3ii_l1 = s_co3ii_check.enclosed(poly2.and(sramcore).edges, 0.06.um, projection).polygons |
| s_co3ii_l2 = s_co3ii_cont.interacting(s_co3ii_cond_corner) |
| s_co3ii_l = s_co3ii_l1.or(s_co3ii_l2) |
| s_co3ii_l.output('S.CO.3ii', 'S.CO.3ii : Inside SramCore AND OPC_drc If Poly2 enclose of contact by < 0.06um on one side, adjacent Poly2 edges’ overlap is 0.01µm') |
| s_co3ii_l.forget |
| s_co3ii_l2.forget |
| s_co3ii_l1.forget |
| s_co3ii_cond_edges.forget |
| s_co3ii_check_corner.forget |
| s_co3ii_cond_corner.forget |
| s_co3ii_check.forget |
| s_co3ii_cont.forget |
| |
| # Rule S.CO.4: COMP enclose contact. is 0µm |
| logger.info('Executing rule S.CO.4') |
| s_co4_l = contact.and(sramcore).interacting(comp).not(comp) |
| s_co4_l.output('S.CO.4', 'S.CO.4 : COMP enclose contact. : 0µm') |
| s_co4_l.forget |
| |
| s_co4i_1 = contact.inside(sramcore).outside(opc_drc).edges.interacting(contact.drc(enclosed(comp, projection) < 0.06.um).edges.centers(0, 0.5)) |
| s_co4i_2 = contact.inside(sramcore).outside(opc_drc).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 enclose 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).outside(opc_drc).edges, 0.06.um).polygons(0.001) |
| s_co4i_l1.output('S.CO.4i', 'S.CO.4i : If COMP enclose 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.4ii: Inside SramCore AND OPC_drc If Poly2 enclose of contact by < 0.06um on one side, adjacent COMP edges’ overlap is 0.01µm |
| logger.info('Executing rule S.CO.4ii') |
| s_co4ii_cont = contact.and(sramcore).and(opc_drc) |
| s_co4ii_cond_edges = s_co4ii_cont.edges.not_outside(s_co4ii_cont.enclosed(comp.and(sramcore), 0.01.um, projection).edges) |
| s_co4ii_check_corner = s_co4ii_cond_edges.extended_in(0.002.um) |
| s_co4ii_check = s_co4ii_cont.edges.interacting(s_co4ii_check_corner).not(s_co4ii_cond_edges) |
| s_co4ii_cond_corner = s_co4ii_cond_edges.width(0.002.um, angle_limit(135)).polygons |
| s_co4ii_l1 = s_co4ii_check.enclosed(comp.and(sramcore).edges, 0.06.um, projection).polygons |
| s_co4ii_l2 = s_co4ii_cont.interacting(s_co4ii_cond_corner) |
| s_co4ii_l = s_co4ii_l1.or(s_co4ii_l2) |
| s_co4ii_l.output('S.CO.4ii', 'S.CO.4ii : If COMP enclose contact by < 0.06um on one side, adjacent COMP edges’ overlap : 0.01µm') |
| s_co4ii_l.forget |
| s_co4ii_l2.forget |
| s_co4ii_l1.forget |
| s_co4ii_cond_edges.forget |
| s_co4ii_check_corner.forget |
| s_co4ii_cond_corner.forget |
| s_co4ii_check.forget |
| s_co4ii_cont.forget |
| |
| # Rule S.CO.6: Metal1 enclose 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 |
| |
| s_co6i_m1_ = metal1.inside(sramcore).drc( width <= 0.34.um).edges.interacting(metal1.corners(90)) |
| s_co6i_m1 = metal1.inside(sramcore).edges.interacting(s_co6i_m1_) |
| # Rule S.CO.6i : Metal 1 (< 0.34µm) enclose contact at end-of-line side is 0µm |
| logger.info('Executing rule S.CO.6i') |
| s_co6i_l1 = (contact.inside(sramcore).not_outside(metal1).not(metal1)) |
| s_co6i_l1.output('S.CO.6i','S.CO.6i: Metal 1 (< 0.34µm) enclose contact at end-of-line side is 0µm') |
| |
| s_co6i_m1.forget |
| s_co6i_l1.forget |
| |
| # Rule S.CO.6ii : If metal 1 enclose contact by < 0.04µm on one side, adjacent metal1 edges enclosure is 0µm |
| logger.info('Executing rule S.CO.6ii') |
| s_co6ii_l1 = contact.and(sramcore).enclosed(metal1.and(sramcore), 0.04.um).polygons |
| s_co6ii_l = s_co6ii_l1.interacting(s_co6ii_l1.not_inside(metal1.and(sramcore))) |
| s_co6ii_l.output('S.CO.6ii', 'S.CO.6ii : If metal 1 enclose contact by < 0.04µm on one side, adjacent metal1 edges enclosure is 0µm') |
| s_co6ii_l.forget |
| |
| # Rule S.CO.7: Space from COMP contact to Poly2 . is 0.12µm |
| logger.info('Executing rule S.CO.7') |
| s_co7_l1 = contact.inside(sramcore).outside(opc_drc).not_outside(comp).separation(poly2, 0.12.um, euclidian).polygons(0.001) |
| s_co7_l1.output('S.CO.7', 'S.CO.7 : Space from COMP contact to Poly2 . : 0.12µm') |
| s_co7_l1.forget |
| |
| # Rule S.CO.7i: Inside SramCore AND OPC_drc marking layers, Space from COMP contact to Poly2 . is 0.07µm |
| logger.info('Executing rule S.CO.7i') |
| s_co7i_l1 = contact.inside(sramcore).inside(opc_drc).not_outside(comp).separation(poly2, 0.07.um, euclidian).polygons(0.001) |
| s_co7i_l1.output('S.CO.7i', 'S.CO.7i :Inside SramCore AND OPC_drc marking layers, Space from COMP contact to Poly2 . : 0.07µm') |
| s_co7i_l1.forget |
| |
| # Rule S.CO.8: Space from Poly2 contact to COMP. is 0.13µm |
| logger.info('Executing rule S.CO.8') |
| s_co8_l1 = contact.inside(sramcore).outside(opc_drc).not_outside(poly2).separation(comp, 0.13.um, euclidian).polygons(0.001) |
| s_co8_l1.output('S.CO.8', 'S.CO.8 : Space from Poly2 contact to COMP. : 0.13µm') |
| s_co8_l1.forget |
| |
| # Rule S.CO.8i: Inside SramCore AND OPC_drc marking layers, Space from Poly2 contact to COMP. is 0.07µm |
| logger.info('Executing rule S.CO.8i') |
| s_co8i_l1 = contact.inside(sramcore).inside(opc_drc).not_outside(poly2).separation(comp, 0.07.um, euclidian).polygons(0.001) |
| s_co8i_l1.output('S.CO.8i', 'S.CO.8i: Inside SramCore AND OPC_drc marking layers, Space from Poly2 contact to COMP. is 0.07µm') |
| s_co8i_l1.forget |
| |
| # Rule S.M1.1: Metal1 width in parallel direction is 0.21µm |
| logger.info('Executing rule S.M1.1') |
| s_m11_l1 = metal1.inside(sramcore).outside(opc_drc).width(0.21.um, projection) |
| s_m11_l1.output('S.M1.1', 'S.M1.1 : Metal1 width in parallel direction : 0.21µm') |
| s_m11_l1.forget |
| |
| # Rule S.M1.1i: Inside SramCore AND OPC_drc marking layers, Metal1 width in parallel direction is 0.035µm |
| logger.info('Executing rule S.M1.1i') |
| s_m11i_l1 = metal1.inside(sramcore).inside(opc_drc).width(0.035.um, projection) |
| s_m11i_l1.output('S.M1.1i', 'S.M1.1i : Metal1 width in parallel direction : 0.035µm') |
| s_m11i_l1.forget |
| |
| # Rule S.M1.2a.i : Metal1 space in parallel direction is 0.20µm |
| logger.info('Executing rule S.M1.2a.i') |
| s_m1_2ai = metal1.and(sramcore).space(0.20.um, projection) |
| s_m1_2ai.output('S.M1.2a.i','S.M1.2a.i : Metal1 space in parallel direction is 0.20µm') |
| s_m1_2ai.forget |
| |
| # Rule S.M1.2a.ii : Metal1 (inside SramCore marking) to Metal1 (outside SramCore marking) space in parallel direction is 0.23µm |
| logger.info('Executing rule S.M1.2a.ii') |
| s_m1_2aii = metal1.and(sramcore).separation(metal1.not(sramcore),0.23.um, projection) |
| s_m1_2aii.output('S.M1.2a.ii','S.M1.2a.ii : Metal1 (inside SramCore marking) to Metal1 (outside SramCore marking) space in parallel direction is 0.23µm') |
| s_m1_2aii.forget |
| |
| # Rule S.M1.2a.iii : Metal1 (inside SramCore marking) to wide Metal1 (outside SramCore marking, length & width >10um) space in parallel direction is 0.30µm |
| logger.info('Executing rule S.M1.2a.iii') |
| wide_metal1 = metal1.not(sramcore).interacting(metal1.not(sramcore).edges.with_length(10.um,nil)) |
| s_m1_2aiii = metal1.and(sramcore).separation(wide_metal1,0.3.um, projection) |
| s_m1_2aiii.output('S.M1.2a.iii','S.M1.2a.iii : Metal1 (inside SramCore marking) to wide Metal1 (outside SramCore marking, length & width >10um) space in parallel direction is 0.30µm') |
| s_m1_2aiii.forget |
| wide_metal1.forget |
| |
| # Rule S.M1.2a.iv : Inside SramCore AND OPC_drc marking layers, Metal1 space in parallel direction is 0.13µm |
| logger.info('Executing rule S.M1.2a.iv') |
| s_m1_2aiv = metal1.inside(sramcore).inside(opc_drc).space(0.13.um, projection) |
| s_m1_2aiv.output('S.M1.2a.iv','S.M1.2a.iv : Inside SramCore AND OPC_drc marking layers,Metal1 space in parallel direction is 0.13µm') |
| s_m1_2aiv.forget |
| |
| # Rule S.M2.2a.i : Metal2 (inside SramCore marking) to Metal2 (outside SramCore marking) space in parallel direction is 0.28µm |
| logger.info('Executing rule S.M2.2a.i') |
| s_m2_2ai = metal2.inside(sramcore).separation(metal2.outside(sramcore),0.28.um, projection) |
| s_m2_2ai.output('S.M2.2a.i','S.M2.2a.i : Metal2 (inside SramCore marking) to Metal2 (outside SramCore marking) space in parallel direction is 0.28µm') |
| s_m2_2ai.forget |
| |
| # Rule S.M2.3 : Minimum Metal2 Area is 0.12µm² |
| logger.info('Executing rule S.M2.3') |
| s_m2_3 = metal2.inside(sramcore).with_area(nil,0.12.um) |
| s_m2_3.output('S.M2.3','S.M2.3 : Minimum Metal2 Area is 0.12µm²') |
| s_m2_3.forget |
| |
| # Rule S.V1.3 : Metal1 enclose VIA1 is 0µm |
| logger.info('Executing rule S.V1.3') |
| s_v1_3 = via1.inside(sramcore).interacting(metal1.inside(sramcore)).not(metal1.inside(sramcore)) |
| s_v1_3.output('S.V1.3','S.V1.3 : Metal1 enclose VIA1 is 0µm') |
| s_v1_3.forget |
| |
| s_v13i_m1_ = metal1.inside(sramcore).drc( width <= 0.34.um).edges.interacting(metal1.corners(90)) |
| s_v13i_m1 = metal1.inside(sramcore).edges.interacting(s_v13i_m1_) |
| # Rule S.V1.3i : Metal 1 (< 0.34µm) enclose via1 at end-of-line side is 0µm |
| logger.info('Executing rule S.V1.3i') |
| s_v13i_l1 = (via1.inside(sramcore).not_outside(metal1).not(metal1)) |
| s_v13i_l1.output('S.V1.3i','S.V1.3i: Metal 1 (< 0.34µm) enclose Via1 at end-of-line side is 0µm') |
| |
| s_v13i_m1.forget |
| s_v13i_l1.forget |
| |
| s_v1_3ii_ed = via1.inside(sramcore).edges.not(metal1.inside(sramcore).edges).interacting(contact.inside(sramcore).edges.and(metal1.inside(sramcore).edges)) |
| # Rule S.V1.3ii : If metal1 enclose via1 by < 0.04µm on one side, adjacent metal1 edges enclosure is 0µm |
| logger.info('Executing rule S.V1.3ii') |
| s_v1_3ii_l1 = metal1.inside(sramcore).edges.enclosing(s_v1_3ii_ed,0.04.um,projection).polygons(0.001) |
| s_v1_3ii = s_v1_3ii_l1.or(via1.inside(sramcore).not_outside(metal1.inside(sramcore)).not(metal1)) |
| s_v1_3ii.output('S.V1.3ii','S.V1.3ii : If metal1 enclose via1 by < 0.04µm on one side, adjacent metal1 edges enclosure is 0µm') |
| |
| s_v1_3ii_ed.forget |
| s_v1_3ii_l1.forget |
| s_v1_3ii.forget |
| |
| end #FEOL |