Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated exit code for DRC regression #78

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions rules/klayout/drc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,22 @@ Explains how to use the runset.
```

## Rule Deck Usage
The `run_drc.py` script takes a gds file to run DRC rule decks of GF180 technology with switches to select subsets of all checks.

### Requirements
Please make sure to define PDK_ROOT and PDK environment variables to make it work. Example definition would be to work for this repo, go to the `rules/klayout` directory and run:
```bash
export PDK_ROOT=`pwd`
export PDK="drc"
```
Also, please make sure to install the required python packages at `../requirements.test.txt` by using
```bash
pip install -r ../requirements.test.txt
```

The `run_drc.py` script takes a gds file to run DRC rule decks of GF180 technology with switches to select subsets of all checks.

### **Switches**
### Switches
The list of switches used for running DRC:

1. **FEOL** : Default is on. Use it for checking Front End Of Line layers (wells, diffusion, polys, contacts).
2. **BEOL** : Default is on. Use it for checking Back End Of Line layers (metal layers, top metal layer, vias).
Expand All @@ -44,7 +56,7 @@ The `run_drc.py` script takes a gds file to run DRC rule decks of GF180 technolo
Example:

```bash
python3 run_drc.py --path=testing/switch_checking/switch_checking.gds --thr=16 --run_mode=flat --gf180mcu=A --antenna --no_offgrid
python3 run_drc.py --path=testing/switch_checking/simple_por.gds.gz --thr=16 --run_mode=flat --gf180mcu=A --antenna --no_offgrid
```

### Options
Expand Down
251 changes: 136 additions & 115 deletions rules/klayout/drc/gf180mcu.drc
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,25 @@ if $report
logger.info("GF180MCU Klayout DRC runset output at: %s" % [$report])
report("DRC Run Report at", $report)
else
logger.info("GF180MCU Klayout DRC runset output at default location." % [File.join(File.dirname(RBA::CellView::active.filename), "gf180_drc.lyrdb").path])
logger.info("GF180MCU Klayout DRC runset output at default location." % [File.join(File.dirname(RBA::CellView::active.filename), "gf180_drc.lyrdb")])
report("DRC Run Report at", File.join(File.dirname(RBA::CellView::active.filename), "gf180_drc.lyrdb"))
end

if $thr
logger.info("Number of threads to use %s" % [$thr])
threads($thr)
logger.info("Number of threads to use %s" % [$thr])
else
logger.info("Number of threads to use 16")
threads(16)
threads(%x("nproc"))
logger.info("Number of threads to use #{%x("nproc")}")
end

#=== PRINT DETAILS ===
if $verbose == "true"
logger.info("Verbose mode: #{$verbose}")
verbose(true)
else
verbose(false)
logger.info("Verbose mode: false")
end

# === TILING MODE ===
Expand Down Expand Up @@ -95,112 +104,112 @@ end # run_mode
logger.info("Read in polygons from layers.")


comp = polygons(22 , 0 )
dnwell = polygons(12 , 0 )
nwell = polygons(21 , 0 )
lvpwell = polygons(204, 0 )
dualgate = polygons(55 , 0 )
poly2 = polygons(30 , 0 )
nplus = polygons(32 , 0 )
pplus = polygons(31 , 0 )
sab = polygons(49 , 0 )
esd = polygons(24 , 0 )
contact = polygons(33 , 0 )
metal1 = polygons(34 , 0 )
via1 = polygons(35 , 0 )
metal2 = polygons(36 , 0 )
via2 = polygons(38 , 0 )
metal3 = polygons(42 , 0 )
via3 = polygons(40 , 0 )
metal4 = polygons(46 , 0 )
via4 = polygons(41 , 0 )
metal5 = polygons(81 , 0 )
via5 = polygons(82 , 0 )
metaltop = polygons(53 , 0 )
pad = polygons(37 , 0 )
resistor = polygons(62 , 0 )
fhres = polygons(227, 0 )
fusetop = polygons(75 , 0 )
fusewindow_d = polygons(96 , 1 )
polyfuse = polygons(220, 0 )
mvsd = polygons(210, 0 )
mvpsd = polygons(11 , 39)
nat = polygons(5 , 0 )
comp_dummy = polygons(22 , 4 )
poly2_dummy = polygons(30 , 4 )
metal1_dummy = polygons(34 , 4 )
metal2_dummy = polygons(36 , 4 )
metal3_dummy = polygons(42 , 4 )
metal4_dummy = polygons(46 , 4 )
metal5_dummy = polygons(81 , 4 )
metaltop_dummy = polygons(53 , 4 )
comp_label = polygons(22 , 10)
poly2_label = polygons(30 , 10)
metal1_label = polygons(34 , 10)
metal2_label = polygons(36 , 10)
metal3_label = polygons(42 , 10)
metal4_label = polygons(46 , 10)
metal5_label = polygons(81 , 10)
metaltop_label = polygons(53 , 10)
metal1_slot = polygons(34 , 3 )
metal2_slot = polygons(36 , 3 )
metal3_slot = polygons(42 , 3 )
metal4_slot = polygons(46 , 3 )
metal5_slot = polygons(81 , 3 )
metaltop_slot = polygons(53 , 3 )
ubmpperi = polygons(183, 0 )
ubmparray = polygons(184, 0 )
ubmeplate = polygons(185, 0 )
schottky_diode = polygons(241, 0 )
zener = polygons(178, 0 )
res_mk = polygons(110, 5 )
opc_drc = polygons(124, 5 )
ndmy = polygons(111, 5 )
pmndmy = polygons(152, 5 )
v5_xtor = polygons(112, 1 )
cap_mk = polygons(117, 5 )
mos_cap_mk = polygons(166, 5 )
ind_mk = polygons(151, 5 )
diode_mk = polygons(115, 5 )
drc_bjt = polygons(127, 5 )
lvs_bjt = polygons(118, 5 )
mim_l_mk = polygons(117, 10)
latchup_mk = polygons(137, 5 )
guard_ring_mk = polygons(167, 5 )
otp_mk = polygons(173, 5 )
mtpmark = polygons(122, 5 )
neo_ee_mk = polygons(88 , 17)
sramcore = polygons(108, 5 )
lvs_rf = polygons(100, 5 )
lvs_drain = polygons(100, 7 )
ind_mk = polygons(151, 5 )
hvpolyrs = polygons(123, 5 )
lvs_io = polygons(119, 5 )
probe_mk = polygons(13 , 17)
esd_mk = polygons(24 , 5 )
lvs_source = polygons(100, 8 )
well_diode_mk = polygons(153, 51)
ldmos_xtor = polygons(226, 0 )
plfuse = polygons(125, 5 )
efuse_mk = polygons(80 , 5 )
mcell_feol_mk = polygons(11 , 17)
ymtp_mk = polygons(86 , 17)
dev_wf_mk = polygons(128, 17)
metal1_blk = polygons(34 , 5 )
metal2_blk = polygons(36 , 5 )
metal3_blk = polygons(42 , 5 )
metal4_blk = polygons(46 , 5 )
metal5_blk = polygons(81 , 5 )
metalt_blk = polygons(53 , 5 )
pr_bndry = polygons(0 , 0 )
mdiode = polygons(116, 5 )
metal1_res = polygons(110, 11)
metal2_res = polygons(110, 12)
metal3_res = polygons(110, 13)
metal4_res = polygons(110, 14)
metal5_res = polygons(110, 15)
metal6_res = polygons(110, 16)
border = polygons(63 , 0 )
comp = polygons(22 , 0 ).merged
dnwell = polygons(12 , 0 ).merged
nwell = polygons(21 , 0 ).merged
lvpwell = polygons(204, 0 ).merged
dualgate = polygons(55 , 0 ).merged
poly2 = polygons(30 , 0 ).merged
nplus = polygons(32 , 0 ).merged
pplus = polygons(31 , 0 ).merged
sab = polygons(49 , 0 ).merged
esd = polygons(24 , 0 ).merged
contact = polygons(33 , 0 ).merged
metal1 = polygons(34 , 0 ).merged
via1 = polygons(35 , 0 ).merged
metal2 = polygons(36 , 0 ).merged
via2 = polygons(38 , 0 ).merged
metal3 = polygons(42 , 0 ).merged
via3 = polygons(40 , 0 ).merged
metal4 = polygons(46 , 0 ).merged
via4 = polygons(41 , 0 ).merged
metal5 = polygons(81 , 0 ).merged
via5 = polygons(82 , 0 ).merged
metaltop = polygons(53 , 0 ).merged
pad = polygons(37 , 0 ).merged
resistor = polygons(62 , 0 ).merged
fhres = polygons(227, 0 ).merged
fusetop = polygons(75 , 0 ).merged
fusewindow_d = polygons(96 , 1 ).merged
polyfuse = polygons(220, 0 ).merged
mvsd = polygons(210, 0 ).merged
mvpsd = polygons(11 , 39).merged
nat = polygons(5 , 0 ).merged
comp_dummy = polygons(22 , 4 ).merged
poly2_dummy = polygons(30 , 4 ).merged
metal1_dummy = polygons(34 , 4 ).merged
metal2_dummy = polygons(36 , 4 ).merged
metal3_dummy = polygons(42 , 4 ).merged
metal4_dummy = polygons(46 , 4 ).merged
metal5_dummy = polygons(81 , 4 ).merged
metaltop_dummy = polygons(53 , 4 ).merged
comp_label = polygons(22 , 10).merged
poly2_label = polygons(30 , 10).merged
metal1_label = polygons(34 , 10).merged
metal2_label = polygons(36 , 10).merged
metal3_label = polygons(42 , 10).merged
metal4_label = polygons(46 , 10).merged
metal5_label = polygons(81 , 10).merged
metaltop_label = polygons(53 , 10).merged
metal1_slot = polygons(34 , 3 ).merged
metal2_slot = polygons(36 , 3 ).merged
metal3_slot = polygons(42 , 3 ).merged
metal4_slot = polygons(46 , 3 ).merged
metal5_slot = polygons(81 , 3 ).merged
metaltop_slot = polygons(53 , 3 ).merged
ubmpperi = polygons(183, 0 ).merged
ubmparray = polygons(184, 0 ).merged
ubmeplate = polygons(185, 0 ).merged
schottky_diode = polygons(241, 0 ).merged
zener = polygons(178, 0 ).merged
res_mk = polygons(110, 5 ).merged
opc_drc = polygons(124, 5 ).merged
ndmy = polygons(111, 5 ).merged
pmndmy = polygons(152, 5 ).merged
v5_xtor = polygons(112, 1 ).merged
cap_mk = polygons(117, 5 ).merged
mos_cap_mk = polygons(166, 5 ).merged
ind_mk = polygons(151, 5 ).merged
diode_mk = polygons(115, 5 ).merged
drc_bjt = polygons(127, 5 ).merged
lvs_bjt = polygons(118, 5 ).merged
mim_l_mk = polygons(117, 10).merged
latchup_mk = polygons(137, 5 ).merged
guard_ring_mk = polygons(167, 5 ).merged
otp_mk = polygons(173, 5 ).merged
mtpmark = polygons(122, 5 ).merged
neo_ee_mk = polygons(88 , 17).merged
sramcore = polygons(108, 5 ).merged
lvs_rf = polygons(100, 5 ).merged
lvs_drain = polygons(100, 7 ).merged
ind_mk = polygons(151, 5 ).merged
hvpolyrs = polygons(123, 5 ).merged
lvs_io = polygons(119, 5 ).merged
probe_mk = polygons(13 , 17).merged
esd_mk = polygons(24 , 5 ).merged
lvs_source = polygons(100, 8 ).merged
well_diode_mk = polygons(153, 51).merged
ldmos_xtor = polygons(226, 0 ).merged
plfuse = polygons(125, 5 ).merged
efuse_mk = polygons(80 , 5 ).merged
mcell_feol_mk = polygons(11 , 17).merged
ymtp_mk = polygons(86 , 17).merged
dev_wf_mk = polygons(128, 17).merged
metal1_blk = polygons(34 , 5 ).merged
metal2_blk = polygons(36 , 5 ).merged
metal3_blk = polygons(42 , 5 ).merged
metal4_blk = polygons(46 , 5 ).merged
metal5_blk = polygons(81 , 5 ).merged
metalt_blk = polygons(53 , 5 ).merged
pr_bndry = polygons(0 , 0 ).merged
mdiode = polygons(116, 5 ).merged
metal1_res = polygons(110, 11).merged
metal2_res = polygons(110, 12).merged
metal3_res = polygons(110, 13).merged
metal4_res = polygons(110, 14).merged
metal5_res = polygons(110, 15).merged
metal6_res = polygons(110, 16).merged
border = polygons(63 , 0 ).merged

# ================= COUNT POLYGONS =================
poly_count = 0
Expand Down Expand Up @@ -474,7 +483,7 @@ logger.info("METAL_TOP Selected is %s" % [METAL_TOP])
if $metal_level
METAL_LEVEL = $metal_level
else
METAL_LEVEL = "6LM"
METAL_LEVEL = "5LM"
end # METAL_LEVEL

logger.info("METAL_STACK Selected is %s" % [METAL_LEVEL])
Expand Down Expand Up @@ -509,7 +518,7 @@ logger.info("Gold enabled %s" % [GOLD])
if $mim_option
MIM_OPTION = $mim_option
else
MIM_OPTION = "Nan"
MIM_OPTION = "B"
end

logger.info("MIM Option selected %s" % [MIM_OPTION])
Expand Down Expand Up @@ -836,7 +845,7 @@ nw1a_l1 = nwell.width(0.86.um, euclidian).polygons(0.001).overlapping(dualgate)
nw1a_l1.output("NW.1a_5V", "NW.1a_5V : Min. Nwell Width (This is only for litho purpose on the generated area). : 0.86µm")
nw1a_l1.forget

nw_1b = nwell.outside(dnwell).and(res_mk).not(comp).not(poly2)
nw_1b = nwell.outside(dnwell).and(res_mk)
# Rule NW.1b_3.3V: Min. Nwell Width as a resistor (Outside DNWELL only). is 2µm
logger.info("Executing rule NW.1b_3.3V")
nw1b_l1 = nw_1b.width(2.um, euclidian).polygons(0.001).not_interacting(v5_xtor).not_interacting(dualgate)
Expand Down Expand Up @@ -3071,6 +3080,12 @@ mt2a_l1 = metaltop.space(0.38.um, euclidian).polygons(0.001)
mt2a_l1.output("MT.2a", "MT.2a : min. metaltop spacing : 0.38µm")
mt2a_l1.forget

# Rule MT.2b: Space to wide Metal2 (length & width > 10um) is 0.5µm
logger.info("Executing rule MT.2b")
mt2b_l1 = metaltop.separation(metal2.not_interacting(metal2.edges.with_length(nil, 10.um)), 0.5.um, euclidian).polygons(0.001)
mt2b_l1.output("MT.2b", "MT.2b : Space to wide Metal2 (length & width > 10um) : 0.5µm")
mt2b_l1.forget

# Rule MT.4: Minimum MetalTop area is 0.5625µm²
logger.info("Executing rule MT.4")
mt4_l1 = metaltop.with_area(nil, 0.5625.um)
Expand All @@ -3092,6 +3107,12 @@ mt2a_l1 = metaltop.space(0.46.um, euclidian).polygons(0.001)
mt2a_l1.output("MT.2a", "MT.2a : min. metaltop spacing : 0.46µm")
mt2a_l1.forget

# Rule MT.2b: Space to wide Metal2 (length & width > 10um) is 0.6µm
logger.info("Executing rule MT.2b")
mt2b_l1 = metaltop.separation(metaltop.not_interacting(metal2.edges.with_length(nil, 10.um)), 0.6.um, euclidian).polygons(0.001)
mt2b_l1.output("MT.2b", "MT.2b : Space to wide Metal2 (length & width > 10um) : 0.6µm")
mt2b_l1.forget

# Rule MT.4: Minimum MetalTop area is 0.5625µm²
logger.info("Executing rule MT.4")
mt4_l1 = metaltop.with_area(nil, 0.5625.um)
Expand Down Expand Up @@ -3137,8 +3158,8 @@ mt305_l1 = top_metal.enclosing(top_via, 0.12.um, euclidian).polygons(0.001).or(t
mt305_l1.output("MT30.5", "MT30.5 : Minimum thick MetalTop enclose underlying via (for example: via5 for 6LM case) [Outside Not Allowed].")
mt305_l1.forget

mt30p6_cond = top_metal.drc( width <= 0.34.um)
mt30p6_eol = top_metal.edges.with_length(nil, 0.34.um).interacting(mt30p6_cond.first_edges).interacting(mt30p6_cond.second_edges).not(mt30p6_cond.first_edges).not(mt30p6_cond.second_edges)
mt30p6_cond = top_metal.drc( width < 2.5.um)
mt30p6_eol = top_metal.edges.with_length(nil, 2.5.um).interacting(mt30p6_cond.first_edges).interacting(mt30p6_cond.second_edges).not(mt30p6_cond.first_edges).not(mt30p6_cond.second_edges)
# Rule MT30.6: Thick MetalTop end-of-line (width <2.5um) enclose underlying via (for example: via5 for 6LM case) [Outside Not Allowed].
logger.info("Executing rule MT30.6")
mt306_l1 = mt30p6_eol.enclosing(top_via.edges,0.25.um, projection).polygons(0.001).or(top_via.not_inside(top_metal))
Expand Down
36 changes: 18 additions & 18 deletions rules/klayout/drc/gf180mcu_antenna.drc
Original file line number Diff line number Diff line change
Expand Up @@ -87,24 +87,24 @@ end # run_mode
#--------------------------------------- LAYER DEFINITIONS --------------------------------------------
#======================================================================================================

comp = polygons(22, 0)
dualgate = polygons(55, 0)
poly2 = polygons(30, 0)
nplus = polygons(32, 0)
pplus = polygons(31, 0)
contact = polygons(33, 0)
metal1 = polygons(34, 0)
via1 = polygons(35, 0)
metal2 = polygons(36, 0)
via2 = polygons(38, 0)
metal3 = polygons(42, 0)
via3 = polygons(40, 0)
metal4 = polygons(46, 0)
via4 = polygons(41, 0)
metal5 = polygons(81, 0)
via5 = polygons(82, 0)
metaltop = polygons(53, 0)
fusetop = polygons(75, 0)
comp = polygons(22, 0).merged
dualgate = polygons(55, 0).merged
poly2 = polygons(30, 0).merged
nplus = polygons(32, 0).merged
pplus = polygons(31, 0).merged
contact = polygons(33, 0).merged
metal1 = polygons(34, 0).merged
via1 = polygons(35, 0).merged
metal2 = polygons(36, 0).merged
via2 = polygons(38, 0).merged
metal3 = polygons(42, 0).merged
via3 = polygons(40, 0).merged
metal4 = polygons(46, 0).merged
via4 = polygons(41, 0).merged
metal5 = polygons(81, 0).merged
via5 = polygons(82, 0).merged
metaltop = polygons(53, 0).merged
fusetop = polygons(75, 0).merged

#======================================================================================================
#--------------------------------------- LAYER DERIVATIONS --------------------------------------------
Expand Down
Loading