diff --git a/checks/drc_checks/klayout/met_min_ca_density.lydrc b/checks/drc_checks/klayout/met_min_ca_density.lydrc index 994e70f..2821164 100644 --- a/checks/drc_checks/klayout/met_min_ca_density.lydrc +++ b/checks/drc_checks/klayout/met_min_ca_density.lydrc @@ -16,6 +16,39 @@ drc-dsl-xml +# +# Ways to call. Required parameters: input, report, top_cell. Optional: full_area (um^2). +# 1. klayout -b -r met_min_ca_density.lydrc -rd input=InFile.gds -rd report=/dir/out.rpt -rd top_cell=mytop -rd +# 2. klayout -b -r met_min_ca_density.lydrc -rd input=InFile.gds -rd report=/dir/out.rpt -rd top_cell=mytop -rd full_area=10278400.1111 +# 3. klayout -b -r met_min_ca_density.lydrc -rd input=InFile.gds -rd report=/dir/out.rpt -rd top_cell=mytop -rd full_area=legacy-prBoundary +# those modes are: +# 1. For sky130/project_wrapper hardwired default full_area=10278400.0 (from: 2920x3520): OMIT script option -rd full_area=... +# 2. Pass your own explicitly via script options: -rd full_area=... (e.g. -rd full_area=10278400) +# 3. To force old/obsolete mode: use script options: -rd full_area=legacy-prBoundary +# +# IMPORTANT: Default mode #1 is ONLY relevant for the sky130 project_wrapper; for all else including full-chip you MUST use mode #2 or #3. +# Mode #3 is really only of use/meaning if there's a big solid prBoundary shape, i.e. "close" to covering the whole topcell. +# +# WARNING: If report path is RELATIVE, it gets written RELATIVE to the input gds file! +# +# NOTES: +# Marker-error shapes (in non-legacy mode) are cell's extent (bounding-box), which for arbitrary user-projects +# may have a shape and total-area significantly different from intended project_wrapper size and aspect-ratio. +# This bbox's area is not necessarily same or related to full_area (either built-in default, or user's explicit parameter). +# +# In _default_content/gds/user_project_wrapper.gds, the prBoundary covers (0,0;2920,3520), but there is +# metal OUTSIDE this box. Such metal (even outside the drawn prB, or outside of (0,0;2920,3520)) IS COUNTED +# towards the density ratio, despite the denominator being always just a fixed 2920x3520 rect. If prB was +# covered 100% by metal, the outer metal area would yield density greater than 1; yielding a negative +# clear-area-density. +# +# The XOR-check is expected to ensure project_wrapper stays within the lines, such that default full_area is meaningful. +# In other words: fix XOR-check errors first, then recheck density and address its errors. +# +# For legacy-mode, metal-area was divided by prBoundary shape-area. When prB is less/smaller than metal, +# such a "density" number can easily become greater than 1; yielding a negative clear-area-density. +# + source($input, $top_cell) report("Density Checks", $report) @@ -66,9 +99,44 @@ via4 = polygons(via4_wildcard) m5 = polygons(m5_wildcard) -chip_boundary = input(235,4) +chip_boundary = input(235,4) # legacy-mode only used these shapes, both as input(total area) and output(markers) #area = (m4+m4fill).area -full_area = chip_boundary.area + +# built-in fixed default for sky130/project_wrapper. Use if no -rd full_area=... +full_area = 10278400.0 +mode = "using full_area=#{full_area.to_s} built-in sky130/project_wrapper default-value" + +# prb_bbox=chip_boundary.bbox.to_s +# prb_bboxa=chip_boundary.bbox.area +# puts "full_area=#{full_area}" +# puts "prb.bbox=#{prb_bbox}" +# puts "prb.bbox.area=#{prb_bboxa}" + +if $full_area + if $full_area == "legacy-prBoundary" + mode = "using full_area=chip_boundary.area (lpp:235,4), due script-parameter 'full_area=#{$full_area}'" + # could also be (the not equivalent): chip_boundary.bbox.area + full_area = chip_boundary.area + else + # error shape to write (whole topcell bbox), up to one per metal layer. + # (But this bbox area is not necessarily equal to full_area). + chip_boundary = extent + val = $full_area.to_f + # XML! Could use ENTITY: "val <= 0" (val less-than-or-equal 0) but "0 >= val" is more readable, sadly. + if 0 >= val + STDERR.puts "ERROR: 'full_area=#{$full_area}' script-parameter parsed as non-positive value: #{val}" + STDERR.flush + exit 1 + else + full_area = val + mode = "using 'full_area=#{$full_area}' script-parameter, parsed as: #{full_area}" + end + end +end + + +puts "area-mode: #{mode}" +STDOUT.flush #li1_wildcard = "67/20" #li1fill_wildcard = "56/28"