From ed6e97a419c2dd325b96ff5513eac9dce6e7d933 Mon Sep 17 00:00:00 2001 From: FaragElsayed2 Date: Sun, 5 Feb 2023 10:05:34 +0200 Subject: [PATCH] Adding linting checks for ruby/drc files Fixing some linting issues Updating linting check for ruby Removing bundle installation Removing unused Gemfile Fixing some ruby linting issues --- .github/workflows/linting.yml | 14 +- .github/workflows/regression.yml | 3 - .rubocop.yml | 45 + Makefile | 9 +- klayout/drc/rule_decks/drc_bjt.drc | 41 - klayout/drc/rule_decks/dualgate.drc | 121 +- klayout/drc/rule_decks/dummy_exclude.drc | 43 - klayout/drc/rule_decks/efuse.drc | 201 - klayout/drc/rule_decks/hres.drc | 137 - klayout/drc/rule_decks/lres.drc | 100 - klayout/drc/rule_decks/lvs_bjt.drc | 34 - klayout/drc/rule_decks/main.drc | 1450 +++---- klayout/drc/rule_decks/mcell.drc | 47 - klayout/drc/rule_decks/otp_mk.drc | 143 - klayout/drc/rule_decks/pres.drc | 99 - klayout/drc/rule_decks/tail.drc | 6 +- klayout/drc/testing/run_regression.py | 2 +- .../drc/testing/testcases/unit/drc_bjt.gds | Bin 5114 -> 0 bytes .../drc/testing/testcases/unit/drc_bjt.svg | 90 - .../testing/testcases/unit/dummy_exclude.gds | Bin 3448 -> 0 bytes .../testing/testcases/unit/dummy_exclude.svg | 46 - klayout/drc/testing/testcases/unit/efuse.gds | Bin 256920 -> 0 bytes klayout/drc/testing/testcases/unit/efuse.svg | 3817 ----------------- klayout/drc/testing/testcases/unit/hres.gds | Bin 78832 -> 0 bytes klayout/drc/testing/testcases/unit/hres.svg | 935 ---- klayout/drc/testing/testcases/unit/lres.gds | Bin 73290 -> 0 bytes klayout/drc/testing/testcases/unit/lres.svg | 690 --- .../drc/testing/testcases/unit/lvs_bjt.gds | Bin 1950 -> 0 bytes .../drc/testing/testcases/unit/lvs_bjt.svg | 42 - klayout/drc/testing/testcases/unit/mcell.gds | Bin 17168 -> 0 bytes klayout/drc/testing/testcases/unit/mcell.svg | 184 - klayout/drc/testing/testcases/unit/otp_mk.gds | Bin 121226 -> 0 bytes klayout/drc/testing/testcases/unit/otp_mk.svg | 1540 ------- klayout/drc/testing/testcases/unit/pres.gds | Bin 70460 -> 0 bytes klayout/drc/testing/testcases/unit/pres.svg | 658 --- pdk_regression.yml | 1 + 36 files changed, 802 insertions(+), 9696 deletions(-) create mode 100644 .rubocop.yml delete mode 100644 klayout/drc/rule_decks/drc_bjt.drc delete mode 100644 klayout/drc/rule_decks/dummy_exclude.drc delete mode 100644 klayout/drc/rule_decks/efuse.drc delete mode 100644 klayout/drc/rule_decks/hres.drc delete mode 100644 klayout/drc/rule_decks/lres.drc delete mode 100644 klayout/drc/rule_decks/lvs_bjt.drc delete mode 100644 klayout/drc/rule_decks/mcell.drc delete mode 100644 klayout/drc/rule_decks/otp_mk.drc delete mode 100644 klayout/drc/rule_decks/pres.drc delete mode 100644 klayout/drc/testing/testcases/unit/drc_bjt.gds delete mode 100644 klayout/drc/testing/testcases/unit/drc_bjt.svg delete mode 100644 klayout/drc/testing/testcases/unit/dummy_exclude.gds delete mode 100644 klayout/drc/testing/testcases/unit/dummy_exclude.svg delete mode 100644 klayout/drc/testing/testcases/unit/efuse.gds delete mode 100644 klayout/drc/testing/testcases/unit/efuse.svg delete mode 100644 klayout/drc/testing/testcases/unit/hres.gds delete mode 100644 klayout/drc/testing/testcases/unit/hres.svg delete mode 100644 klayout/drc/testing/testcases/unit/lres.gds delete mode 100644 klayout/drc/testing/testcases/unit/lres.svg delete mode 100644 klayout/drc/testing/testcases/unit/lvs_bjt.gds delete mode 100644 klayout/drc/testing/testcases/unit/lvs_bjt.svg delete mode 100644 klayout/drc/testing/testcases/unit/mcell.gds delete mode 100644 klayout/drc/testing/testcases/unit/mcell.svg delete mode 100644 klayout/drc/testing/testcases/unit/otp_mk.gds delete mode 100644 klayout/drc/testing/testcases/unit/otp_mk.svg delete mode 100644 klayout/drc/testing/testcases/unit/pres.gds delete mode 100644 klayout/drc/testing/testcases/unit/pres.svg diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 275c512b..f5578329 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -21,12 +21,20 @@ on: jobs: lint_python: runs-on: ubuntu-latest - strategy: - max-parallel: 12 steps: - uses: actions/checkout@v3 with: submodules: 'recursive' - name: Lint with flake8 run: | - make lint + make lint_python + + lint_ruby: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: 'recursive' + - name: Lint with rubocop + run: | + make lint_ruby diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index 6b7678f0..e222aae4 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -45,7 +45,6 @@ jobs: needs: build_drc-matrix runs-on: ubuntu-latest strategy: - max-parallel: 4 fail-fast: false matrix: part: [drc] @@ -64,7 +63,6 @@ jobs: drc_switch: runs-on: ubuntu-latest strategy: - max-parallel: 4 fail-fast: false matrix: include: @@ -83,7 +81,6 @@ jobs: lvs_regression: runs-on: ubuntu-latest strategy: - max-parallel: 4 fail-fast: false matrix: include: diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000..ca447691 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,45 @@ +# The behavior of RuboCop can be controlled via the .rubocop.yml +# configuration file. It makes it possible to enable/disable +# certain cops (checks) and to alter their behavior if they accept +# any parameters. The file can be placed either in your home +# directory or in some project directory. +# +# RuboCop will start looking for the configuration file in the directory +# where the inspected file is and continue its way up to the root directory. +# +# See https://docs.rubocop.org/rubocop/configuration + +Style/FrozenStringLiteralComment: + Enabled: false + +GlobalVars: + Description: Do not introduce global variables. + Enabled: false + +UselessAssignment: + Description: Useless assignment to variable. + Enabled: false + +Metrics/AbcSize: + Description: Assignment Branch Condition size for conn_space is too high. + Enabled: false + +Metrics/MethodLength: + Description: Method has too many lines. + Enabled: false + +RSpec/VariableName: + Description: Use snake_case for variable names. + EnforcedStyle: "snake_case" + Enabled: false + +Metrics/BlockNesting: + Description: Avoid more than 3 levels of block nesting. + Enabled: false + +AllCops: + Exclude: + - 'env/**/*' + Include: + - '**/*.rb' + - '**/*.drc' diff --git a/Makefile b/Makefile index 21f134b2..87c50bbd 100644 --- a/Makefile +++ b/Makefile @@ -25,12 +25,19 @@ ENVIRONMENT_FILE := pdk_regression.yml # Path to regression KLAYOUT_TESTS := klayout/drc/testing/ + include third_party/make-env/conda.mk # Lint python code -lint: | $(CONDA_ENV_PYTHON) +lint_python: | $(CONDA_ENV_PYTHON) @$(IN_CONDA_ENV) flake8 . +# Lint ruby code +lint_ruby:| $(CONDA_ENV_PYTHON) + @$(IN_CONDA_ENV) gem install rubocop + @ln -s $$CONDA_PREFIX/bin/ruby $$CONDA_PREFIX/share/rubygems/bin/ruby + @$(IN_CONDA_ENV) rubocop . + ################################################################################ ## DRC Regression section ################################################################################ diff --git a/klayout/drc/rule_decks/drc_bjt.drc b/klayout/drc/rule_decks/drc_bjt.drc deleted file mode 100644 index e6db3a5e..00000000 --- a/klayout/drc/rule_decks/drc_bjt.drc +++ /dev/null @@ -1,41 +0,0 @@ -################################################################################################ -# 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 - #================================================ - #--------------------DRC_BJT--------------------- - #================================================ - - # Rule BJT.1: Min. DRC_BJT overlap of DNWELL for NPN BJT. - logger.info("Executing rule BJT.1") - bjt1_l1 = dnwell.interacting(drc_bjt).not(dnwell.inside(drc_bjt)) - bjt1_l1.output("BJT.1", "BJT.1 : Min. DRC_BJT overlap of DNWELL for NPN BJT.") - bjt1_l1.forget - - # Rule BJT.2: Min. DRC_BJT overlap of PCOM in Psub. - logger.info("Executing rule BJT.2") - bjt2_l1 = pcomp.outside(nwell).outside(dnwell).interacting(drc_bjt).not(pcomp.outside(nwell).outside(dnwell).inside(drc_bjt)) - bjt2_l1.output("BJT.2", "BJT.2 : Min. DRC_BJT overlap of PCOM in Psub.") - bjt2_l1.forget - - # Rule BJT.3: Minimum space of DRC_BJT layer to unrelated COMP. is 0.1µm - logger.info("Executing rule BJT.3") - bjt3_l1 = comp.outside(drc_bjt).separation(drc_bjt, 0.1.um, euclidian).polygons(0.001) - bjt3_l1.output("BJT.3", "BJT.3 : Minimum space of DRC_BJT layer to unrelated COMP. : 0.1µm") - bjt3_l1.forget -end #FEOL - diff --git a/klayout/drc/rule_decks/dualgate.drc b/klayout/drc/rule_decks/dualgate.drc index 871a7a6e..0490b8b9 100644 --- a/klayout/drc/rule_decks/dualgate.drc +++ b/klayout/drc/rule_decks/dualgate.drc @@ -15,74 +15,73 @@ ################################################################################################ if FEOL - #================================================ - #--------------------DUALGATE-------------------- - #================================================ + #================================================ + #--------------------DUALGATE-------------------- + #================================================ - # Rule DV.1: Min. Dualgate enclose DNWELL. is 0.5µm - logger.info("Executing rule DV.1") - dv1_l1 = dualgate.enclosing(dnwell, 0.5.um, euclidian).polygons(0.001) - dv1_l2 = dnwell.not_outside(dualgate).not(dualgate) - dv1_l = dv1_l1.or(dv1_l2) - dv1_l.output("DV.1", "DV.1 : Min. Dualgate enclose DNWELL. : 0.5µm") - dv1_l1.forget - dv1_l2.forget - dv1_l.forget + # Rule DV.1: Min. Dualgate enclose DNWELL. is 0.5µm + logger.info('Executing rule DV.1') + dv1_l1 = dualgate.enclosing(dnwell, 0.5.um, euclidian).polygons(0.001) + dv1_l2 = dnwell.not_outside(dualgate).not(dualgate) + dv1_l = dv1_l1.or(dv1_l2) + dv1_l.output('DV.1', 'DV.1 : Min. Dualgate enclose DNWELL. : 0.5µm') + dv1_l1.forget + dv1_l2.forget + dv1_l.forget - # Rule DV.2: Min. Dualgate Space. Merge if Space is less than this design rule. is 0.44µm - logger.info("Executing rule DV.2") - dv2_l1 = dualgate.space(0.44.um, euclidian).polygons(0.001) - dv2_l1.output("DV.2", "DV.2 : Min. Dualgate Space. Merge if Space is less than this design rule. : 0.44µm") - dv2_l1.forget + # Rule DV.2: Min. Dualgate Space. Merge if Space is less than this design rule. is 0.44µm + logger.info('Executing rule DV.2') + dv2_l1 = dualgate.space(0.44.um, euclidian).polygons(0.001) + dv2_l1.output('DV.2', 'DV.2 : Min. Dualgate Space. Merge if Space is less than this design rule. : 0.44µm') + dv2_l1.forget - # Rule DV.3: Min. Dualgate to COMP space [unrelated]. is 0.24µm - logger.info("Executing rule DV.3") - dv3_l1 = dualgate.separation(comp.outside(dualgate), 0.24.um, euclidian).polygons(0.001) - dv3_l1.output("DV.3", "DV.3 : Min. Dualgate to COMP space [unrelated]. : 0.24µm") - dv3_l1.forget + # Rule DV.3: Min. Dualgate to COMP space [unrelated]. is 0.24µm + logger.info('Executing rule DV.3') + dv3_l1 = dualgate.separation(comp.outside(dualgate), 0.24.um, euclidian).polygons(0.001) + dv3_l1.output('DV.3', 'DV.3 : Min. Dualgate to COMP space [unrelated]. : 0.24µm') + dv3_l1.forget - # rule DV.4 is not a DRC check - # Refer to: https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_07_07.html + # rule DV.4 is not a DRC check + # Refer to: https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_07_07.html - # Rule DV.5: Min. Dualgate width. is 0.7µm - logger.info("Executing rule DV.5") - dv5_l1 = dualgate.width(0.7.um, euclidian).polygons(0.001) - dv5_l1.output("DV.5", "DV.5 : Min. Dualgate width. : 0.7µm") - dv5_l1.forget + # Rule DV.5: Min. Dualgate width. is 0.7µm + logger.info('Executing rule DV.5') + dv5_l1 = dualgate.width(0.7.um, euclidian).polygons(0.001) + dv5_l1.output('DV.5', 'DV.5 : Min. Dualgate width. : 0.7µm') + dv5_l1.forget - comp_dv = comp.not(pcomp.outside(nwell)) - # Rule DV.6: Min. Dualgate enclose COMP (except substrate tap). is 0.24µm - logger.info("Executing rule DV.6") - dv6_l1 = dualgate.enclosing(comp_dv, 0.24.um, euclidian).polygons(0.001) - dv6_l2 = comp_dv.not_outside(dualgate).not(dualgate) - dv6_l = dv6_l1.or(dv6_l2) - dv6_l.output("DV.6", "DV.6 : Min. Dualgate enclose COMP (except substrate tap). : 0.24µm") - dv6_l1.forget - dv6_l2.forget - dv6_l.forget + comp_dv = comp.not(pcomp.outside(nwell)) + # Rule DV.6: Min. Dualgate enclose COMP (except substrate tap). is 0.24µm + logger.info('Executing rule DV.6') + dv6_l1 = dualgate.enclosing(comp_dv, 0.24.um, euclidian).polygons(0.001) + dv6_l2 = comp_dv.not_outside(dualgate).not(dualgate) + dv6_l = dv6_l1.or(dv6_l2) + dv6_l.output('DV.6', 'DV.6 : Min. Dualgate enclose COMP (except substrate tap). : 0.24µm') + dv6_l1.forget + dv6_l2.forget + dv6_l.forget - # Rule DV.7: COMP (except substrate tap) can not be partially overlapped by Dualgate. - logger.info("Executing rule DV.7") - dv7_l1 = dualgate.not_outside(comp_dv).not(dualgate.covering(comp_dv)) - dv7_l1.output("DV.7", "DV.7 : COMP (except substrate tap) can not be partially overlapped by Dualgate.") - dv7_l1.forget + # Rule DV.7: COMP (except substrate tap) can not be partially overlapped by Dualgate. + logger.info('Executing rule DV.7') + dv7_l1 = dualgate.not_outside(comp_dv).not(dualgate.covering(comp_dv)) + dv7_l1.output('DV.7', 'DV.7 : COMP (except substrate tap) can not be partially overlapped by Dualgate.') + dv7_l1.forget - comp_dv.forget + comp_dv.forget - # Rule DV.8: Min Dualgate enclose Poly2. is 0.4µm - logger.info("Executing rule DV.8") - dv8_l1 = dualgate.enclosing(poly2, 0.4.um, euclidian).polygons(0.001) - dv8_l2 = poly2.not_outside(dualgate).not(dualgate) - dv8_l = dv8_l1.or(dv8_l2) - dv8_l.output("DV.8", "DV.8 : Min Dualgate enclose Poly2. : 0.4µm") - dv8_l1.forget - dv8_l2.forget - dv8_l.forget - - # Rule DV.9: 3.3V and 5V/6V PMOS cannot be sitting inside same NWELL. - logger.info("Executing rule DV.9") - dv9_l1 = nwell.covering(pgate.and(dualgate)).covering(pgate.not_inside(v5_xtor).not_inside(dualgate)) - dv9_l1.output("DV.9", "DV.9 : 3.3V and 5V/6V PMOS cannot be sitting inside same NWELL.") - dv9_l1.forget -end #FEOL + # Rule DV.8: Min Dualgate enclose Poly2. is 0.4µm + logger.info('Executing rule DV.8') + dv8_l1 = dualgate.enclosing(poly2, 0.4.um, euclidian).polygons(0.001) + dv8_l2 = poly2.not_outside(dualgate).not(dualgate) + dv8_l = dv8_l1.or(dv8_l2) + dv8_l.output('DV.8', 'DV.8 : Min Dualgate enclose Poly2. : 0.4µm') + dv8_l1.forget + dv8_l2.forget + dv8_l.forget + # Rule DV.9: 3.3V and 5V/6V PMOS cannot be sitting inside same NWELL. + logger.info('Executing rule DV.9') + dv9_l1 = nwell.covering(pgate.and(dualgate)).covering(pgate.not_inside(v5_xtor).not_inside(dualgate)) + dv9_l1.output('DV.9', 'DV.9 : 3.3V and 5V/6V PMOS cannot be sitting inside same NWELL.') + dv9_l1.forget +end diff --git a/klayout/drc/rule_decks/dummy_exclude.drc b/klayout/drc/rule_decks/dummy_exclude.drc deleted file mode 100644 index ed3c4656..00000000 --- a/klayout/drc/rule_decks/dummy_exclude.drc +++ /dev/null @@ -1,43 +0,0 @@ -################################################################################################ -# 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. -################################################################################################ - -#================================================ -#--------------DUMMY EXCLUDE LAYERS-------------- -#================================================ - -# rule DE.1 is not a DRC check -## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_08.html#design-rules-for-dummy-exclude-layers-ndmy-and-pmndmy - -# Rule DE.2: Minimum NDMY or PMNDMY size (x or y dimension in um). is 0.8µm -logger.info("Executing rule DE.2") -de2_l1 = ndmy.or(pmndmy).width(0.8.um, euclidian) -de2_l1.output("DE.2", "DE.2 : Minimum NDMY or PMNDMY size (x or y dimension in um). : 0.8µm") -de2_l1.forget - -# Rule DE.3: If size greater than 15000 um2 then two sides should not be greater than (80 um). -logger.info("Executing rule DE.3") -de3_ndmy_area = ndmy.with_area(15000.um, nil) -de3_l1 = de3_ndmy_area.edges.with_length(80.001.um, nil) -de3_l1.output("DE.3", "DE.3 : If size greater than 15000 um2 then two sides should not be greater than (80 um).") -de3_l1.forget -de3_ndmy_area.forget - -# Rule DE.4: Minimum NDMY to NDMY space (Merge if space is less). is 20µm -logger.info("Executing rule DE.4") -de4_l1 = ndmy.space(20.um, euclidian) -de4_l1.output("DE.4", "DE.4 : Minimum NDMY to NDMY space (Merge if space is less). : 20µm") -de4_l1.forget - diff --git a/klayout/drc/rule_decks/efuse.drc b/klayout/drc/rule_decks/efuse.drc deleted file mode 100644 index ccaf55a0..00000000 --- a/klayout/drc/rule_decks/efuse.drc +++ /dev/null @@ -1,201 +0,0 @@ -################################################################################################ -# 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. -################################################################################################ - - -#================================================ -#---------------------EFUSE---------------------- -#================================================ - - -logger.info("Starting EFUSE derivations") -plfuse_efuse = plfuse.and(efuse_mk) - -# Rule EF.01: Min. (Poly2 butt PLFUSE) within EFUSE_MK and Pplus. -logger.info("Executing rule EF.01") -ef01_l1 = poly2.or(plfuse).interacting(efuse_mk).not_inside(efuse_mk.and(pplus)) -ef01_l1.output("EF.01", "EF.01 : Min. (Poly2 butt PLFUSE) within EFUSE_MK and Pplus.") -ef01_l1.forget - -# Rule EF.02: Min. Max. PLFUSE width. is 0.18µm -logger.info("Executing rule EF.02") -ef02_l1 = plfuse.drc(width != 0.18.um) -ef02_l1.output("EF.02", "EF.02 : Min. Max. PLFUSE width. : 0.18µm") -ef02_l1.forget - -# Rule EF.03: Min. Max. PLFUSE length. is 1.26µm -logger.info("Executing rule EF.03") -ef03_l1 = plfuse.edges.interacting(poly2.edges.and(plfuse.edges).centers(0, 0.95)).without_length(1.26.um) -ef03_l1.output("EF.03", "EF.03 : Min. Max. PLFUSE length. : 1.26µm") -ef03_l1.forget - -# Rule EF.04a: Min. Max. PLFUSE overlap Poly2 (coinciding permitted) and touch cathode and anode. -logger.info("Executing rule EF.04a") -ef04a_l1 = plfuse.not_in(plfuse.interacting(poly2.not(plfuse), 2, 2)).inside(efuse_mk).or(plfuse.not(poly2).inside(efuse_mk)) -ef04a_l1.output("EF.04a", "EF.04a : Min. Max. PLFUSE overlap Poly2 (coinciding permitted) and touch cathode and anode.") -ef04a_l1.forget - -# Rule EF.04b: PLFUSE must be rectangular. -logger.info("Executing rule EF.04b") -ef04b_l1 = plfuse.non_rectangles -ef04b_l1.output("EF.04b", "EF.04b : PLFUSE must be rectangular.") -ef04b_l1.forget - -# Rule EF.04c: Cathode Poly2 must be rectangular. -logger.info("Executing rule EF.04c") -cathode = poly2.and(efuse_mk).not(lvs_source.or(plfuse)) -ef04c_l1 = cathode.non_rectangles -ef04c_l1.output("EF.04c", "EF.04c : Cathode Poly2 must be rectangular.") -ef04c_l1.forget - -# Rule EF.04d: Anode Poly2 must be rectangular. -logger.info("Executing rule EF.04d") -anode = poly2.and(lvs_source).and(efuse_mk) -ef04d_l1 = anode.non_rectangles -ef04d_l1.output("EF.04d", "EF.04d : Anode Poly2 must be rectangular.") -ef04d_l1.forget - -# Rule EF.05: Min./Max. LVS_Source overlap Poly2 (at Anode). -logger.info("Executing rule EF.05") -ef05_l1 = poly2.not(plfuse).interacting(lvs_source).not(lvs_source).and(efuse_mk).or(lvs_source.not(poly2).and(efuse_mk)) -ef05_l1.output("EF.05", "EF.05 : Min./Max. LVS_Source overlap Poly2 (at Anode).") -ef05_l1.forget - -# Rule EF.06: Min./Max. Cathode Poly2 width. is 2.26µm -logger.info("Executing rule EF.06") -cathode_width = cathode.edges.not_interacting(cathode.edges.interacting(plfuse)).or(cathode.edges.interacting(plfuse)) -ef06_l1 = cathode_width.without_length(2.26.um) -ef06_l1.output("EF.06", "EF.06 : Min./Max. Cathode Poly2 width. : 2.26µm") -ef06_l1.forget - -# Rule EF.07: Min./Max. Cathode Poly2 length. is 1.84µm -logger.info("Executing rule EF.07") -ef07_l1 = cathode.edges.not(cathode_width).without_length(1.84.um) -ef07_l1.output("EF.07", "EF.07 : Min./Max. Cathode Poly2 length. : 1.84µm") -ef07_l1.forget - -# Rule EF.08: Min./Max. Anode Poly2 width. is 1.06µm -logger.info("Executing rule EF.08") -anode_width = anode.edges.not_interacting(anode.edges.interacting(plfuse)).or(anode.edges.interacting(plfuse)) -ef08_l1 = anode_width.without_length(1.06.um) -ef08_l1.output("EF.08", "EF.08 : Min./Max. Anode Poly2 width. : 1.06µm") -ef08_l1.forget - -# Rule EF.09: Min./Max. Anode Poly2 length. is 2.43µm -logger.info("Executing rule EF.09") -ef09_l1 = anode.edges.not(anode_width).without_length(2.43.um) -ef09_l1.output("EF.09", "EF.09 : Min./Max. Anode Poly2 length. : 2.43µm") -ef09_l1.forget -anode_width.forget - -# Rule EF.10: Min. Cathode Poly2 to Poly2 space. is 0.26µm -logger.info("Executing rule EF.10") -ef10_l1 = cathode.space(0.26.um, euclidian) -ef10_l1.output("EF.10", "EF.10 : Min. Cathode Poly2 to Poly2 space. : 0.26µm") -ef10_l1.forget - -# Rule EF.11: Min. Anode Poly2 to Poly2 space. is 0.26µm -logger.info("Executing rule EF.11") -ef11_l1 = anode.space(0.26.um, euclidian) -ef11_l1.output("EF.11", "EF.11 : Min. Anode Poly2 to Poly2 space. : 0.26µm") -ef11_l1.forget - -# Rule EF.12: Min. Space of Cathode Contact to PLFUSE end. -logger.info("Executing rule EF.12") -cont_ef = contact.and(plfuse_efuse) -ef12_l1 = plfuse_efuse.separation(contact.and(cathode), 0.155.um).polygons(0.001).or(cont_ef) -ef12_l1.output("EF.12", "EF.12 : Min. Space of Cathode Contact to PLFUSE end.") -ef12_l1.forget - -# Rule EF.13: Min. Space of Anode Contact to PLFUSE end. -logger.info("Executing rule EF.13") -ef13_l1 = plfuse_efuse.separation(contact.and(anode), 0.14.um).polygons(0.001).or(cont_ef) -ef13_l1.output("EF.13", "EF.13 : Min. Space of Anode Contact to PLFUSE end.") -ef13_l1.forget -cont_ef.forget - -# Rule EF.14: Min. EFUSE_MK enclose LVS_Source. -logger.info("Executing rule EF.14") -ef14_l1 = lvs_source.not_outside(efuse_mk).not(efuse_mk) -ef14_l1.output("EF.14", "EF.14 : Min. EFUSE_MK enclose LVS_Source.") -ef14_l1.forget - -# Rule EF.15: NO Contact is allowed to touch PLFUSE. -logger.info("Executing rule EF.15") -ef15_l1 = plfuse.interacting(contact) -ef15_l1.output("EF.15", "EF.15 : NO Contact is allowed to touch PLFUSE.") -ef15_l1.forget - -# Rule EF.16a: Cathode must contain exact number of Contacts at each ends. is 4µm -logger.info("Executing rule EF.16a") -ef16a_l1 = cathode.not_covering(contact, 4, 4) -ef16a_l1.output("EF.16a", "EF.16a : Cathode must contain exact number of Contacts at each ends. : 4µm") -ef16a_l1.forget - -# Rule EF.16b: Anode must contain exact number of Contacts at each ends. is 4µm -logger.info("Executing rule EF.16b") -ef16b_l1 = anode.not_covering(contact, 4, 4) -ef16b_l1.output("EF.16b", "EF.16b : Anode must contain exact number of Contacts at each ends. : 4µm") -ef16b_l1.forget - -# Rule EF.17: Min. Space of EFUSE_MK to EFUSE_MK. is 0.26µm -logger.info("Executing rule EF.17") -ef17_l1 = efuse_mk.space(0.26.um, euclidian) -ef17_l1.output("EF.17", "EF.17 : Min. Space of EFUSE_MK to EFUSE_MK. : 0.26µm") -ef17_l1.forget - -# Rule EF.18: PLFUSE must sit on field oxide (NOT COMP), no cross with any COMP, Nplus, Pplus, ESD, SAB, Resistor, Metal1, Metal2. -logger.info("Executing rule EF.18") -ef18_l1 = plfuse.not(plfuse.outside(comp).outside(nplus).outside(esd).outside(sab).outside(resistor).outside(metal1).outside(metal2)) -ef18_l1.output("EF.18", "EF.18 : PLFUSE must sit on field oxide (NOT COMP), no cross with any COMP, Nplus, Pplus, ESD, SAB, Resistor, Metal1, Metal2.") -ef18_l1.forget - -# Rule EF.19: Min. PLFUSE space to Metal1, Metal2. -logger.info("Executing rule EF.19") -ef19_l1 = plfuse.not(plfuse.outside(metal1).outside(metal2)) -ef19_l1.output("EF.19", "EF.19 : Min. PLFUSE space to Metal1, Metal2.") -ef19_l1.forget - -# Rule EF.20: Min. PLFUSE space to COMP, Nplus, Pplus, Resistor, ESD, SAB. is 2.73µm -logger.info("Executing rule EF.20") -ef20_l1 = plfuse.separation(comp + nplus + esd + sab + resistor, 2.73.um, euclidian) -ef20_l1.output("EF.20", "EF.20 : Min. PLFUSE space to COMP, Nplus, Pplus, Resistor, ESD, SAB. : 2.73µm") -ef20_l1.forget - -# Rule EF.21: Min./Max. eFUSE Poly2 length. is 5.53µm -logger.info("Executing rule EF.21") -ef_21_fuse = poly2.interacting(plfuse).inside(efuse_mk.and(pplus)).extents.edges -ef_21_anode = anode.edges.not_interacting(anode.edges.interacting(plfuse)) -ef_21_cathode = cathode.edges.not_interacting(cathode.edges.interacting(plfuse)) -ef21_l1 = ef_21_fuse.not_interacting(ef_21_anode.or(ef_21_cathode).centers(0, 0.95)).without_length(5.53.um) -ef21_l1.output("EF.21", "EF.21 : Min./Max. eFUSE Poly2 length. : 5.53µm") -ef21_l1.forget -ef_21_fuse.forget -ef_21_anode.forget -ef_21_cathode.forget - -# Rule EF.22a: Min./Max. Cathode Poly2 overlap with PLFUSE in width direction. is 1.04µm -logger.info("Executing rule EF.22a") -ef22a_l1 = cathode.edges.interacting(plfuse).not(plfuse.edges).without_length(1.04.um) -ef22a_l1.output("EF.22a", "EF.22a : Min./Max. Cathode Poly2 overlap with PLFUSE in width direction. : 1.04µm") -ef22a_l1.forget - -# Rule EF.22b: Min./Max. Anode Poly2 overlap with PLFUSE in width direction. is 0.44µm -logger.info("Executing rule EF.22b") -ef22b_l1 = anode.edges.interacting(plfuse).not(plfuse.edges).without_length(0.44.um) -ef22b_l1.output("EF.22b", "EF.22b : Min./Max. Anode Poly2 overlap with PLFUSE in width direction. : 0.44µm") -ef22b_l1.forget -plfuse_efuse.forget - diff --git a/klayout/drc/rule_decks/hres.drc b/klayout/drc/rule_decks/hres.drc deleted file mode 100644 index fb55001f..00000000 --- a/klayout/drc/rule_decks/hres.drc +++ /dev/null @@ -1,137 +0,0 @@ -################################################################################################ -# 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 - #================================================ - #----------------H POLY RESISTOR----------------- - #================================================ - - logger.info("Starting HRES derivations") - hres_poly = poly2.interacting(pplus).interacting(sab).interacting(res_mk).interacting(resistor) - hres1_poly = poly2.interacting(pplus).interacting(sab).interacting(res_mk) - - # Rule HRES.1: Minimum space. Note : Merge if the spacing is less than 0.4 um. is 0.4µm - logger.info("Executing rule HRES.1") - hres1_l1 = resistor.interacting(hres1_poly).space(0.4.um, euclidian) - hres1_l1.output("HRES.1", "HRES.1 : Minimum space. Note : Merge if the spacing is less than 0.4 um. : 0.4µm") - hres1_l1.forget - - # Rule HRES.2: Minimum width of Poly2 resistor. is 1µm - logger.info("Executing rule HRES.2") - hres2_l1 = hres_poly.width(1.um, euclidian) - hres2_l1.output("HRES.2", "HRES.2 : Minimum width of Poly2 resistor. : 1µm") - hres2_l1.forget - - # Rule HRES.3: Minimum space between Poly2 resistors. is 0.4µm - logger.info("Executing rule HRES.3") - hres3_l1 = hres_poly.space(0.4.um, euclidian) - hres3_l1.output("HRES.3", "HRES.3 : Minimum space between Poly2 resistors. : 0.4µm") - hres3_l1.forget - - # Rule HRES.4: Minimum RESISTOR overlap of Poly2 resistor. is 0.4µm - logger.info("Executing rule HRES.4") - hres4_l1 = hres_poly.enclosed(resistor, 0.4.um, euclidian).polygons(0.001) - hres4_l2 = hres_poly.not_outside(resistor).not(resistor) - hres4_l = hres4_l1.or(hres4_l2) - hres4_l.output("HRES.4", "HRES.4 : Minimum RESISTOR overlap of Poly2 resistor. : 0.4µm") - hres4_l1.forget - hres4_l2.forget - hres4_l.forget - - # Rule HRES.5: Minimum RESISTOR space to unrelated Poly2. is 0.3µm - logger.info("Executing rule HRES.5") - hres5_l1 = resistor.interacting(hres1_poly).separation(poly2.not_interacting(sab), 0.3.um, euclidian) - hres5_l1.output("HRES.5", "HRES.5 : Minimum RESISTOR space to unrelated Poly2. : 0.3µm") - hres5_l1.forget - - # Rule HRES.6: Minimum RESISTOR space to COMP. - logger.info("Executing rule HRES.6") - hres6_l1 = resistor.interacting(hres1_poly).separation(comp, 0.3.um, euclidian).polygons(0.001) - hres6_l2 = comp.not_outside(resistor.interacting(hres1_poly)) - hres6_l = hres6_l1.or(hres6_l2) - hres6_l.output("HRES.6", "HRES.6 : Minimum RESISTOR space to COMP.") - hres6_l.forget - hres6_l1.forget - hres6_l2.forget - hres1_poly.forget - - # Rule HRES.7: Minimum Pplus overlap of contact on Poly2 resistor. is 0.2µm - logger.info("Executing rule HRES.7") - hres7_l1 = contact.and(hres_poly).enclosed(pplus, 0.2.um, euclidian).polygons(0.001) - hres7_l2 = contact.and(hres_poly).not_outside(pplus).not(pplus) - hres7_l = hres7_l1.or(hres7_l2) - hres7_l.output("HRES.7", "HRES.7 : Minimum Pplus overlap of contact on Poly2 resistor. : 0.2µm") - hres7_l1.forget - hres7_l2.forget - hres7_l.forget - - # Rule HRES.8: Space from salicide block to contact on Poly2 resistor. - logger.info("Executing rule HRES.8") - hres8_l1 = contact.and(hres_poly).separation(sab,0.22.um).polygons(0.001).or(contact.and(hres_poly).interacting(sab)) - hres8_l1.output("HRES.8", "HRES.8 : Space from salicide block to contact on Poly2 resistor.") - hres8_l1.forget - - # Rule HRES.9: Minimum salicide block overlap of Poly2 resistor in width direction. - logger.info("Executing rule HRES.9") - hres9_sab = sab.interacting(pplus).interacting(res_mk).interacting(resistor) - hres9_clear_sab = hres9_sab.not(hres_poly) - hres9_bad_inside_edge = hres9_sab.edges.inside_part(hres_poly).extended(0,0,0.001,0.001).interacting(hres9_clear_sab, 1, 1) - hres9_sab_hole = hres9_sab.holes.and(hres_poly) - hres9_l1 = hres_poly.enclosed(hres9_sab, 0.28.um, euclidian).polygons(0.001) - hres9_l2 = hres9_bad_inside_edge.or(hres9_sab_hole) - hres9_l = hres9_l1.or(hres9_l2) - hres9_l.output("HRES.9", "HRES.9 : Minimum salicide block overlap of Poly2 resistor in width direction.") - hres9_l.forget - hres9_l1.forget - hres9_l2.forget - hres9_sab.forget - hres9_clear_sab.forget - hres9_bad_inside_edge.forget - hres9_sab_hole.forget - - # Rule HRES.10: Minimum & maximum Pplus overlap of SAB. - logger.info("Executing rule HRES.10") - pplus1_hres10 = pplus.and(sab).drc(width != 0.1.um) - pplus2_hres10 = pplus.not_overlapping(sab).edges - hres10_l1 = pplus1_hres10.or(pplus2_hres10).extended(0, 0, 0.001, 0.001).interacting(hres_poly) - hres10_l1.output("HRES.10", "HRES.10 : Minimum & maximum Pplus overlap of SAB.") - hres10_l1.forget - pplus1_hres10.forget - pplus2_hres10.forget - - # Rule HRES.11 is not a DRC check - ## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_03.html#hres-poly-resistor-phres-optional-with-one-additional-mask - - # Rule HRES.12a: P type Poly2 resistor (high sheet rho) shall be covered by RES_MK marking. RES_MK length shall be coincide with resistor length (Defined by Pplus space) and width covering the width of Poly2. - logger.info("Executing rule HRES.12a") - mk_hres12a = res_mk.edges.not(poly2.not(pplus).and(sab).edges).inside_part(poly2) - hres12a_l1 = res_mk.interacting(resistor).interacting(mk_hres12a) - hres12a_l1.output("HRES.12a", "HRES.12a : P type Poly2 resistor (high sheet rho) shall be covered by RES_MK marking. RES_MK length shall be coincide with resistor length (Defined by Pplus space) and width covering the width of Poly2. ") - hres12a_l1.forget - mk_hres12a.forget - - # Rule HRES.12b: If the size of single RES_MK mark layer is greater than 15000 um2 and both side (X and Y) are greater than 80 um. Then the minimum spacing to adjacent RES_MK layer. is 20µm - logger.info("Executing rule HRES.12b") - hres12b = res_mk.with_area(15000.001.um,nil).edges.with_length(80.001.um,nil) - hres12b_l1 = hres12b.separation(res_mk.edges, 20.um) - hres12b_l1.output("HRES.12b", "HRES.12b : If the size of single RES_MK mark layer is greater than 15000 um2 and both side (X and Y) are greater than 80 um. Then the minimum spacing to adjacent RES_MK layer. : 20µm") - hres12b_l1.forget - hres12b.forget - hres_poly.forget - -end #FEOL - diff --git a/klayout/drc/rule_decks/lres.drc b/klayout/drc/rule_decks/lres.drc deleted file mode 100644 index 9f5d7ecd..00000000 --- a/klayout/drc/rule_decks/lres.drc +++ /dev/null @@ -1,100 +0,0 @@ -################################################################################################ -# 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 - #================================================ - #----------------N+ POLY RESISTOR---------------- - #================================================ - - logger.info("Starting LRES derivations") - lres_poly = poly2.and(nplus).interacting(sab).interacting(res_mk) - - # Rule LRES.1: Minimum width of Poly2 resistor. is 0.8µm - logger.info("Executing rule LRES.1") - lres1_l1 = lres_poly.width(0.8.um, euclidian) - lres1_l1.output("LRES.1", "LRES.1 : Minimum width of Poly2 resistor. : 0.8µm") - lres1_l1.forget - - # Rule LRES.2: Minimum space between Poly2 resistors. is 0.4µm - logger.info("Executing rule LRES.2") - lres2_l1 = lres_poly.isolated(0.4.um, euclidian) - lres2_l1.output("LRES.2", "LRES.2 : Minimum space between Poly2 resistors. : 0.4µm") - lres2_l1.forget - - # Rule LRES.3: Minimum space from Poly2 resistor to COMP. - logger.info("Executing rule LRES.3") - lres3_l1 = lres_poly.separation(comp, 0.6.um, euclidian).polygons(0.001).or(comp.not_outside(lres_poly)) - lres3_l1.output("LRES.3", "LRES.3 : Minimum space from Poly2 resistor to COMP.") - lres3_l1.forget - - # Rule LRES.4: Minimum space from Poly2 resistor to unrelated Poly2. is 0.6µm - logger.info("Executing rule LRES.4") - lres4_l1 = lres_poly.separation(poly2.not_interacting(sab), 0.6.um, euclidian) - lres4_l1.output("LRES.4", "LRES.4 : Minimum space from Poly2 resistor to unrelated Poly2. : 0.6µm") - lres4_l1.forget - - # Rule LRES.5: Minimum Nplus implant overlap of Poly2 resistor. is 0.3µm - logger.info("Executing rule LRES.5") - lres5_l1 = lres_poly.enclosed(nplus, 0.3.um, euclidian).polygons(0.001) - lres5_l2 = lres_poly.not_outside(nplus).not(nplus) - lres5_l = lres5_l1.or(lres5_l2) - lres5_l.output("LRES.5", "LRES.5 : Minimum Nplus implant overlap of Poly2 resistor. : 0.3µm") - lres5_l1.forget - lres5_l2.forget - lres5_l.forget - - # Rule LRES.6: Minimum salicide block overlap of Poly2 resistor in width direction. is 0.28µm - logger.info("Executing rule LRES.6") - lres6_l1 = lres_poly.enclosed(sab,0.28.um) - lres6_l1.output("LRES.6", "LRES.6 : Minimum salicide block overlap of Poly2 resistor in width direction. : 0.28µm") - lres6_l1.forget - - # Rule LRES.7: Space from salicide block to contact on Poly2 resistor. - logger.info("Executing rule LRES.7") - cont_lres7 = contact.and(lres_poly) - lres7_l1 = cont_lres7.separation(sab,0.22.um).polygons(0.001) - lres7_l2 = cont_lres7.interacting(sab) - lres7_l = lres7_l1.or(lres7_l2) - lres7_l.output("LRES.7", "LRES.7 : Space from salicide block to contact on Poly2 resistor.") - lres7_l.forget - lres7_l1.forget - lres7_l2.forget - cont_lres7.forget - - # Rule LRES.8 is not a DRC check - ## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_02.html#n-poly-resistor-low-sheet-rho - - # Rule LRES.9a: Nplus Poly2 resistor shall be covered by RES_MK marking. RES_MK length shall be coincide with resistor length (Defined by SAB length) and width covering the width of Poly2. - logger.info("Executing rule LRES.9a") - mk_lres9 = res_mk.edges.not(poly2.and(nplus).and(sab).edges).inside_part(poly2) - lres9a_l1 = res_mk.interacting(lres_poly).interacting(mk_lres9) - lres9a_l1.output("LRES.9a", "LRES.9a : Nplus Poly2 resistor shall be covered by RES_MK marking. RES_MK length shall be coincide with resistor length (Defined by SAB length) and width covering the width of Poly2. ") - lres9a_l1.forget - mk_lres9.forget - - # Rule LRES.9b: If the size of single RES_MK mark layer is greater than 15000um2 and both side (X and Y) are greater than 80um. - ## then the minimum spacing to adjacent RES_MK layer. is 20µm - logger.info("Executing rule LRES.9b") - lres9b = res_mk.with_area(15000.001.um,nil).edges.with_length(80.001.um,nil) - lres9b_l1 = lres9b.separation(res_mk.edges, 20.um) - lres9b_l1.output("LRES.9b", "LRES.9b : If the size of single RES_MK mark layer is greater than 15000um2 and both side (X and Y) are greater than 80um. then the minimum spacing to adjacent RES_MK layer. : 20µm") - lres9b_l1.forget - lres9b.forget - lres_poly.forget - -end #FEOL - diff --git a/klayout/drc/rule_decks/lvs_bjt.drc b/klayout/drc/rule_decks/lvs_bjt.drc deleted file mode 100644 index 38ad912b..00000000 --- a/klayout/drc/rule_decks/lvs_bjt.drc +++ /dev/null @@ -1,34 +0,0 @@ -################################################################################################ -# 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 - #================================================ - #--------------------LVS_BJT--------------------- - #================================================ - - vnpn_e = ncomp.interacting(lvs_bjt).inside(dnwell) - vpnp_e = pcomp.inside(nwell).interacting(lvs_bjt) - # Rule LVS_BJT.1: Minimum LVS_BJT enclosure of NPN or PNP Emitter COMP layers - logger.info("Executing rule LVS_BJT.1") - lvs_l1 = vnpn_e.or(vpnp_e).not_inside(lvs_bjt) - lvs_l1.output("LVS_BJT.1", "LVS_BJT.1 : Minimum LVS_BJT enclosure of NPN or PNP Emitter COMP layers") - lvs_l1.forget - - vnpn_e.forget - - vpnp_e.forget -end #FEOL - diff --git a/klayout/drc/rule_decks/main.drc b/klayout/drc/rule_decks/main.drc index e575e6c1..56a3b256 100644 --- a/klayout/drc/rule_decks/main.drc +++ b/klayout/drc/rule_decks/main.drc @@ -14,880 +14,788 @@ # limitations under the License. ################################################################################################ -#=========================================================================================================================== -#------------------------------------------- GF 0.18um MCU DRC RULE DECK -------------------------------------------------- -#=========================================================================================================================== +#======================================================================================================================= +#--------------------------------------------- GF 0.18um MCU DRC RULE DECK --------------------------------------------- +#======================================================================================================================= require 'time' -require "logger" +require 'logger' require 'etc' exec_start_time = Time.now -logger = Logger.new(STDOUT) +logger = Logger.new($stdout) -logger.formatter = proc do |severity, datetime, progname, msg| - "#{datetime}: Memory Usage (" + `pmap #{Process.pid} | tail -1`[10,40].strip + ") : #{msg} +logger.formatter = proc do |_severity, datetime, _progname, msg| + "#{datetime}: Memory Usage (" + `pmap #{Process.pid} | tail -1`[10, 40].strip + ") : #{msg} " end #================================================ #----------------- FILE SETUP ------------------- #================================================ -logger.info("Starting running GF180MCU Klayout DRC runset on %s" % [$input]) -logger.info("Ruby Version for klayout: %s" % [RUBY_VERSION]) +logger.info("Starting running GF180MCU Klayout DRC runset on #{$input}") +logger.info("Ruby Version for klayout: #{RUBY_VERSION}") if $input - if $topcell - source($input, $topcell) - else - source($input) - end -end - -if $table_name - table_name = $table_name -else - table_name = "main" + if $topcell + source($input, $topcell) + else + source($input) + end end - -logger.info("Loading database to memory is complete.") +logger.info('Loading database to memory is complete.') if $report - logger.info("GF180MCU Klayout DRC runset output at: %s" % [$report]) - report("DRC Run Report at", $report) + logger.info("GF180MCU Klayout DRC runset output at: #{$report}") + report('DRC Run Report at', $report) else - layout_dir = Pathname.new(RBA::CellView::active.filename).parent.realpath - report_path = layout_dir.join("gf180_drc.lyrdb").to_s - logger.info("GF180MCU Klayout DRC runset output at default location: %s" % report_path) - report("DRC Run Report at", report_path) + layout_dir = Pathname.new(RBA::CellView.active.filename).parent.realpath + report_path = layout_dir.join('gf180_drc.lyrdb').to_s + logger.info('GF180MCU Klayout DRC runset output at default location: %s', report_path) + report('DRC Run Report at', report_path) end #================================================ #------------------ SWITCHES -------------------- #================================================ -logger.info("Evaluate switches.") +logger.info('Evaluate switches.') # connectivity rules -if $conn_drc == "true" +if $conn_drc == 'true' CONNECTIVITY_RULES = $conn_drc - logger.info("connectivity rules are enabled.") + logger.info('connectivity rules are enabled.') else CONNECTIVITY_RULES = false - logger.info("connectivity rules are disabled.") -end # connectivity rules + logger.info('connectivity rules are disabled.') +end # WEDGE -if $wedge == "false" - WEDGE = $wedge -else - WEDGE = "true" -end # WEDGE +WEDGE = if $wedge == 'false' + $wedge + else + 'true' + end -logger.info("Wedge enabled %s" % [WEDGE]) +logger.info("Wedge enabled: #{WEDGE}") # BALL -if $ball == "false" - BALL = $ball -else - BALL = "true" -end # BALL +BALL = if $ball == 'false' + $ball + else + 'true' + end -logger.info("Ball enabled %s" % [BALL]) +logger.info("Ball enabled: #{BALL}") # GOLD -if $gold == "false" - GOLD = $gold -else - GOLD = "true" -end # GOLD +GOLD = if $gold == 'false' + $gold + else + 'true' + end -logger.info("Gold enabled %s" % [GOLD]) +logger.info("Gold enabled: #{GOLD}") -if $mim_option - MIM_OPTION = $mim_option -else - MIM_OPTION = "B" -end +# MIM +MIM_OPTION = $mim_option || 'B' -logger.info("MIM Option selected %s" % [MIM_OPTION]) +logger.info("MIM Option selected: #{MIM_OPTION}") # OFFGRID -if $offgrid == "false" - OFFGRID = false -else - OFFGRID = true -end # OFFGRID +OFFGRID = $offgrid != 'false' -logger.info("Offgrid enabled %s" % [OFFGRID]) +logger.info("Offgrid enabled: #{OFFGRID}") +# threads if $thr - threads($thr) + threads($thr) else - thr ||= Etc.nprocessors - threads(thr) + thr ||= Etc.nprocessors + threads(thr) end -logger.info("Number of threads to use %s" % [$thr]) + +logger.info("Number of threads to use #{$thr}") #=== PRINT DETAILS === logger.info("Verbose mode: #{$verbose}") -if $verbose == "true" +if $verbose == 'true' verbose(true) else verbose(false) end # === TILING MODE === -if $run_mode == "tiling" +case $run_mode +when 'tiling' tiles(500.um) tile_borders(10.um) - logger.info("Tiling mode is enabled.") + logger.info('Tiling mode is enabled.') -elsif $run_mode == "deep" +when 'deep' #=== HIER MODE === deep - logger.info("deep mode is enabled.") + logger.info('deep mode is enabled.') else #=== FLAT MODE === flat - logger.info("flat mode is enabled.") -end # run_mode + logger.info('flat mode is enabled.') +end # METAL_TOP -if $metal_top - METAL_TOP = $metal_top -else - METAL_TOP = "9K" -end # METAL_TOP +METAL_TOP = $metal_top || '9K' -logger.info("METAL_TOP Selected is %s" % [METAL_TOP]) +logger.info("METAL_TOP Selected is #{METAL_TOP}") # METAL_LEVEL -if $metal_level - METAL_LEVEL = $metal_level -else - METAL_LEVEL = "5LM" -end # METAL_LEVEL +METAL_LEVEL = $metal_level || '5LM' -logger.info("METAL_STACK Selected is %s" % [METAL_LEVEL]) +logger.info("METAL_STACK Selected is #{METAL_LEVEL}") # FEOL -if $feol == "false" +if $feol == 'false' FEOL = $feol - logger.info("FEOL is disabled.") + logger.info('FEOL is disabled.') else - FEOL = "true" - logger.info("FEOL is enabled.") -end # FEOL + FEOL = 'true'.freeze + logger.info('FEOL is enabled.') +end # BEOL -if $beol == "false" +if $beol == 'false' BEOL = $beol - logger.info("BEOL is disabled.") + logger.info('BEOL is disabled.') else - BEOL = "true" - logger.info("BEOL is enabled.") -end # BEOL + BEOL = 'true'.freeze + logger.info('BEOL is enabled.') +end #================================================ #------------- LAYERS DEFINITIONS --------------- #================================================ polygons_count = 0 -logger.info("Read in polygons from layers.") +logger.info('Read in polygons from layers.') -def get_polygons(l, d) - ps = polygons(l, d) - return $run_mode == "deep" ? ps : ps.merged +def get_polygons(layer, data_type) + ps = polygons(layer, data_type) + $run_mode == 'deep' ? ps : ps.merged end -comp = get_polygons(22 , 0 ) -count = comp.count() -logger.info("comp has %d polygons" % [count]) -polygons_count += count - -dnwell = get_polygons(12 , 0 ) -count = dnwell.count() -logger.info("dnwell has %d polygons" % [count]) -polygons_count += count - -nwell = get_polygons(21 , 0 ) -count = nwell.count() -logger.info("nwell has %d polygons" % [count]) -polygons_count += count - -lvpwell = get_polygons(204, 0 ) -count = lvpwell.count() -logger.info("lvpwell has %d polygons" % [count]) -polygons_count += count - -dualgate = get_polygons(55 , 0 ) -count = dualgate.count() -logger.info("dualgate has %d polygons" % [count]) -polygons_count += count - -poly2 = get_polygons(30 , 0 ) -count = poly2.count() -logger.info("poly2 has %d polygons" % [count]) -polygons_count += count - -nplus = get_polygons(32 , 0 ) -count = nplus.count() -logger.info("nplus has %d polygons" % [count]) -polygons_count += count - -pplus = get_polygons(31 , 0 ) -count = pplus.count() -logger.info("pplus has %d polygons" % [count]) -polygons_count += count - -sab = get_polygons(49 , 0 ) -count = sab.count() -logger.info("sab has %d polygons" % [count]) -polygons_count += count - -esd = get_polygons(24 , 0 ) -count = esd.count() -logger.info("esd has %d polygons" % [count]) -polygons_count += count - -resistor = get_polygons(62 , 0 ) -count = resistor.count() -logger.info("resistor has %d polygons" % [count]) -polygons_count += count - -fhres = get_polygons(227, 0 ) -count = fhres.count() -logger.info("fhres has %d polygons" % [count]) -polygons_count += count - -fusetop = get_polygons(75 , 0 ) -count = fusetop.count() -logger.info("fusetop has %d polygons" % [count]) -polygons_count += count - -fusewindow_d = get_polygons(96 , 1 ) -count = fusewindow_d.count() -logger.info("fusewindow_d has %d polygons" % [count]) -polygons_count += count - -polyfuse = get_polygons(220, 0 ) -count = polyfuse.count() -logger.info("polyfuse has %d polygons" % [count]) -polygons_count += count - -mvsd = get_polygons(210, 0 ) -count = mvsd.count() -logger.info("mvsd has %d polygons" % [count]) -polygons_count += count - -mvpsd = get_polygons(11 , 39) -count = mvpsd.count() -logger.info("mvpsd has %d polygons" % [count]) -polygons_count += count - -nat = get_polygons(5 , 0 ) -count = nat.count() -logger.info("nat has %d polygons" % [count]) -polygons_count += count - -comp_dummy = get_polygons(22 , 4 ) -count = comp_dummy.count() -logger.info("comp_dummy has %d polygons" % [count]) -polygons_count += count - -poly2_dummy = get_polygons(30 , 4 ) -count = poly2_dummy.count() -logger.info("poly2_dummy has %d polygons" % [count]) -polygons_count += count - -schottky_diode = get_polygons(241, 0 ) -count = schottky_diode.count() -logger.info("schottky_diode has %d polygons" % [count]) -polygons_count += count - -zener = get_polygons(178, 0 ) -count = zener.count() -logger.info("zener has %d polygons" % [count]) -polygons_count += count - -res_mk = get_polygons(110, 5 ) -count = res_mk.count() -logger.info("res_mk has %d polygons" % [count]) -polygons_count += count - -opc_drc = get_polygons(124, 5 ) -count = opc_drc.count() -logger.info("opc_drc has %d polygons" % [count]) -polygons_count += count - -ndmy = get_polygons(111, 5 ) -count = ndmy.count() -logger.info("ndmy has %d polygons" % [count]) -polygons_count += count - -pmndmy = get_polygons(152, 5 ) -count = pmndmy.count() -logger.info("pmndmy has %d polygons" % [count]) -polygons_count += count - -v5_xtor = get_polygons(112, 1 ) -count = v5_xtor.count() -logger.info("v5_xtor has %d polygons" % [count]) -polygons_count += count - -cap_mk = get_polygons(117, 5 ) -count = cap_mk.count() -logger.info("cap_mk has %d polygons" % [count]) -polygons_count += count - -mos_cap_mk = get_polygons(166, 5 ) -count = mos_cap_mk.count() -logger.info("mos_cap_mk has %d polygons" % [count]) -polygons_count += count - -ind_mk = get_polygons(151, 5 ) -count = ind_mk.count() -logger.info("ind_mk has %d polygons" % [count]) -polygons_count += count - -diode_mk = get_polygons(115, 5 ) -count = diode_mk.count() -logger.info("diode_mk has %d polygons" % [count]) -polygons_count += count - -drc_bjt = get_polygons(127, 5 ) -count = drc_bjt.count() -logger.info("drc_bjt has %d polygons" % [count]) -polygons_count += count - -lvs_bjt = get_polygons(118, 5 ) -count = lvs_bjt.count() -logger.info("lvs_bjt has %d polygons" % [count]) -polygons_count += count - -mim_l_mk = get_polygons(117, 10) -count = mim_l_mk.count() -logger.info("mim_l_mk has %d polygons" % [count]) -polygons_count += count - -latchup_mk = get_polygons(137, 5 ) -count = latchup_mk.count() -logger.info("latchup_mk has %d polygons" % [count]) -polygons_count += count - -guard_ring_mk = get_polygons(167, 5 ) -count = guard_ring_mk.count() -logger.info("guard_ring_mk has %d polygons" % [count]) -polygons_count += count - -otp_mk = get_polygons(173, 5 ) -count = otp_mk.count() -logger.info("otp_mk has %d polygons" % [count]) -polygons_count += count - -mtpmark = get_polygons(122, 5 ) -count = mtpmark.count() -logger.info("mtpmark has %d polygons" % [count]) -polygons_count += count - -neo_ee_mk = get_polygons(88 , 17) -count = neo_ee_mk.count() -logger.info("neo_ee_mk has %d polygons" % [count]) -polygons_count += count - -sramcore = get_polygons(108, 5 ) -count = sramcore.count() -logger.info("sramcore has %d polygons" % [count]) -polygons_count += count - -lvs_rf = get_polygons(100, 5 ) -count = lvs_rf.count() -logger.info("lvs_rf has %d polygons" % [count]) -polygons_count += count - -lvs_drain = get_polygons(100, 7 ) -count = lvs_drain.count() -logger.info("lvs_drain has %d polygons" % [count]) -polygons_count += count - -ind_mk = get_polygons(151, 5 ) -count = ind_mk.count() -logger.info("ind_mk has %d polygons" % [count]) -polygons_count += count - -hvpolyrs = get_polygons(123, 5 ) -count = hvpolyrs.count() -logger.info("hvpolyrs has %d polygons" % [count]) -polygons_count += count - -lvs_io = get_polygons(119, 5 ) -count = lvs_io.count() -logger.info("lvs_io has %d polygons" % [count]) -polygons_count += count - -probe_mk = get_polygons(13 , 17) -count = probe_mk.count() -logger.info("probe_mk has %d polygons" % [count]) -polygons_count += count - -esd_mk = get_polygons(24 , 5 ) -count = esd_mk.count() -logger.info("esd_mk has %d polygons" % [count]) -polygons_count += count - -lvs_source = get_polygons(100, 8 ) -count = lvs_source.count() -logger.info("lvs_source has %d polygons" % [count]) -polygons_count += count - -well_diode_mk = get_polygons(153, 51) -count = well_diode_mk.count() -logger.info("well_diode_mk has %d polygons" % [count]) -polygons_count += count - -ldmos_xtor = get_polygons(226, 0 ) -count = ldmos_xtor.count() -logger.info("ldmos_xtor has %d polygons" % [count]) -polygons_count += count - -plfuse = get_polygons(125, 5 ) -count = plfuse.count() -logger.info("plfuse has %d polygons" % [count]) -polygons_count += count - -efuse_mk = get_polygons(80 , 5 ) -count = efuse_mk.count() -logger.info("efuse_mk has %d polygons" % [count]) -polygons_count += count - -mcell_feol_mk = get_polygons(11 , 17) -count = mcell_feol_mk.count() -logger.info("mcell_feol_mk has %d polygons" % [count]) -polygons_count += count - -ymtp_mk = get_polygons(86 , 17) -count = ymtp_mk.count() -logger.info("ymtp_mk has %d polygons" % [count]) -polygons_count += count - -dev_wf_mk = get_polygons(128, 17) -count = dev_wf_mk.count() -logger.info("dev_wf_mk has %d polygons" % [count]) -polygons_count += count - -comp_label = get_polygons(22 , 10) -count = comp_label.count() -logger.info("comp_label has %d polygons" % [count]) -polygons_count += count - -poly2_label = get_polygons(30 , 10) -count = poly2_label.count() -logger.info("poly2_label has %d polygons" % [count]) -polygons_count += count - -mdiode = get_polygons(116, 5 ) -count = mdiode.count() -logger.info("mdiode has %d polygons" % [count]) -polygons_count += count - -contact = get_polygons(33 , 0 ) -count = contact.count() -logger.info("contact has %d polygons" % [count]) -polygons_count += count - -metal1_drawn = get_polygons(34 , 0 ) -count = metal1_drawn.count() -logger.info("metal1_drawn has %d polygons" % [count]) -polygons_count += count - -metal1_dummy = get_polygons(34 , 4 ) -count = metal1_dummy.count() -logger.info("metal1_dummy has %d polygons" % [count]) -polygons_count += count +comp = get_polygons(22, 0) +count = comp.count +logger.info("comp has #{count} polygons") +polygons_count += count + +dnwell = get_polygons(12, 0) +count = dnwell.count +logger.info("dnwell has #{count} polygons") +polygons_count += count + +nwell = get_polygons(21, 0) +count = nwell.count +logger.info("nwell has #{count} polygons") +polygons_count += count + +lvpwell = get_polygons(204, 0) +count = lvpwell.count +logger.info("lvpwell has #{count} polygons") +polygons_count += count + +dualgate = get_polygons(55, 0) +count = dualgate.count +logger.info("dualgate has #{count} polygons") +polygons_count += count + +poly2 = get_polygons(30, 0) +count = poly2.count +logger.info("poly2 has #{count} polygons") +polygons_count += count + +nplus = get_polygons(32, 0) +count = nplus.count +logger.info("nplus has #{count} polygons") +polygons_count += count + +pplus = get_polygons(31, 0) +count = pplus.count +logger.info("pplus has #{count} polygons") +polygons_count += count + +sab = get_polygons(49, 0) +count = sab.count +logger.info("sab has #{count} polygons") +polygons_count += count + +esd = get_polygons(24, 0) +count = esd.count +logger.info("esd has #{count} polygons") +polygons_count += count + +resistor = get_polygons(62, 0) +count = resistor.count +logger.info("resistor has #{count} polygons") +polygons_count += count + +fhres = get_polygons(227, 0) +count = fhres.count +logger.info("fhres has #{count} polygons") +polygons_count += count + +fusetop = get_polygons(75, 0) +count = fusetop.count +logger.info("fusetop has #{count} polygons") +polygons_count += count + +fusewindow_d = get_polygons(96, 1) +count = fusewindow_d.count +logger.info("fusewindow_d has #{count} polygons") +polygons_count += count + +polyfuse = get_polygons(220, 0) +count = polyfuse.count +logger.info("polyfuse has #{count} polygons") +polygons_count += count + +mvsd = get_polygons(210, 0) +count = mvsd.count +logger.info("mvsd has #{count} polygons") +polygons_count += count + +mvpsd = get_polygons(11, 39) +count = mvpsd.count +logger.info("mvpsd has #{count} polygons") +polygons_count += count + +nat = get_polygons(5, 0) +count = nat.count +logger.info("nat has #{count} polygons") +polygons_count += count + +comp_dummy = get_polygons(22, 4) +count = comp_dummy.count +logger.info("comp_dummy has #{count} polygons") +polygons_count += count + +poly2_dummy = get_polygons(30, 4) +count = poly2_dummy.count +logger.info("poly2_dummy has #{count} polygons") +polygons_count += count + +schottky_diode = get_polygons(241, 0) +count = schottky_diode.count +logger.info("schottky_diode has #{count} polygons") +polygons_count += count + +zener = get_polygons(178, 0) +count = zener.count +logger.info("zener has #{count} polygons") +polygons_count += count + +res_mk = get_polygons(110, 5) +count = res_mk.count +logger.info("res_mk has #{count} polygons") +polygons_count += count + +opc_drc = get_polygons(124, 5) +count = opc_drc.count +logger.info("opc_drc has #{count} polygons") +polygons_count += count + +ndmy = get_polygons(111, 5) +count = ndmy.count +logger.info("ndmy has #{count} polygons") +polygons_count += count + +pmndmy = get_polygons(152, 5) +count = pmndmy.count +logger.info("pmndmy has #{count} polygons") +polygons_count += count + +v5_xtor = get_polygons(112, 1) +count = v5_xtor.count +logger.info("v5_xtor has #{count} polygons") +polygons_count += count + +cap_mk = get_polygons(117, 5) +count = cap_mk.count +logger.info("cap_mk has #{count} polygons") +polygons_count += count + +mos_cap_mk = get_polygons(166, 5) +count = mos_cap_mk.count +logger.info("mos_cap_mk has #{count} polygons") +polygons_count += count + +ind_mk = get_polygons(151, 5) +count = ind_mk.count +logger.info("ind_mk has #{count} polygons") +polygons_count += count + +diode_mk = get_polygons(115, 5) +count = diode_mk.count +logger.info("diode_mk has #{count} polygons") +polygons_count += count + +drc_bjt = get_polygons(127, 5) +count = drc_bjt.count +logger.info("drc_bjt has #{count} polygons") +polygons_count += count + +lvs_bjt = get_polygons(118, 5) +count = lvs_bjt.count +logger.info("lvs_bjt has #{count} polygons") +polygons_count += count + +mim_l_mk = get_polygons(117, 10) +count = mim_l_mk.count +logger.info("mim_l_mk has #{count} polygons") +polygons_count += count + +latchup_mk = get_polygons(137, 5) +count = latchup_mk.count +logger.info("latchup_mk has #{count} polygons") +polygons_count += count + +guard_ring_mk = get_polygons(167, 5) +count = guard_ring_mk.count +logger.info("guard_ring_mk has #{count} polygons") +polygons_count += count + +otp_mk = get_polygons(173, 5) +count = otp_mk.count +logger.info("otp_mk has #{count} polygons") +polygons_count += count + +mtpmark = get_polygons(122, 5) +count = mtpmark.count +logger.info("mtpmark has #{count} polygons") +polygons_count += count + +neo_ee_mk = get_polygons(88, 17) +count = neo_ee_mk.count +logger.info("neo_ee_mk has #{count} polygons") +polygons_count += count + +sramcore = get_polygons(108, 5) +count = sramcore.count +logger.info("sramcore has #{count} polygons") +polygons_count += count + +lvs_rf = get_polygons(100, 5) +count = lvs_rf.count +logger.info("lvs_rf has #{count} polygons") +polygons_count += count + +lvs_drain = get_polygons(100, 7) +count = lvs_drain.count +logger.info("lvs_drain has #{count} polygons") +polygons_count += count + +ind_mk = get_polygons(151, 5) +count = ind_mk.count +logger.info("ind_mk has #{count} polygons") +polygons_count += count + +hvpolyrs = get_polygons(123, 5) +count = hvpolyrs.count +logger.info("hvpolyrs has #{count} polygons") +polygons_count += count + +lvs_io = get_polygons(119, 5) +count = lvs_io.count +logger.info("lvs_io has #{count} polygons") +polygons_count += count + +probe_mk = get_polygons(13, 17) +count = probe_mk.count +logger.info("probe_mk has #{count} polygons") +polygons_count += count + +esd_mk = get_polygons(24, 5) +count = esd_mk.count +logger.info("esd_mk has #{count} polygons") +polygons_count += count + +lvs_source = get_polygons(100, 8) +count = lvs_source.count +logger.info("lvs_source has #{count} polygons") +polygons_count += count + +well_diode_mk = get_polygons(153, 51) +count = well_diode_mk.count +logger.info("well_diode_mk has #{count} polygons") +polygons_count += count + +ldmos_xtor = get_polygons(226, 0) +count = ldmos_xtor.count +logger.info("ldmos_xtor has #{count} polygons") +polygons_count += count + +plfuse = get_polygons(125, 5) +count = plfuse.count +logger.info("plfuse has #{count} polygons") +polygons_count += count + +efuse_mk = get_polygons(80, 5) +count = efuse_mk.count +logger.info("efuse_mk has #{count} polygons") +polygons_count += count + +mcell_feol_mk = get_polygons(11, 17) +count = mcell_feol_mk.count +logger.info("mcell_feol_mk has #{count} polygons") +polygons_count += count + +ymtp_mk = get_polygons(86, 17) +count = ymtp_mk.count +logger.info("ymtp_mk has #{count} polygons") +polygons_count += count + +dev_wf_mk = get_polygons(128, 17) +count = dev_wf_mk.count +logger.info("dev_wf_mk has #{count} polygons") +polygons_count += count + +comp_label = get_polygons(22, 10) +count = comp_label.count +logger.info("comp_label has #{count} polygons") +polygons_count += count + +poly2_label = get_polygons(30, 10) +count = poly2_label.count +logger.info("poly2_label has #{count} polygons") +polygons_count += count + +mdiode = get_polygons(116, 5) +count = mdiode.count +logger.info("mdiode has #{count} polygons") +polygons_count += count + +contact = get_polygons(33, 0) +count = contact.count +logger.info("contact has #{count} polygons") +polygons_count += count + +metal1_drawn = get_polygons(34, 0) +count = metal1_drawn.count +logger.info("metal1_drawn has #{count} polygons") +polygons_count += count + +metal1_dummy = get_polygons(34, 4) +count = metal1_dummy.count +logger.info("metal1_dummy has #{count} polygons") +polygons_count += count metal1 = metal1_drawn + metal1_dummy -metal1_label = get_polygons(34 , 10) -count = metal1_label.count() -logger.info("metal1_label has %d polygons" % [count]) -polygons_count += count - -metal1_slot = get_polygons(34 , 3 ) -count = metal1_slot.count() -logger.info("metal1_slot has %d polygons" % [count]) -polygons_count += count - -metal1_blk = get_polygons(34 , 5 ) -count = metal1_blk.count() -logger.info("metal1_blk has %d polygons" % [count]) -polygons_count += count - -via1 = get_polygons(35 , 0 ) -count = via1.count() -logger.info("via1 has %d polygons" % [count]) -polygons_count += count - - -if METAL_LEVEL == "2LM" - metal2_drawn = get_polygons(36 , 0 ) - count = metal2_drawn.count() - logger.info("metal2_drawn has %d polygons" % [count]) - polygons_count += count - - metal2_dummy = get_polygons(36 , 4 ) - count = metal2_dummy.count() - logger.info("metal2_dummy has %d polygons" % [count]) - polygons_count += count - - metal2 = metal2_drawn + metal2_dummy - - metal2_label = get_polygons(36 , 10) - count = metal2_label.count() - logger.info("metal2_label has %d polygons" % [count]) - polygons_count += count - - metal2_slot = get_polygons(36 , 3 ) - count = metal2_slot.count() - logger.info("metal2_slot has %d polygons" % [count]) - polygons_count += count - - metal2_blk = get_polygons(36 , 5 ) - count = metal2_blk.count() - logger.info("metal2_blk has %d polygons" % [count]) - polygons_count += count - +metal1_label = get_polygons(34, 10) +count = metal1_label.count +logger.info("metal1_label has #{count} polygons") +polygons_count += count + +metal1_slot = get_polygons(34, 3) +count = metal1_slot.count +logger.info("metal1_slot has #{count} polygons") +polygons_count += count + +metal1_blk = get_polygons(34, 5) +count = metal1_blk.count +logger.info("metal1_blk has #{count} polygons") +polygons_count += count + +via1 = get_polygons(35, 0) +count = via1.count +logger.info("via1 has #{count} polygons") +polygons_count += count + +metal2_drawn = get_polygons(36, 0) +count = metal2_drawn.count +logger.info("metal2_drawn has #{count} polygons") +polygons_count += count + +metal2_dummy = get_polygons(36, 4) +count = metal2_dummy.count +logger.info("metal2_dummy has #{count} polygons") +polygons_count += count + +metal2 = metal2_drawn + metal2_dummy + +metal2_label = get_polygons(36, 10) +count = metal2_label.count +logger.info("metal2_label has #{count} polygons") +polygons_count += count + +metal2_slot = get_polygons(36, 3) +count = metal2_slot.count +logger.info("metal2_slot has #{count} polygons") +polygons_count += count + +metal2_blk = get_polygons(36, 5) +count = metal2_blk.count +logger.info("metal2_blk has #{count} polygons") +polygons_count += count + +if METAL_LEVEL == '2LM' + top_via = via1 topmin1_via = contact top_metal = metal2 topmin1_metal = metal1 - + else - metal2_drawn = get_polygons(36 , 0 ) - count = metal2_drawn.count() - logger.info("metal2_drawn has %d polygons" % [count]) - polygons_count += count - - metal2_dummy = get_polygons(36 , 4 ) - count = metal2_dummy.count() - logger.info("metal2_dummy has %d polygons" % [count]) - polygons_count += count - - metal2 = metal2_drawn + metal2_dummy - - metal2_label = get_polygons(36 , 10) - count = metal2_label.count() - logger.info("metal2_label has %d polygons" % [count]) - polygons_count += count - - metal2_slot = get_polygons(36 , 3 ) - count = metal2_slot.count() - logger.info("metal2_slot has %d polygons" % [count]) - polygons_count += count - - metal2_blk = get_polygons(36 , 5 ) - count = metal2_blk.count() - logger.info("metal2_blk has %d polygons" % [count]) - polygons_count += count - - via2 = get_polygons(38 , 0 ) - count = via2.count() - logger.info("via2 has %d polygons" % [count]) - polygons_count += count - - if METAL_LEVEL == "3LM" - metal3_drawn = get_polygons(42 , 0 ) - count = metal3_drawn.count() - logger.info("metal3_drawn has %d polygons" % [count]) - polygons_count += count - - metal3_dummy = get_polygons(42 , 4 ) - count = metal3_dummy.count() - logger.info("metal3_dummy has %d polygons" % [count]) - polygons_count += count - - metal3 = metal3_drawn + metal3_dummy - - metal3_label = get_polygons(42 , 10) - count = metal3_label.count() - logger.info("metal3_label has %d polygons" % [count]) - polygons_count += count - - metal3_slot = get_polygons(42 , 3 ) - count = metal3_slot.count() - logger.info("metal3_slot has %d polygons" % [count]) - polygons_count += count - - metal3_blk = get_polygons(42 , 5 ) - count = metal3_blk.count() - logger.info("metal3_blk has %d polygons" % [count]) - polygons_count += count - + + via2 = get_polygons(38, 0) + count = via2.count + logger.info("via2 has #{count} polygons") + polygons_count += count + + metal3_drawn = get_polygons(42, 0) + count = metal3_drawn.count + logger.info("metal3_drawn has #{count} polygons") + polygons_count += count + + metal3_dummy = get_polygons(42, 4) + count = metal3_dummy.count + logger.info("metal3_dummy has #{count} polygons") + polygons_count += count + + metal3 = metal3_drawn + metal3_dummy + + metal3_label = get_polygons(42, 10) + count = metal3_label.count + logger.info("metal3_label has #{count} polygons") + polygons_count += count + + metal3_slot = get_polygons(42, 3) + count = metal3_slot.count + logger.info("metal3_slot has #{count} polygons") + polygons_count += count + + metal3_blk = get_polygons(42, 5) + count = metal3_blk.count + logger.info("metal3_blk has #{count} polygons") + polygons_count += count + + if METAL_LEVEL == '3LM' + top_via = via2 topmin1_via = via1 top_metal = metal3 topmin1_metal = metal2 else - metal3_drawn = get_polygons(42 , 0 ) - count = metal3_drawn.count() - logger.info("metal3_drawn has %d polygons" % [count]) - polygons_count += count - - metal3_dummy = get_polygons(42 , 4 ) - count = metal3_dummy.count() - logger.info("metal3_dummy has %d polygons" % [count]) - polygons_count += count - - metal3 = metal3_drawn + metal3_dummy - - metal3_label = get_polygons(42 , 10) - count = metal3_label.count() - logger.info("metal3_label has %d polygons" % [count]) - polygons_count += count - - metal3_slot = get_polygons(42 , 3 ) - count = metal3_slot.count() - logger.info("metal3_slot has %d polygons" % [count]) - polygons_count += count - - metal3_blk = get_polygons(42 , 5 ) - count = metal3_blk.count() - logger.info("metal3_blk has %d polygons" % [count]) - polygons_count += count - - via3 = get_polygons(40 , 0 ) - - if METAL_LEVEL == "4LM" - metal4_drawn = get_polygons(46 , 0 ) - count = metal4_drawn.count() - logger.info("metal4_drawn has %d polygons" % [count]) - polygons_count += count - - metal4_dummy = get_polygons(46 , 4 ) - count = metal4_dummy.count() - logger.info("metal4_dummy has %d polygons" % [count]) - polygons_count += count - - metal4 = metal4_drawn + metal4_dummy - - metal4_label = get_polygons(46 , 10) - count = metal4_label.count() - logger.info("metal4_label has %d polygons" % [count]) - polygons_count += count - - metal4_slot = get_polygons(46 , 3 ) - count = metal4_slot.count() - logger.info("metal4_slot has %d polygons" % [count]) - polygons_count += count - - metal4_blk = get_polygons(46 , 5 ) - count = metal4_blk.count() - logger.info("metal4_blk has %d polygons" % [count]) - polygons_count += count - + + via3 = get_polygons(40, 0) + count = via3.count + logger.info("via3 has #{count} polygons") + polygons_count += count + + metal4_drawn = get_polygons(46, 0) + count = metal4_drawn.count + logger.info("metal4_drawn has #{count} polygons") + polygons_count += count + + metal4_dummy = get_polygons(46, 4) + count = metal4_dummy.count + logger.info("metal4_dummy has #{count} polygons") + polygons_count += count + + metal4 = metal4_drawn + metal4_dummy + + metal4_label = get_polygons(46, 10) + count = metal4_label.count + logger.info("metal4_label has #{count} polygons") + polygons_count += count + + metal4_slot = get_polygons(46, 3) + count = metal4_slot.count + logger.info("metal4_slot has #{count} polygons") + polygons_count += count + + metal4_blk = get_polygons(46, 5) + count = metal4_blk.count + logger.info("metal4_blk has #{count} polygons") + polygons_count += count + + if METAL_LEVEL == '4LM' + top_via = via3 topmin1_via = via2 top_metal = metal4 topmin1_metal = metal3 else - metal4_drawn = get_polygons(46 , 0 ) - count = metal4_drawn.count() - logger.info("metal4_drawn has %d polygons" % [count]) - polygons_count += count - - metal4_dummy = get_polygons(46 , 4 ) - count = metal4_dummy.count() - logger.info("metal4_dummy has %d polygons" % [count]) - polygons_count += count - - metal4 = metal4_drawn + metal4_dummy - - metal4_label = get_polygons(46 , 10) - count = metal4_label.count() - logger.info("metal4_label has %d polygons" % [count]) - polygons_count += count - - metal4_slot = get_polygons(46 , 3 ) - count = metal4_slot.count() - logger.info("metal4_slot has %d polygons" % [count]) - polygons_count += count - - metal4_blk = get_polygons(46 , 5 ) - count = metal4_blk.count() - logger.info("metal4_blk has %d polygons" % [count]) - polygons_count += count - - via4 = get_polygons(41 , 0 ) - count = via4.count() - logger.info("via4 has %d polygons" % [count]) - polygons_count += count - - if METAL_LEVEL == "5LM" - metal5_drawn = get_polygons(81 , 0 ) - count = metal5_drawn.count() - logger.info("metal5_drawn has %d polygons" % [count]) - polygons_count += count - - metal5_dummy = get_polygons(81 , 4 ) - count = metal5_dummy.count() - logger.info("metal5_dummy has %d polygons" % [count]) - polygons_count += count - - metal5 = metal5_drawn + metal5_dummy - - metal5_label = get_polygons(81 , 10) - count = metal5_label.count() - logger.info("metal5_label has %d polygons" % [count]) - polygons_count += count - - metal5_slot = get_polygons(81 , 3 ) - count = metal5_slot.count() - logger.info("metal5_slot has %d polygons" % [count]) - polygons_count += count - - metal5_blk = get_polygons(81 , 5 ) - count = metal5_blk.count() - logger.info("metal5_blk has %d polygons" % [count]) - polygons_count += count + + via4 = get_polygons(41, 0) + count = via4.count + logger.info("via4 has #{count} polygons") + polygons_count += count + + case METAL_LEVEL + when '5LM' + metal5_drawn = get_polygons(81, 0) + count = metal5_drawn.count + logger.info("metal5_drawn has #{count} polygons") + polygons_count += count + + metal5_dummy = get_polygons(81, 4) + count = metal5_dummy.count + logger.info("metal5_dummy has #{count} polygons") + polygons_count += count + + metal5 = metal5_drawn + metal5_dummy + + metal5_label = get_polygons(81, 10) + count = metal5_label.count + logger.info("metal5_label has #{count} polygons") + polygons_count += count + + metal5_slot = get_polygons(81, 3) + count = metal5_slot.count + logger.info("metal5_slot has #{count} polygons") + polygons_count += count + + metal5_blk = get_polygons(81, 5) + count = metal5_blk.count + logger.info("metal5_blk has #{count} polygons") + polygons_count += count top_via = via4 topmin1_via = via3 top_metal = metal5 topmin1_metal = metal4 - elsif METAL_LEVEL == "6LM" - metal5_drawn = get_polygons(81 , 0 ) - count = metal5_drawn.count() - logger.info("metal5_drawn has %d polygons" % [count]) - polygons_count += count + when '6LM' + metal5_drawn = get_polygons(81, 0) + count = metal5_drawn.count + logger.info("metal5_drawn has #{count} polygons") + polygons_count += count - metal5_dummy = get_polygons(81 , 4 ) - count = metal5_dummy.count() - logger.info("metal5_dummy has %d polygons" % [count]) - polygons_count += count + metal5_dummy = get_polygons(81, 4) + count = metal5_dummy.count + logger.info("metal5_dummy has #{count} polygons") + polygons_count += count metal5 = metal5_drawn + metal5_dummy - metal5_label = get_polygons(81 , 10) - count = metal5_label.count() - logger.info("metal5_label has %d polygons" % [count]) - polygons_count += count - - metal5_slot = get_polygons(81 , 3 ) - count = metal5_slot.count() - logger.info("metal5_slot has %d polygons" % [count]) - polygons_count += count + metal5_label = get_polygons(81, 10) + count = metal5_label.count + logger.info("metal5_label has #{count} polygons") + polygons_count += count - metal5_blk = get_polygons(81 , 5 ) - count = metal5_blk.count() - logger.info("metal5_blk has %d polygons" % [count]) - polygons_count += count + metal5_slot = get_polygons(81, 3) + count = metal5_slot.count + logger.info("metal5_slot has #{count} polygons") + polygons_count += count - via5 = get_polygons(82 , 0 ) - count = via5.count() - logger.info("via5 has %d polygons" % [count]) - polygons_count += count + metal5_blk = get_polygons(81, 5) + count = metal5_blk.count + logger.info("metal5_blk has #{count} polygons") + polygons_count += count + via5 = get_polygons(82, 0) + count = via5.count + logger.info("via5 has #{count} polygons") + polygons_count += count - metaltop_drawn = get_polygons(53 , 0 ) - count = metaltop_drawn.count() - logger.info("metaltop_drawn has %d polygons" % [count]) - polygons_count += count + metaltop_drawn = get_polygons(53, 0) + count = metaltop_drawn.count + logger.info("metaltop_drawn has #{count} polygons") + polygons_count += count - metaltop_dummy = get_polygons(53 , 4 ) - count = metaltop_dummy.count() - logger.info("metaltop_dummy has %d polygons" % [count]) - polygons_count += count + metaltop_dummy = get_polygons(53, 4) + count = metaltop_dummy.count + logger.info("metaltop_dummy has #{count} polygons") + polygons_count += count metaltop = metaltop_drawn + metaltop_dummy - metaltop_label = get_polygons(53 , 10) - count = metaltop_label.count() - logger.info("metaltop_label has %d polygons" % [count]) - polygons_count += count + metaltop_label = get_polygons(53, 10) + count = metaltop_label.count + logger.info("metaltop_label has #{count} polygons") + polygons_count += count - metaltop_slot = get_polygons(53 , 3 ) - count = metaltop_slot.count() - logger.info("metaltop_slot has %d polygons" % [count]) - polygons_count += count + metaltop_slot = get_polygons(53, 3) + count = metaltop_slot.count + logger.info("metaltop_slot has #{count} polygons") + polygons_count += count - metalt_blk = get_polygons(53 , 5 ) - count = metalt_blk.count() - logger.info("metalt_blk has %d polygons" % [count]) - polygons_count += count + metalt_blk = get_polygons(53, 5) + count = metalt_blk.count + logger.info("metalt_blk has #{count} polygons") + polygons_count += count top_via = via5 topmin1_via = via4 top_metal = metaltop topmin1_metal = metal5 else - logger.error("Unknown metal stack %s" % [METAL_LEVEL]) + logger.error("Unknown metal stack #{METAL_LEVEL}") raise end end end end -pad = get_polygons(37 , 0 ) -count = pad.count() -logger.info("pad has %d polygons" % [count]) -polygons_count += count - -ubmpperi = get_polygons(183, 0 ) -count = ubmpperi.count() -logger.info("ubmpperi has %d polygons" % [count]) -polygons_count += count - -ubmparray = get_polygons(184, 0 ) -count = ubmparray.count() -logger.info("ubmparray has %d polygons" % [count]) -polygons_count += count - -ubmeplate = get_polygons(185, 0 ) -count = ubmeplate.count() -logger.info("ubmeplate has %d polygons" % [count]) -polygons_count += count - -metal1_res = get_polygons(110, 11) -count = metal1_res.count() -logger.info("metal1_res has %d polygons" % [count]) -polygons_count += count - -metal2_res = get_polygons(110, 12) -count = metal2_res.count() -logger.info("metal2_res has %d polygons" % [count]) -polygons_count += count - -metal3_res = get_polygons(110, 13) -count = metal3_res.count() -logger.info("metal3_res has %d polygons" % [count]) -polygons_count += count - -metal4_res = get_polygons(110, 14) -count = metal4_res.count() -logger.info("metal4_res has %d polygons" % [count]) -polygons_count += count - -metal5_res = get_polygons(110, 15) -count = metal5_res.count() -logger.info("metal5_res has %d polygons" % [count]) -polygons_count += count - -metal6_res = get_polygons(110, 16) -count = metal6_res.count() -logger.info("metal6_res has %d polygons" % [count]) -polygons_count += count - -pr_bndry = get_polygons(0 , 0 ) -count = pr_bndry.count() -logger.info("pr_bndry has %d polygons" % [count]) -polygons_count += count - -border = get_polygons(63 , 0 ) -count = border.count() -logger.info("border has %d polygons" % [count]) -polygons_count += count +pad = get_polygons(37, 0) +count = pad.count +logger.info("pad has #{count} polygons") +polygons_count += count + +ubmpperi = get_polygons(183, 0) +count = ubmpperi.count +logger.info("ubmpperi has #{count} polygons") +polygons_count += count + +ubmparray = get_polygons(184, 0) +count = ubmparray.count +logger.info("ubmparray has #{count} polygons") +polygons_count += count + +ubmeplate = get_polygons(185, 0) +count = ubmeplate.count +logger.info("ubmeplate has #{count} polygons") +polygons_count += count + +metal1_res = get_polygons(110, 11) +count = metal1_res.count +logger.info("metal1_res has #{count} polygons") +polygons_count += count + +metal2_res = get_polygons(110, 12) +count = metal2_res.count +logger.info("metal2_res has #{count} polygons") +polygons_count += count + +metal3_res = get_polygons(110, 13) +count = metal3_res.count +logger.info("metal3_res has #{count} polygons") +polygons_count += count + +metal4_res = get_polygons(110, 14) +count = metal4_res.count +logger.info("metal4_res has #{count} polygons") +polygons_count += count + +metal5_res = get_polygons(110, 15) +count = metal5_res.count +logger.info("metal5_res has #{count} polygons") +polygons_count += count + +metal6_res = get_polygons(110, 16) +count = metal6_res.count +logger.info("metal6_res has #{count} polygons") +polygons_count += count + +pr_bndry = get_polygons(0, 0) +count = pr_bndry.count +logger.info("pr_bndry has #{count} polygons") +polygons_count += count + +border = get_polygons(63, 0) +count = border.count +logger.info("border has #{count} polygons") +polygons_count += count logger.info("Total no. of polygons in the design is #{polygons_count}") -logger.info("Starting deriving base layers.") +logger.info('Starting deriving base layers.') #===================================================== #------------- BASE LAYERS DERIVATIONS --------------- @@ -957,35 +865,35 @@ nwell_n_dn = nwell.not_interacting(dnwell) if CONNECTIVITY_RULES - logger.info("Construct connectivity for the design.") + logger.info('Construct connectivity for the design.') - connect(dnwell, ncomp) + connect(dnwell, ncomp) connect(ncomp, contact) connect(pcomp, contact) - connect(lvpwell_out, pcomp) + connect(lvpwell_out, pcomp) connect(lvpwell_dn, pcomp) - connect(nwell, ncomp) - connect(natcomp, contact) - connect(mvsd, ncomp) - connect(mvpsd, pcomp) - connect(contact, metal1) + connect(nwell, ncomp) + connect(natcomp, contact) + connect(mvsd, ncomp) + connect(mvpsd, pcomp) + connect(contact, metal1) connect(metal1, via1) connect(via1, metal2) - if METAL_LEVEL != "2LM" + if METAL_LEVEL != '2LM' connect(metal2, via2) connect(via2, metal3) - if METAL_LEVEL != "3LM" + if METAL_LEVEL != '3LM' connect(metal3, via3) connect(via3, metal4) - - if METAL_LEVEL != "4LM" + + if METAL_LEVEL != '4LM' connect(metal4, via4) connect(via4, metal5) - if METAL_LEVEL != "5LM" + if METAL_LEVEL != '5LM' connect(metal5, via5) connect(via5, metaltop) end @@ -993,21 +901,20 @@ if CONNECTIVITY_RULES end end -end #CONNECTIVITY_RULES +end #================================================ #------------ PRE-DEFINED FUNCTIONS ------------- #================================================ -def conn_space(layer,conn_val,not_conn_val, mode) - if conn_val > not_conn_val - raise "ERROR : Wrong connectivity implementation" - end +def conn_space(layer, conn_val, not_conn_val, mode) + raise 'ERROR : Wrong connectivity implementation' if conn_val > not_conn_val + connected_output = layer.space(conn_val.um, mode).polygons(0.001) unconnected_errors_unfiltered = layer.space(not_conn_val.um, mode) singularity_errors = layer.space(0.001.um) # Filter out the errors arising from the same net - unconnected_errors = DRC::DRCLayer::new(self, RBA::EdgePairs::new) + unconnected_errors = DRC::DRCLayer.new(self, RBA::EdgePairs.new) unconnected_errors_unfiltered.data.each do |ep| net1 = l2n_data.probe_net(layer.data, ep.first.p1) net2 = l2n_data.probe_net(layer.data, ep.second.p1) @@ -1019,17 +926,16 @@ def conn_space(layer,conn_val,not_conn_val, mode) end end unconnected_output = unconnected_errors.polygons.or(singularity_errors.polygons(0.001)) - return connected_output, unconnected_output + [connected_output, unconnected_output] end -def conn_separation(layer1, layer2, conn_val,not_conn_val, mode) - if conn_val > not_conn_val - raise "ERROR : Wrong connectivity implementation" - end +def conn_separation(layer1, layer2, conn_val, not_conn_val, mode) + raise 'ERROR : Wrong connectivity implementation' if conn_val > not_conn_val + connected_output = layer1.separation(layer2, conn_val.um, mode).polygons(0.001) unconnected_errors_unfiltered = layer1.separation(layer2, not_conn_val.um, mode) # Filter out the errors arising from the same net - unconnected_errors = DRC::DRCLayer::new(self, RBA::EdgePairs::new) + unconnected_errors = DRC::DRCLayer.new(self, RBA::EdgePairs.new) unconnected_errors_unfiltered.data.each do |ep| net1 = l2n_data.probe_net(layer1.data, ep.first.p1) net2 = l2n_data.probe_net(layer2.data, ep.second.p1) @@ -1041,30 +947,24 @@ def conn_separation(layer1, layer2, conn_val,not_conn_val, mode) end end unconnected_output = unconnected_errors.polygons(0.001) - return connected_output, unconnected_output + [connected_output, unconnected_output] end # === IMPLICIT EXTRACTION === if CONNECTIVITY_RULES - logger.info("Connectivity rules enabled, Netlist object will be generated.") + logger.info('Connectivity rules enabled, Netlist object will be generated.') netlist -end #CONNECTIVITY_RULES +end # === LAYOUT EXTENT === CHIP = extent.sized(0.0) -logger.info("Total area of the design is #{CHIP.area()} um^2.") +logger.info("Total area of the design is #{CHIP.area} um^2.") #================================================ #----------------- MAIN RUNSET ------------------ #================================================ -logger.info("Starting GF180MCU DRC rules.") -if FEOL - logger.info("Running all FEOL rules") -end #FEOL - -if BEOL - logger.info("Running all BEOL rules") -end #BEOL - +logger.info('Starting GF180MCU DRC rules.') +logger.info('Running all FEOL rules') if FEOL +logger.info('Running all BEOL rules') if BEOL diff --git a/klayout/drc/rule_decks/mcell.drc b/klayout/drc/rule_decks/mcell.drc deleted file mode 100644 index 70a0c585..00000000 --- a/klayout/drc/rule_decks/mcell.drc +++ /dev/null @@ -1,47 +0,0 @@ -################################################################################################ -# 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 - #================================================ - #---------------------MCELL---------------------- - #================================================ - - # Rule MC.1: min. mcell width is 0.4µm - logger.info("Executing rule MC.1") - mc1_l1 = mcell_feol_mk.width(0.4.um, euclidian).polygons(0.001) - mc1_l1.output("MC.1", "MC.1 : min. mcell width : 0.4µm") - mc1_l1.forget - - # Rule MC.2: min. mcell spacing is 0.4µm - logger.info("Executing rule MC.2") - mc2_l1 = mcell_feol_mk.space(0.4.um, euclidian).polygons(0.001) - mc2_l1.output("MC.2", "MC.2 : min. mcell spacing : 0.4µm") - mc2_l1.forget - - # Rule MC.3: Minimum Mcell area is 0.35µm² - logger.info("Executing rule MC.3") - mc3_l1 = mcell_feol_mk.with_area(nil, 0.35.um) - mc3_l1.output("MC.3", "MC.3 : Minimum Mcell area : 0.35µm²") - mc3_l1.forget - - # Rule MC.4: Minimum area enclosed by Mcell is 0.35µm² - logger.info("Executing rule MC.4") - mc4_l1 = mcell_feol_mk.holes.with_area(nil, 0.35.um) - mc4_l1.output("MC.4", "MC.4 : Minimum area enclosed by Mcell : 0.35µm²") - mc4_l1.forget -end #FEOL - - diff --git a/klayout/drc/rule_decks/otp_mk.drc b/klayout/drc/rule_decks/otp_mk.drc deleted file mode 100644 index ce62944c..00000000 --- a/klayout/drc/rule_decks/otp_mk.drc +++ /dev/null @@ -1,143 +0,0 @@ -################################################################################################ -# 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 - #================================================ - #---------------------OTP_MK--------------------- - #================================================ - - logger.info("Starting OTP_MK derivations") - - comp_otp = comp.and(otp_mk) - poly_otp = poly2.and(otp_mk) - sab_otp = sab.and(otp_mk) - - # Rule O.DF.3a: Min. COMP Space. P-substrate tap (PCOMP outside NWELL) can be butted for different voltage devices as the potential is same. is 0.24µm - logger.info("Executing rule O.DF.3a") - odf3a_l1 = comp_otp.space(0.24.um, euclidian) - odf3a_l1.output("O.DF.3a", "O.DF.3a : Min. COMP Space. P-substrate tap (PCOMP outside NWELL) can be butted for different voltage devices as the potential is same. : 0.24µm") - odf3a_l1.forget - - # Rule O.DF.6: Min. COMP extend beyond poly2 (it also means source/drain overhang). is 0.22µm - logger.info("Executing rule O.DF.6") - odf6_l1 = poly2.and(otp_mk).enclosed(comp_otp, 0.22.um, projection) - odf6_l1.output("O.DF.6", "O.DF.6 : Min. COMP extend beyond poly2 (it also means source/drain overhang). : 0.22µm") - odf6_l1.forget - - # Rule O.DF.9: Min. COMP area (um2). is 0.1444µm² - logger.info("Executing rule O.DF.9") - odf9_l1 = comp_otp.with_area(nil, 0.1444.um) - odf9_l1.output("O.DF.9", "O.DF.9 : Min. COMP area (um2). : 0.1444µm²") - odf9_l1.forget - - # Rule O.PL.2: Min. poly2 width. is 0.22µm - logger.info("Executing rule O.PL.2") - opl2_l1 = poly_otp.edges.and(tgate.edges).width(0.22.um, euclidian) - opl2_l1.output("O.PL.2", "O.PL.2 : Min. poly2 width. : 0.22µm") - opl2_l1.forget - - # Rule O.PL.3a: Min. poly2 Space on COMP. is 0.18µm - logger.info("Executing rule O.PL.3a") - opl3a_l1 = (tgate).or(poly2.not(comp)).and(otp_mk).space(0.18.um, euclidian) - opl3a_l1.output("O.PL.3a", "O.PL.3a : Min. poly2 Space on COMP. : 0.18µm") - opl3a_l1.forget - - # Rule O.PL.4: Min. extension beyond COMP to form Poly2 end cap. is 0.14µm - logger.info("Executing rule O.PL.4") - opl4_l1 = comp_otp.enclosed(poly_otp, 0.14.um, euclidian) - opl4_l1.output("O.PL.4", "O.PL.4 : Min. extension beyond COMP to form Poly2 end cap. : 0.14µm") - opl4_l1.forget - - # rule O.PL.5a is not a DRC check - ## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_10.html - - # rule O.PL.5b is not a DRC check - ## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_10.html - - # Rule O.SB.2: Min. salicide Block Space. is 0.28µm - logger.info("Executing rule O.SB.2") - osb2_l1 = sab_otp.space(0.28.um, euclidian) - osb2_l1.output("O.SB.2", "O.SB.2 : Min. salicide Block Space. : 0.28µm") - osb2_l1.forget - - # Rule O.SB.3: Min. space from salicide block to unrelated COMP. is 0.09µm - logger.info("Executing rule O.SB.3") - osb3_l1 = sab.outside(comp).and(otp_mk).separation(comp.outside(sab), 0.09.um, euclidian).polygons(0.001) - osb3_l1.output("O.SB.3", "O.SB.3 : Min. space from salicide block to unrelated COMP. : 0.09µm") - osb3_l1.forget - - # Rule O.SB.4: Min. space from salicide block to contact. - logger.info("Executing rule O.SB.4") - osb4_l1 = sab_otp.separation(contact, 0.03.um, euclidian).polygons(0.001).or(sab_otp.and(contact)) - osb4_l1.output("O.SB.4", "O.SB.4 : Min. space from salicide block to contact.") - osb4_l1.forget - - # rule O.SB.5a is not a DRC check - ## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_10.html - - # Rule O.SB.5b_LV: Min. space from salicide block to unrelated Poly2 on COMP. is 0.1µm - logger.info("Executing rule O.SB.5b_LV") - osb5b_l1 = sab_otp.outside(tgate).separation(tgate.outside(sab), 0.1.um, euclidian).polygons(0.001).not_interacting(v5_xtor).not_interacting(dualgate) - osb5b_l1.output("O.SB.5b_LV", "O.SB.5b_LV : Min. space from salicide block to unrelated Poly2 on COMP. : 0.1µm") - osb5b_l1.forget - - # rule O.SB.5b_MV is not a DRC check - ## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_10.html - - # Rule O.SB.9: Min. salicide block extension beyond unsalicided Poly2. is 0.1µm - logger.info("Executing rule O.SB.9") - osb9_l1 = poly_otp.enclosed(sab_otp, 0.1.um, euclidian) - osb9_l1.output("O.SB.9", "O.SB.9 : Min. salicide block extension beyond unsalicided Poly2. : 0.1µm") - osb9_l1.forget - - # Rule O.SB.11: Min. salicide block overlap with COMP. is 0.04µm - logger.info("Executing rule O.SB.11") - osb11_l1 = sab_otp.overlap(comp, 0.04.um, euclidian) - osb11_l1.output("O.SB.11", "O.SB.11 : Min. salicide block overlap with COMP. : 0.04µm") - osb11_l1.forget - - # rule O.SB.12 is not a DRC check - ## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_10.html - - # Rule O.SB.13_LV: Min. area of silicide block (um2). is 1.488µm² - logger.info("Executing rule O.SB.13_LV") - osb13_l1 = sab_otp.with_area(nil, 1.488.um).not_interacting(v5_xtor).not_interacting(dualgate) - osb13_l1.output("O.SB.13_LV", "O.SB.13_LV : Min. area of silicide block (um2). : 1.488µm²") - osb13_l1.forget - - # Rule O.SB.13_MV: Min. area of silicide block (um2). is 2µm² - logger.info("Executing rule O.SB.13_MV") - osb13_l1 = sab_otp.and(v5_xtor).with_area(nil, 2.um) - osb13_l1.output("O.SB.13_MV", "O.SB.13_MV : Min. area of silicide block (um2). : 2µm²") - osb13_l1.forget - - # rule O.SB.15b is not a DRC check - ## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_10.html - - # Rule O.CO.7: Min. space from COMP contact to Poly2 on COMP. is 0.13µm - logger.info("Executing rule O.CO.7") - oco7_l1 = contact.not_outside(comp_otp).separation(tgate.and(otp_mk), 0.13.um, euclidian) - oco7_l1.output("O.CO.7", "O.CO.7 : Min. space from COMP contact to Poly2 on COMP. : 0.13µm") - oco7_l1.forget - - # Rule O.PL.ORT: Orientation-restricted gates must have the gate width aligned along the X-axis (poly line running horizontally) in reference to wafer notch down. is 0µm - logger.info("Executing rule O.PL.ORT") - oplort_l1 = comp_otp.not(poly_otp).edges.and(tgate.edges).without_angle(0.um) - oplort_l1.output("O.PL.ORT", "O.PL.ORT : Orientation-restricted gates must have the gate width aligned along the X-axis (poly line running horizontally) in reference to wafer notch down. : 0µm") - oplort_l1.forget - -end #FEOL - diff --git a/klayout/drc/rule_decks/pres.drc b/klayout/drc/rule_decks/pres.drc deleted file mode 100644 index c6e64c72..00000000 --- a/klayout/drc/rule_decks/pres.drc +++ /dev/null @@ -1,99 +0,0 @@ -################################################################################################ -# 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 - #================================================ - #----------------P+ POLY RESISTOR---------------- - #================================================ - - logger.info("Starting PRES derivations") - pres_poly = poly2.and(pplus).interacting(sab).interacting(res_mk).not_interacting(resistor) - - # Rule PRES.1: Minimum width of Poly2 resistor. is 0.8µm - logger.info("Executing rule PRES.1") - pres1_l1 = pres_poly.width(0.8.um, euclidian) - pres1_l1.output("PRES.1", "PRES.1 : Minimum width of Poly2 resistor. : 0.8µm") - pres1_l1.forget - - # Rule PRES.2: Minimum space between Poly2 resistors. is 0.4µm - logger.info("Executing rule PRES.2") - pres2_l1 = pres_poly.isolated(0.4.um, euclidian) - pres2_l1.output("PRES.2", "PRES.2 : Minimum space between Poly2 resistors. : 0.4µm") - pres2_l1.forget - - # Rule PRES.3: Minimum space from Poly2 resistor to COMP. - logger.info("Executing rule PRES.3") - pres3_l1 = pres_poly.separation(comp, 0.6.um, euclidian).polygons(0.001) - pres3_l2 = comp.not_outside(pres_poly) - pres3_l = pres3_l1.or(pres3_l2) - pres3_l.output("PRES.3", "PRES.3 : Minimum space from Poly2 resistor to COMP.") - pres3_l.forget - pres3_l1.forget - pres3_l2.forget - - # Rule PRES.4: Minimum space from Poly2 resistor to unrelated Poly2. is 0.6µm - logger.info("Executing rule PRES.4") - pres4_l1 = pres_poly.separation(poly2.not_interacting(sab), 0.6.um, euclidian) - pres4_l1.output("PRES.4", "PRES.4 : Minimum space from Poly2 resistor to unrelated Poly2. : 0.6µm") - pres4_l1.forget - - # Rule PRES.5: Minimum Plus implant overlap of Poly2 resistor. is 0.3µm - logger.info("Executing rule PRES.5") - pres5_l1 = pres_poly.enclosed(pplus, 0.3.um, euclidian).polygons(0.001) - pres5_l2 = pres_poly.not_outside(pplus).not(pplus) - pres5_l = pres5_l1.or(pres5_l2) - pres5_l.output("PRES.5", "PRES.5 : Minimum Plus implant overlap of Poly2 resistor. : 0.3µm") - pres5_l1.forget - pres5_l2.forget - pres5_l.forget - - # Rule PRES.6: Minimum salicide block overlap of Poly2 resistor in width direction. is 0.28µm - logger.info("Executing rule PRES.6") - pres6_l1 = pres_poly.enclosed(sab,0.28.um) - pres6_l1.output("PRES.6", "PRES.6 : Minimum salicide block overlap of Poly2 resistor in width direction. : 0.28µm") - pres6_l1.forget - - # Rule PRES.7: Space from salicide block to contact on Poly2 resistor. - logger.info("Executing rule PRES.7") - pres7_l1 = contact.and(pres_poly).separation(sab,0.22.um).polygons(0.001) - pres7_l2 = contact.and(pres_poly).interacting(sab) - pres7_l = pres7_l1.or(pres7_l2) - pres7_l.output("PRES.7", "PRES.7 : Space from salicide block to contact on Poly2 resistor.") - pres7_l1.forget - pres7_l2.forget - - # Rule PRES.8 is not a DRC check - ## Please refer to https://gf180mcu-pdk.readthedocs.io/en/latest/physical_verification/design_manual/drm_10_01.html#p-poly-resistor-pres - - # Rule PRES.9a: Pplus Poly2 resistor shall be covered by RES_MK marking. RES_MK length shall be coincide with resistor length (Defined by SAB length) and width covering the width of Poly2. - logger.info("Executing rule PRES.9a") - mk_pres9a = res_mk.edges.not(poly2.and(pplus).and(sab).edges).inside_part(poly2) - pres9a_l1 = res_mk.interacting(pres_poly).interacting(mk_pres9a) - pres9a_l1.output("PRES.9a", "PRES.9a : Pplus Poly2 resistor shall be covered by RES_MK marking. RES_MK length shall be coincide with resistor length (Defined by SAB length) and width covering the width of Poly2.") - pres9a_l1.forget - mk_pres9a.forget - - # Rule PRES.9b: If the size of single RES_MK mark layer is greater than 15000um2 and both side (X and Y) are greater than 80um. - ## then the minimum spacing to adjacent RES_MK layer. is 20µm - logger.info("Executing rule PRES.9b") - pres9b = res_mk.with_area(15000.001.um,nil).edges.with_length(80.001.um,nil) - pres9b_l1 = pres9b.separation(res_mk.edges, 20.um) - pres9b_l1.output("PRES.9b", "PRES.9b : If the size of single RES_MK mark layer is greater than 15000um2 and both side (X and Y) are greater than 80um. then the minimum spacing to adjacent RES_MK layer. : 20µm") - pres9b_l1.forget - pres9b.forget - pres_poly.forget - -end #PRES diff --git a/klayout/drc/rule_decks/tail.drc b/klayout/drc/rule_decks/tail.drc index b4ef0bca..a9a22a63 100644 --- a/klayout/drc/rule_decks/tail.drc +++ b/klayout/drc/rule_decks/tail.drc @@ -14,10 +14,6 @@ # limitations under the License. ################################################################################################ - - exec_end_time = Time.now run_time = exec_end_time - exec_start_time -logger.info("%s DRC Total Run time %f seconds" % [table_name, run_time]) - - +logger.info("#{$table_name} DRC Total Run time #{run_time} seconds") diff --git a/klayout/drc/testing/run_regression.py b/klayout/drc/testing/run_regression.py index a3ba601c..f8109fca 100644 --- a/klayout/drc/testing/run_regression.py +++ b/klayout/drc/testing/run_regression.py @@ -444,7 +444,7 @@ def parse_existing_rules(rule_deck_path, output_path, target_table=None): with open(runset, "r") as f: for line in f: if ".output" in line: - line_list = line.split('"') + line_list = line.split("'") rule_info = dict() rule_info["table_name"] = os.path.basename(runset).replace( ".drc", "" diff --git a/klayout/drc/testing/testcases/unit/drc_bjt.gds b/klayout/drc/testing/testcases/unit/drc_bjt.gds deleted file mode 100644 index 2c180521610316b3f366410728de13a997bbb45f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5114 zcmbW5TWnQT5Qe9xJ%`2?BMHzHkZyP&q6DhTJ;0rb9-e-_Ho(YiJuUDnjh)sI=>V@A^W+`GvX(N--##H4`ja} zKhjUeJMN5*cUGs4*Er`b9k0>y#+`}wL;uJF;e+uS*+<4{w7eKU>7Vn2>?7ke!Uy9t zT3&?TB&_emt3;!BE2sYD{8H}IXz|gz?>j!x=Zz=wt~ei@InVh8pMAy{OSA1 z`mU}=^g`CV#xl_hSs%QQ)>kB?PY3e&UG<)j+`q(Q`gi36GJito%?IT93*JZ8m;KW^ zLHAF`ySjgj7H^#pt;agIHR!q@x~BWbXz{j&7(MTsj;p$Vpo5>$;vH9`_1GWC1EIq{ zFj_oT&-v)nbl5l0gBFkLANvFI1Y+K>e~cE7nLpVdoF`>H!Sh9g)%ExwkXcFJ147TSYHq zojW^M^g`AL?<4j8!BL_YLSNXcdXV+O`wYF8em=f0Abc=hBm2lWjg}YVC;fAtkbPvFM)+WyM$3!vlk+Xt zBPuxQd~p6H=P!CEq{RzP-gkV^yZL;P;yfYiUE6D-7g{_aHAHI;D zU;Lna_vusV`BNX1Fa6{t9*v$U3QOwD=%B?^5}Gg83i#jlYj1PbD=E% zL`I7zPiNF`6Ma(7AGt5!o`!qF+#mVA|9VJ^54!(m=yC2N4}|{KA0aIsqnGoN^MtH- zovTDIw0Mj@bN)wZ|J?y2=0CIl_w@eJ&FpH?{*AbQAU^2+kgk`$anHcH&pOw+ETqK; z>1PG&SBcNZJyZDmP?xf7gmb&AiHx(88o$S#&h6#(E!%6ljCIZM-PfqTdv|F*o@cXO z$iDll_&FfzA#R-2746%5k*K7{xu1R@Dn0HTo~IuOSm@l(r}#Nw=|qhiOM0Sx7d)rF zm8;bk&+rwp-=Zhf7la?;#u#7!*6%V8e!nmCAkRDx%B1t}T#|VZ^7tigjF|`j=I81Q zBLBwakUX#Q{vNqr|52^4y2yF(m-G7beh|X9wn=?K_~HFMvhRv{>Z`hF->ZoxUq`NRcf zDyvp4Si02P(A4Zz)l_+WYvR4=RXHZ^)R+jgw?{(r5P zHq(5qH5IisZP~HK+qSjtm3kSJ{;A4qsC%Qn+1uXa?PzSSZ>ZZ||EeeDd4zm9N&nkZ zLOyHsyM}xh*vOv&_|EWIrG8g1T72WqNWH(ml!)_$(2cmOKA^>8^aFPeN}iDQ{+s-} QZe)G%Uh5CxJ5Ub&1LdCp;{X5v diff --git a/klayout/drc/testing/testcases/unit/drc_bjt.svg b/klayout/drc/testing/testcases/unit/drc_bjt.svg deleted file mode 100644 index e183e172..00000000 --- a/klayout/drc/testing/testcases/unit/drc_bjt.svg +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BJT.1 -BJT.2 -BJT.3 -BJT.1 -BJT.2 -BJT.3 -BJT.1 Min. DRC_BJT overlap of DNWELL for NPN BJT = 0 -BJT.2 Min. DRC_BJT overlap of PCOMP in Psub = 0 -BJT.3 Minimum space of DRC_BJT layer to unrelated COMP = 0.1 - - \ No newline at end of file diff --git a/klayout/drc/testing/testcases/unit/dummy_exclude.gds b/klayout/drc/testing/testcases/unit/dummy_exclude.gds deleted file mode 100644 index 0e3dd515ccb5788b979c4a5e7b975da51c14a411..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3448 zcmb`KT})h65Xa{(ySJN`8l;WLhvxVof!N>{LD7Vo!cw7>hHf;peUL2WqMMYv%7>vg zq-vn8#$tkrY0xINP22}VUu@Gpl0baXq$W1?!C3Uch-p$yiYZX`jx*=nvtM|(2D&f5 z&7Aw6nKS3yIp=~2KHov8FnpW-00W+ct?&fYW&Vet&)nD61hBmzuxs~+FSLJ~`1{51 zwP(Nl{P3$#5%AU(ndbg*$D!`d4hDcf2w-mY!C5dL@j(FUiVDz441&=-qqyg1;!j|_ z@-jMeKc=b2n`glP=vqHJ$PbQJNu zS7sl|oj;8A$b4aWQtDIG_OTvsJ;jxJ=JKTWqsV$So?p*8&Y$Wm^LHuzDZhF2-vJDB z{fJ`+Nxm&jZ6Efo-|FHaOdfa#iR?$|6}6q|86TfoQhl7+)r|P`wlukqt8q`gld#?M zgecFGku>EwBF8=T*!m5?^gZhT#Q7U^Zq%o#?bG)>_0B4Fti&`*{?>{3d;~yK+Y{4D z@Ako$WFMqmM19czKl-54_A40eufgV0vsSc3B7+b1mfK11-voGn7;01}6;;t{(GeYq z^$+(8KC8uG>|IM#4Zbag`>REx*jXP6h1L;e7L4&`2+Jt7q9bO@2w@o_J|NV^zzsGc z$Z|~d#`-OLFc!B(%yy%PY8pIa2QumvlDnPGklfi8kAv|=32ZNw_Yo1bd)?4l#)vl*zv@#>d;B~z+J=LPEPnGD60V_IW z4TzyPqqbTSS}t0oYO+|ih}#xD*K3I*QQM9Wi5^R2DXP?3Hc*)!IO{y8Fz-H?y`Q`L z++H5fyxZM84lr>M9p709&h*r;rzhz;$h+w}dRmr#ycl5W3iTr5rAEZFQ)z1Z)D`di z>uJg7uOl+=c2RGmvqe+e=dXL~Z#YWNWF6N}ll5xcTmO5X>gi0rlaoG0?&)e=={G^% zZ;C?G+!^X_=nl8gF5V1KRGj^d;oc&1-rChWqu{&TmzCkN+^H+_*0Q=V!My{Se(QVL ZM>MsajhUyur~c> - - - - - - - - - - - - - - - - - - - - - - - -DE.3 -DE.3 -DE.4 -DE.4 -DE.2 -DE.2 -2 ERRs -DE.3 (a) Maximum NDMY size (sq um) = 15000 -DE.2 Minimum DNDMY or PMNDMY size (x or y dimension in um) = 0.8 -NDMY and PMNDMY -DE.4 Minimum NDMY to NDMY space = 20 -DE.3 (b) If size greater than 15000um (sq) then one side cannot be greater than (um) = 80 -2 ERRs - - \ No newline at end of file diff --git a/klayout/drc/testing/testcases/unit/efuse.gds b/klayout/drc/testing/testcases/unit/efuse.gds deleted file mode 100644 index 9af4699e769749156d2d4d53596e8ea2f61e771b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256920 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 NzpDn;e_gPE{TGQA%2ogX diff --git a/klayout/drc/testing/testcases/unit/efuse.svg b/klayout/drc/testing/testcases/unit/efuse.svg deleted file mode 100644 index d63437b6..00000000 --- a/klayout/drc/testing/testcases/unit/efuse.svg +++ /dev/null @@ -1,3817 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -EF.04d -EF.04d -EF.04c -EF.04c -EF.22b -EF.22a -EF.22b -EF.22a -EF.22b -EF.22a -EF.04d -EF.04d -EF.04c -EF.04c -EF.10 -EF.10 -EF.10 -EF.10 -Space -Touch -Corner2Edge -Corner2Corner -45deg -Cor2Cor_90Deg -EF.20_SAB -Space -Corner2Edge -EF.10 -EF.10 -EF.10 -EF.10 -EF.10 -EF.10 -EF.10 -Corner2Corner -45deg -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.10 -EF.10 -EF.11 -EF.11 -EF.11 -EF.11 -45deg -Corner2Corner -Corner2Edge -Space -EF.11 -EF.11 -EF.11 -EF.11 -EF.11 -EF.11 -EF.11 -45deg -Corner2Corner -Corner2Edge -Space -EF.11 -EF.11 -EF.17 -EF.17 -EF.17 -EF.17 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -Space -Touch -Corner2Edge -Corner2Corner -EF.17 -EF.17 -EF.17 -EF.17 -EF.17 -EF.17 -EF.17 -45deg -Cor2Cor_90Deg -EF.20_Res -Space -Corner2Edge -Corner2Corner -45deg -EF.20 -EF.20 -EF.17 -EF.17 -EF.04b_Normal -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.04b -EF.04b -EF.04b -EF.04b -EF.04b -EF.04b -EF.20 -EF.20 -EF.20 -Space -Touch -Corner2Edge -Corner2Corner -45deg -Cor2Cor_90Deg -EF.20_Nplus -EF.01 -EF.01 -EF.01 -EF.01 -EF.01 -Space -Corner2Edge -Corner2Corner -45deg -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.01 -EF.01 -EF.01 -EF.01 -EF.01 -EF.01 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -Space -Touch -Corner2Edge -Corner2Corner -EF.01 -EF.01 -EF.01 -EF.01 -45deg -Cor2Cor_90Deg -EF.20_ESD -Space -Corner2Edge -Corner2Corner -45deg -EF.20 -EF.20 -EF.20 -EF.01 -EF.01 -EF.01 -EF.01 -EF.01 -EF.01 -EF.01 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -Space -EF.02 -EF.02 -Touch -Corner2Edge -Corner2Corner -45deg -Cor2Cor_90Deg -EF.20_COMP -Space -EF.02 -EF.02 -EF.02 -EF.02 -EF.02 -EF.02 -EF.02 -EF.02 -Corner2Edge -Corner2Corner -45deg -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -EF.02 -EF.02 -EF.20 -EF.20 -EF.20 -EF.20 -EF.20 -Space -Corner2Edge -EF.02 -EF.02 -EF.02 -EF.02 -EF.02 -EF.02 -EF.02 -EF.02 -Corner2Corner -45deg -EF.19 -EF.19 -EF.19 -EF.19 -EF.19 -EF.19_Metal2 -Space -Touch -Both -EF.03 -EF.03 -Both -Pfuse -EF.03 -EF.03 -Both -EF.03 -EF.03 -Both -Pfuse -EF.03 -EF.03 -EF.21 -EF.04a -EF.04a -Both -EF.21 -EF.21 -Both -EF.04a -EF.04a -EF.04a -EF.04a -EF.21 -EF.04a -EF.04a -Both -EF.21 -EF.21 -Both -EF.04a -EF.04a -EF.04a -EF.04a -Cut Corner Plufse -Additional Plfuse -Basic -EF.04b -EF.04b -Cut Corner Plufse -Additional Plfuse -Basic -EF.04b -EF.04b -EF.05 -EF.05 -EF.05 -EF.05 -EF.05 -Corner2Edge -Corner2Corner -45deg -EF.19 -EF.19 -EF.19 -EF.19 -EF.19 -EF.19 -Space -EF.05 -EF.05 -EF.05 -EF.05 -EF.05 -EF.05 -Corner2Edge -Corner2Corner -45deg -EF.19 -EF.19 -EF.19 -EF.19 -EF.19 -EF.19_Metal1 -Space -EF.05 -EF.05 -EF.05 -EF.05 -EF.05 -Touch -Corner2Edge -Corner2Corner -45deg -EF.19 -EF.19 -EF.19 -EF.19 -EF.19 -EF.19 -EF.05 -EF.05 -EF.05 -EF.05 -Space -Corner2Edge -Corner2Corner -45deg -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -EF.18_SAB -Larger -Basic -EF.06 -EF.06 -Larger -Basic -EF.06 -EF.06 -Larger -Basic -EF.07 -EF.07 -Larger -Basic -EF.07 -EF.07 -Larger -Basic -EF.08 -EF.08 -Larger -Basic -EF.08 -EF.08 -Larger -Basic -EF.09 -EF.09 -Larger -Basic -EF.09 -EF.09 -EF.12 -EF.12 -EF.12 -Using offset*2 -Cor2Cor_45Deg -Space -EF.12 -EF.12 -EF.12 -EF.12 -EF.12 -EF.12 -EF.12 -Singular -Using offset*2 -Cor2Cor_45Deg -Overlap -Touch -Space -EF.13 -EF.13 -EF.13 -Using offset*2 -Cor2Cor_45Deg -Space -EF.13 -EF.13 -EF.13 -EF.13 -EF.13 -EF.13 -EF.13 -Singular -Using offset*2 -Cor2Cor_45Deg -Overlap -Touch -Space -EF.14 -EF.14 -EF.14 -EF.14 -EF.14 -Space -Touch -Corner2Edge -Corner2Corner -45deg -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -EF.14 -EF.14 -EF.14 -EF.14 -EF.14 -EF.14 -EF.18 -Space -Corner2Edge -Corner2Corner -45deg -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -EF.15 -EF.15 -EF.15 -Using offset*2 -Cor2Cor_45Deg -Space -EF.15 -EF.15 -EF.15 -EF.15 -EF.15 -EF.15 -EF.15 -Singular -Using offset*2 -Cor2Cor_45Deg -Overlap -Touch -Space -Cathode contain more contact -Basic -Anode contain no contact -Anode contain less contact -Cathode contain no contact -Cathode contain less contact -EF.16a -EF.16a -Cathode contain more contact -Basic -Anode contain no contact -Anode contain less contact -Cathode contain no contact -Cathode contain less contact -EF.16a -EF.16a -EF.16a -Cathode contain more contact -Basic -Anode contain no contact -Anode contain less contact -Cathode contain no contact -Cathode contain less contact -EF.16b -EF.16b -Cathode contain more contact -Basic -Anode contain no contact -Anode contain less contact -Cathode contain no contact -Cathode contain less contact -EF.16b -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -45deg -Corner2Corner -Corner2Edge -Touch -Space -EF.18_COMP -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -45deg -Corner2Corner -Corner2Edge -Space -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -45deg -Corner2Corner -Corner2Edge -Touch -Space -EF.18_ESD -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -45deg -Corner2Corner -Corner2Edge -Space -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -45deg -Corner2Corner -Corner2Edge -Touch -Space -EF.18_Metal1 -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -45deg -Corner2Corner -Corner2Edge -Space -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -45deg -Corner2Corner -Corner2Edge -Touch -Space -EF.18_Metal2 -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -45deg -Corner2Corner -Corner2Edge -Space -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -45deg -Corner2Corner -Corner2Edge -Touch -Space -EF.18_Nplus -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -45deg -Corner2Corner -Corner2Edge -Space -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -EF.18 -45deg -Corner2Corner -Corner2Edge -Touch -Space -EF.18_Res - - \ No newline at end of file diff --git a/klayout/drc/testing/testcases/unit/hres.gds b/klayout/drc/testing/testcases/unit/hres.gds deleted file mode 100644 index 9418f5b5e9a30e7dd1699bfba0b248425975dda8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78832 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 Qf@*6Tt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -HRES.12a -HRES.12a -HRES.12a -HRES.12a -HRES.12a -HRES.12a -HRES.12a -HRES.12a -HRES.12a -HRES.12a -HRES.12a -HRES.12a -HRES.10 -HRES.10 -HRES.10 -HRES.10 -HRES.10 -HRES.12b -HRES.12b -HRES.1 -HRES.1 -HRES.1 -HRES.1 -HRES.1 -45deg -Corner2Corner -Corner2Edge -Space -HRES.1 -HRES.1 -HRES.1 -HRES.1 -HRES.1 -HRES.1 -HRES.1 -HRES.1 -Cor2Cor_90Deg -45deg -Corner2Corner -Corner2Edge -Singular -Space -HRES.2 -HRES.2 -HRES.2 -HRES.2 -HRES.2 -HRES.2 -HRES.2 -HRES.2 -HRES.2 -HRES.2 -Width_45deg -Corner_45Deg -Corner2Corner -Width -Default Pass. Minus 2xMinGrid to Fail -HRES.2 -Width_45deg -Corner_45Deg -Corner2Corner -Width -Default Pass. Minus 2xMinGrid to Fail -HRES.3 -HRES.3 -HRES.3 -HRES.3 -HRES.3 -HRES.3 -Notch -45deg -Corner2Corner -Corner2Edge -Space -HRES.3 -HRES.3 -HRES.3 -HRES.3 -HRES.3 -HRES.3 -HRES.3 -HRES.3 -HRES.3 -Cor2Cor_90Deg -Notch -45deg -Corner2Corner -Corner2Edge -Singular -Space -HRES.4 -Basic -Angle45 -HRES.4 -HRES.4 -HRES.4 -HRES.4 -Touch -Basic -Intersect -Angle45 -Singular -HRES.4 -HRES.4 -HRES.4 -HRES.4 -HRES.4 -HRES.5 -HRES.5 -HRES.5 -HRES.5 -HRES.5 -HRES.5 -HRES.5 -HRES.5 -HRES.5 -HRES.5 -HRES.5 -HRES.5 -45deg -Corner2Corner -Corner2Edge -Space -HRES.5 -Cor2Cor_90Deg -45deg -Corner2Corner -Corner2Edge -Singular -Space -HRES.6 -HRES.6 -HRES.6 -HRES.6 -HRES.6 -HRES.6 -HRES.6 -HRES.6 -HRES.6 -HRES.6 -HRES.6 -HRES.6 -45deg -Corner2Corner -Corner2Edge -Space -HRES.6 -Cor2Cor_90Deg -45deg -Corner2Corner -Corner2Edge -Singular -Space -HRES.7 -Basic -Angle45 -HRES.7 -HRES.7 -HRES.7 -HRES.7 -Touch -Basic -Intersect -Angle45 -Singular -HRES.7 -HRES.7 -HRES.7 -HRES.7 -HRES.7 -HRES.8 -HRES.8 -Space -HRES.8 -HRES.8 -HRES.8 -HRES.8 -Touch -Space -HRES.9 -Basic -HRES.9 -HRES.9 -HRES.9 -Touch -Basic -Intersect -Angle45 -Singular -Hole -HRES.9 -HRES.9 -HRES.9 -HRES.9 -HRES.9 -HRES.9 -HRES.10 -HRES.10 -HRES.10 -HRES.10 -HRES.10 -HRES.10 -HRES.10 -HRES.10 -HRES.10 -HRES.10 -HRES.10 - - \ No newline at end of file diff --git a/klayout/drc/testing/testcases/unit/lres.gds b/klayout/drc/testing/testcases/unit/lres.gds deleted file mode 100644 index c5885840fd8a770cbe24c7064b298802bab84240..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73290 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LRES.9a -LRES.9a -LRES.9b -LRES.9b -LRES.9a -LRES.9a -LRES.9b -LRES.9b -LRES.9b -LRES.1 -LRES.1 -LRES.9a -LRES.9a -LRES.9a -LRES.9a -LRES.9a -LRES.9a -LRES.9a -LRES.1 -LRES.1 -LRES.1 -LRES.1 -LRES.1 -LRES.9a -LRES.7 -LRES.7 -LRES.1 -LRES.7 -LRES.7 -LRES.7 -LRES.7 -LRES.7 -LRES.7 -LRES.7 -LRES.1 -LRES.1 -LRES.1 -LRES.1 -LRES.1 -LRES.7 -LRES.7 -LRES.6 -LRES.6 -LRES.6 -LRES.6 -LRES.6 -LRES.6 -FALSE -LRES.5 -LRES.5 -LRES.5 -LRES.5 -LRES.5 -LRES.5 -LRES.5 -LRES.5 -LRES.5 -LRES.5 -LRES.5 -LRES.5 -LRES.2 -LRES.2 -LRES.2 -LRES.2 -LRES.2 -LRES.2 -LRES.2 -LRES.2 -LRES.2 -LRES.2 -LRES.2 -LRES.3 -LRES.3 -LRES.5 -LRES.5 -LRES.4 -LRES.4 -LRES.4 -LRES.4 -LRES.4 -LRES.4 -LRES.4 -LRES.3 -LRES.3 -LRES.3 -LRES.3 -LRES.3 -LRES.4 -LRES.4 -LRES.4 -LRES.4 -LRES.3 -LRES.3 -LRES.3 -LRES.3 -LRES.3 -LRES.3 -LRES.3 -LRES.3 - - \ No newline at end of file diff --git a/klayout/drc/testing/testcases/unit/lvs_bjt.gds b/klayout/drc/testing/testcases/unit/lvs_bjt.gds deleted file mode 100644 index a817e5268b51b755165996b9e30a650b4ebd6296..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1950 zcmaKtTS!z<6o&sZI!D9N5=6@z2NQhAOd-hZ0-BNLXr>k_QW@xzWlSJSM312bmIR@N zgbs)zBzVCdB8mvjE@1W2L(o&wLlnIQoz>dwobAlWoP7CY?fw7za@PI_CVakD#KR5dJ0Vdb0HG0d?mV33~1{5T*y-| z>n$!v)~(s?tgoo+i_4yRYW^+rguHLMa9#95*1O}Ldb_ysNXdQ0?fe+``j7G}s+ ze0!7G7U9Q>WItR4H1)iN8Baf&SQbAa`_aU__zBsE7PpI^kp0~GasA|c<@bTvVX_rJ zEs@>NFGEw;XNNuY)c8yELe|lp4$%u)?~XhAfb;%RU}mcOHM0yPBfwow3x9#|2GVxv z*IH7>?@PTgPmNv3Un0K7edhu9JIFcrp8=*z$X5K^!QbI>|Um5_8UIJp~_&UdVcy z%o4qj_3n6#o=+<|BkSjLu8fV4t@wS8=-J%}b$x8aQ!n#*-lpzPp`%yS_5bMgx{AiO z3?kNPs{Od*p6hF!u&CeBYqFm^9;2^t&tI)_tRf7&9(A~u&i(ch(0pS!^-T^qdAByG zb&jvw3+&7N!?(-*lPLXT7YxBL%1|EFKbD*OR&QTdsHgLa)!S`#_Vic{jSbeZQ}vBj zPv<~a=&E(ZD)n^t!^}2#r9h6qvXrU*q+e53VC?iGdviUjzOt#Vw&8>otZX~ZKPl0_ z4?ejECr{`S=NIROkn@C|v`U@`b$v^o^oic@ - - - - - - - - - - - - - - - - - - - - - - - - - -LVS_BJT.1 -LVS_BJT.1 -LVS_BJT.1 LVS_BJT overlap of all NPN COMP layers = 0 -LVS_BJT MARKING LAYER - - \ No newline at end of file diff --git a/klayout/drc/testing/testcases/unit/mcell.gds b/klayout/drc/testing/testcases/unit/mcell.gds deleted file mode 100644 index c317b75e7fde27fcb379b49dcb52eb9aabead1e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17168 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 D%A?U_ diff --git a/klayout/drc/testing/testcases/unit/mcell.svg b/klayout/drc/testing/testcases/unit/mcell.svg deleted file mode 100644 index 01d5eb71..00000000 --- a/klayout/drc/testing/testcases/unit/mcell.svg +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MC.1 -MC.1 -MC.1 -MC.1 -MC.1 -MC.1 -MC.1 -MC.1 -MC.1 -MC.1 -MC.1 -MC.2 -MC.2 -MC.2 -MC.4 -Basic -Larger -MC.3 -Basic -Larger -Cor2Cor_90Deg -Notch -45deg -Enclose -Corner2Corner -Corner2Edge -Singular -Overlap -Touch -Space -MC.2 -Cor2Cor_90Deg -Notch -45deg -Enclose -Corner2Corner -Corner2Edge -Singular -Overlap -Touch -Space -Corner2Edge -Width_45deg -Corner_45Deg -Corner2Corner -Width -Default Pass. Minus 2xMinGrid to Fail -LIMITATION: Please ensure width*sqrt(2) < width+statusOvlpTc -Default Pass. Minus 2xMinGrid to Fail -MC.1 -Corner2Edge -Width_45deg -Corner_45Deg -Corner2Corner -Singular -Width -Default Pass. Minus 2xMinGrid to Fail -LIMITATION: Please ensure width*sqrt(2) < width+statusOvlpTc -Default Pass. Minus 2xMinGrid to Fail -MC.4 -MC.4 -MC.4 -MC.4 -MC.3 -MC.3 -MC.3 -MC.3 -MC.2 -MC.2 -MC.2 -MC.2 -MC.2 -MC.2 -MC.2 -MC.2 -MC.2 - - \ No newline at end of file diff --git a/klayout/drc/testing/testcases/unit/otp_mk.gds b/klayout/drc/testing/testcases/unit/otp_mk.gds deleted file mode 100644 index caae0a4fb152a23c417056806c16501dcd647466..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 121226 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 SgKIZL(f{6881Q!8HToZ=>HW9> diff --git a/klayout/drc/testing/testcases/unit/otp_mk.svg b/klayout/drc/testing/testcases/unit/otp_mk.svg deleted file mode 100644 index ce7b40fe..00000000 --- a/klayout/drc/testing/testcases/unit/otp_mk.svg +++ /dev/null @@ -1,1540 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -O.SB.3 -O.SB.3 -O.SB.4 -O.SB.4 -O.SB.5b_LV -O.SB.5b_LV -O.SB.5b_LV -O.SB.5b_LV -O.CO.7 -O.SB.9 -O.SB.11 -O.SB.2 -O.SB.2 -O.SB.2 -O.SB.13_MV -O.SB.13_MV -O.CO.7 -O.SB.2 -O.SB.2 -O.SB.3 -O.SB.3 -O.SB.9 -O.SB.5b_LV -O.SB.3 -O.SB.3 -O.SB.3 -O.SB.3 -O.SB.3 -O.SB.3 -O.SB.3 -O.SB.11 -O.SB.5b_LV -O.SB.4 -O.SB.4 -O.SB.4 -O.SB.4 -O.SB.13_LV -O.SB.13_LV -O.PL.ORT -O.PL.ORT -O.PL.ORT -O.PL.ORT -O.PL.ORT -O.PL.ORT -O.PL.ORT -O.PL.ORT -O.PL.ORT -O.PL.ORT -O.PL.ORT -O.PL.ORT -O.SB.5b_LV -O.SB.5b_LV -O.SB.5b_LV -O.SB.2 -O.SB.2 -O.SB.2 -O.SB.2 -O.SB.2 -O.SB.2 -O.SB.2 -O.SB.5b_LV -O.SB.5b_LV -O.PL.3a -O.PL.3a -O.PL.3a -O.PL.3a -O.PL.3a -O.DF.6 -O.PL.3a -O.PL.3a -O.PL.3a -O.PL.3a -O.PL.4 -O.PL.4 -O.PL.4 -O.PL.4 -O.PL.4 -O.PL.4 -O.DF.3a -O.DF.9 -O.DF.3a -O.DF.6 -O.DF.3a -O.DF.3a -O.DF.9 -O.DF.9 -O.DF.9 -O.DF.3a -O.PL.2 -O.PL.2 -O.PL.2 -O.PL.2 -O.PL.2 -O.PL.2 -O.PL.2 -O.PL.2 -O.PL.2 -O.PL.3a -O.PL.3a -O.PL.3a -O.PL.3a -O.PL.3a -O.DF.3a -O.PL.2 -O.PL.2 -O.PL.2 -O.PL.3a -O.PL.3a -O.PL.3a -O.PL.3a -O.PL.3a -O.DF.6 -O.DF.3a -O.DF.9 -O.PL.2 -O.PL.2 -O.PL.2 -O.DF.9 -O.DF.9 -O.DF.9 -O.PL.2 -O.PL.4 -O.PL.4 -O.PL.2 -O.PL.2 -O.PL.3a -O.PL.3a -O.PL.3a -O.DF.6 -O.PL.3a -O.PL.3a -O.DF.3a -O.DF.3a -O.DF.3a -O.SB.2 -Notch -45deg -Corner2Corner -Corner2Edge -Space -45deg -Corner2Corner -Corner2Edge -Space -Using offset*2 -Cor2Cor_45Deg -Space -O.SB.9 -O.SB.5b -O.SB.11 -45deg -Corner2Corner -Corner2Edge -Space -LIMITATION DEPENDENCIES: priWidth > secOvlpPriSide, priWidth>secOvlpPriTopBot, -Basic -Basic -O.SB.13_MV -Basic -Space -O.SB.4 -O.SB.3 -Space -Singular -Using offset*2 -Cor2Cor_45Deg -Touch -Space -Basic -O.SB.13_LV -Basic -O.CO.7 -O.CO.7 -Cor2Cor_90Deg -45deg -Corner2Corner -Corner2Edge -Singular -Touch -Cor2Cor_90Deg -Notch -45deg -Corner2Corner -Corner2Edge -Singular -Space -Space -O.CO.7 -O.CO.7 -LIMITATION DEPENDENCIES: priWidth > secOvlpPriSide, priWidth>secOvlpPriTopBot, -Cor2Cor_90Deg -45deg -Corner2Corner -Corner2Edge -Singular -Touch -Space -Basic -O.CO.7 Space from active contact to poly2 on active = 0.13 (L/MV) -Corner2Corner -Corner2Edge -Singular -Space -LIMITATION DEPENDENCIES: priWidth > secOvlpPriSide, priWidth>secOvlpPriTopBot, -Touch -Basic -Intersect -LIMITATION DEPENDENCIES: priWidth > secOvlpPriSide, priWidth>secOvlpPriTopBot, -Touch -Basic -Intersect -Intersect case will not be checked by DRC because this will fail the LVS. -Intersect case will not be checked by DRC because this will fail the LVS. -Notch -45deg -Corner2Corner -Corner2Edge -Singular -Space -Cor2Cor_90Deg -Cor2Cor_90Deg -Notch -45deg -Corner2Edge -Space -45deg -Corner2Corner -Corner2Edge -Space -O.PL.2 -O.PL.2 -O.PL.2 -O.PL.4 -O.PL.4 -O.PL.3a -O.PL.3a -LIMITATION DEPENDENCIES: priWidth > secOvlpPriSide, priWidth>secOvlpPriTopBot, -Basic -LIMITATION DEPENDENCIES: priWidth > secOvlpPriSide, priWidth>secOvlpPriTopBot, -Basic -Notch -Notch -45deg -Corner2Corner -2 ERRs -O.DF.9 Min. DIF area = 0.1444 -O.DF.3a Min. active space = 0.24 -4 ERRs -O.DF.9 Min. DIF area = 0.1444 -2 ERRs -O.DF.3a Min. active space = 0.24 (LV) -0 ERRs -4 ERRs -O.DF.6 Extension beyond gate or source/drain overhang = 0.22 (LV) -6 ERRs -O.DF.6 Extension beyond gate or source/drain overhang = 0.22 (MV) -4 ERRs -0 ERRs - - \ No newline at end of file diff --git a/klayout/drc/testing/testcases/unit/pres.gds b/klayout/drc/testing/testcases/unit/pres.gds deleted file mode 100644 index 6a3a528975d5db643fa72d1100f24f5f3ed45de2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70460 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 diff --git a/klayout/drc/testing/testcases/unit/pres.svg b/klayout/drc/testing/testcases/unit/pres.svg deleted file mode 100644 index 703e3877..00000000 --- a/klayout/drc/testing/testcases/unit/pres.svg +++ /dev/null @@ -1,658 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PRES.9a -PRES.9a -PRES.9a -PRES.9a -PRES.9b -PRES.9b -PRES.9b -PRES.9b -PRES.9b -PRES.1 -PRES.1 -PRES.9a -PRES.9a -PRES.9a -PRES.9a -PRES.9a -PRES.9a -PRES.9a -PRES.1 -PRES.1 -PRES.1 -PRES.1 -PRES.1 -PRES.9a -PRES.7 -PRES.7 -PRES.1 -PRES.7 -PRES.7 -PRES.7 -PRES.7 -PRES.7 -PRES.7 -PRES.7 -PRES.1 -PRES.1 -PRES.1 -PRES.1 -PRES.1 -PRES.7 -PRES.7 -PRES.6 -PRES.6 -PRES.6 -PRES.6 -PRES.6 -PRES.6 -PRES.6 -PRES.6 -PRES.5 -PRES.5 -PRES.5 -PRES.5 -PRES.5 -PRES.5 -PRES.5 -PRES.5 -PRES.5 -PRES.5 -PRES.5 -PRES.2 -PRES.2 -PRES.2 -PRES.2 -PRES.2 -PRES.2 -PRES.2 -PRES.2 -PRES.2 -PRES.2 -PRES.2 -PRES.3 -PRES.3 -PRES.5 -PRES.5 -PRES.5 -PRES.4 -PRES.4 -PRES.4 -PRES.4 -PRES.4 -PRES.4 -PRES.3 -PRES.3 -PRES.3 -PRES.3 -PRES.3 -PRES.4 -PRES.4 -PRES.4 -PRES.4 -PRES.4 -PRES.3 -PRES.3 -PRES.3 -PRES.3 -PRES.3 -PRES.3 -PRES.3 -PRES.3 - - \ No newline at end of file diff --git a/pdk_regression.yml b/pdk_regression.yml index 7e29276a..d5216abb 100644 --- a/pdk_regression.yml +++ b/pdk_regression.yml @@ -5,6 +5,7 @@ channels: dependencies: - klayout - python + - ruby - pip - pip: - -r requirements.txt