diff --git a/src/db/db/dbFillTool.cc b/src/db/db/dbFillTool.cc index 0dd69de06..04358f6e1 100644 --- a/src/db/db/dbFillTool.cc +++ b/src/db/db/dbFillTool.cc @@ -77,14 +77,16 @@ public: } // because the rasterizer can't handle overlapping cells we need to multiply the row and columns steps - // with an integer until the effective rasterizer pitch get big enough. + // with an integer until the effective rasterizer pitch gets big enough. m_row_steps *= (m_dim.x () - 1) / (m_row_steps * m_row_step.x ()) + 1; m_column_steps *= (m_dim.y () - 1) / (m_column_steps * m_column_step.y ()) + 1; db::Box fp_bbox = fp.box (); // compensate for distortion by sheared kernel - fp_bbox.enlarge (db::Vector (db::coord_traits::rounded (double (fp_bbox.height ()) * std::abs (m_column_step.x ()) / dy), db::coord_traits::rounded (double (fp_bbox.width ()) * std::abs (m_row_step.y ()) / dx))); + db::Coord ex = std::max (std::abs (db::Coord (m_column_step.x () * m_column_steps)), std::abs (db::Coord (m_row_step.x () * m_row_steps))); + db::Coord ey = std::max (std::abs (db::Coord (m_column_step.y () * m_column_steps)), std::abs (db::Coord (m_row_step.y () * m_row_steps))); + fp_bbox.enlarge (db::Vector (ex, ey)); int columns_per_rows = (int (m_row_steps) * m_row_step.y ()) / dy; int rows_per_columns = (int (m_column_steps) * m_column_step.x ()) / dx; @@ -167,6 +169,11 @@ public: return m_area_maps [i]; } + db::AreaMap &area_map (unsigned int i) + { + return m_area_maps [i]; + } + private: std::vector m_area_maps; db::Vector m_row_step, m_column_step; @@ -246,7 +253,7 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f for (unsigned int i = 0; i < am.area_maps (); ++i) { - const db::AreaMap &am1 = am.area_map (i); + db::AreaMap &am1 = am.area_map (i); size_t nx = am1.nx (); size_t ny = am1.ny (); @@ -263,31 +270,54 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f ++jj; } - ninsts += (jj - j); - db::Vector p0 = (am1.p0 () - db::Point ()) - kernel_origin; p0 += db::Vector (i * am1.d ().x (), j * am1.d ().y ()); db::CellInstArray array; - if (jj > j + 1) { - array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0), db::Vector (0, am1.d ().y ()), db::Vector (), (unsigned long) (jj - j), 1); + // try to expand the array in x direction + size_t ii = i + 1; + for ( ; ii < nx; ++ii) { + bool all = true; + for (size_t k = j; k < jj && all; ++k) { + all = am1.get (ii, k) == am1.pixel_area (); + } + if (all) { + for (size_t k = j; k < jj; ++k) { + // disable pixel, so we do not see it again in the following columns + am1.get (ii, k) = 0; + } + } else { + break; + } + } + + ninsts += (jj - j) * (ii - i); + + if (jj > j + 1 || ii > i + 1) { + array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0), db::Vector (0, am1.d ().y ()), db::Vector (am1.d ().x (), 0), (unsigned long) (jj - j), (unsigned long) (ii - i)); } else { array = db::CellInstArray (db::CellInst (fill_cell_index), db::Trans (p0)); } { // In case we run this from a tiling processor we need to lock against multithread races - tl::MutexLocker locker (&db::TilingProcessor::output_lock ()); + tl_assert (cell->layout () != 0); + tl::MutexLocker locker (&cell->layout ()->lock ()); cell->insert (array); } if (remaining_parts) { - if (am1.d ().y () == am1.p ().y ()) { - filled_regions.push_back (db::Polygon (db::Box (db::Point (), db::Point (am1.p ().x (), am1.p ().y () * db::Coord (jj - j))).moved (kernel_origin + p0))); + if (am1.d ().y () == am1.p ().y () && am1.d ().x () == am1.p ().x ()) { + db::Box fill_box (db::Point (), db::Point (am1.p ().x () * db::Coord (ii - i), am1.p ().y () * db::Coord (jj - j))); + filled_regions.push_back (db::Polygon (fill_box.enlarged (fill_margin).moved (kernel_origin + p0))); } else { + db::Box fill_box (db::Point (), db::Point () + am1.p ()); + fill_box.enlarge (fill_margin); for (size_t k = 0; k < jj - j; ++k) { - filled_regions.push_back (db::Polygon (db::Box (db::Point (), db::Point () + am1.p ()).moved (kernel_origin + p0 + db::Vector (0, am1.d ().y () * db::Coord (k))))); + for (size_t l = 0; l < ii - i; ++l) { + filled_regions.push_back (db::Polygon (fill_box.moved (kernel_origin + p0 + db::Vector (am1.d ().x () * db::Coord (l), am1.d ().y () * db::Coord (k))))); + } } } } @@ -314,19 +344,9 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f if (any_fill) { if (remaining_parts) { - std::vector fp1; - - if (fill_margin != db::Vector ()) { - ep.size (filled_regions, fill_margin.x (), fill_margin.y (), fp1, 3 /*mode*/, false /*=don't resolve holes*/); - filled_regions.swap (fp1); - fp1.clear (); - } - fp1.push_back (fp0); ep.boolean (fp1, filled_regions, *remaining_parts, db::BooleanOp::ANotB, false /*=don't resolve holes*/); - - } return true; diff --git a/src/db/db/dbPolygonTools.cc b/src/db/db/dbPolygonTools.cc index 9c306aa21..f709df749 100644 --- a/src/db/db/dbPolygonTools.cc +++ b/src/db/db/dbPolygonTools.cc @@ -1918,7 +1918,7 @@ rasterize_impl (const db::polygon &polygon, db::area_map &am) area_type aa = a; - if (dx == py) { + if (dx == px) { box_type cell (x, y, xx, yy); diff --git a/src/db/db/dbRecursiveShapeIterator.cc b/src/db/db/dbRecursiveShapeIterator.cc index b3965f9ce..1f8758bd1 100644 --- a/src/db/db/dbRecursiveShapeIterator.cc +++ b/src/db/db/dbRecursiveShapeIterator.cc @@ -500,15 +500,21 @@ RecursiveShapeIterator::validate (RecursiveShapeReceiver *receiver) const } if (mp_shapes) { + // Ensures the trees are built properly - this is important in MT contexts (i.e. TilingProcessor) // TODO: get rid of that const cast (const_cast (mp_shapes))->update (); + start_shapes (); + } else if (mp_layout && (! m_has_layers || m_current_layer < m_layers.size ())) { + // Ensures the trees are built properly - this is important in MT contexts (i.e. TilingProcessor) mp_layout->update (); + new_cell (receiver); next_shape (receiver); + } if (mp_layout && ! at_end ()) { diff --git a/src/db/db/dbShapes.cc b/src/db/db/dbShapes.cc index 2c5e90f46..5774973b9 100644 --- a/src/db/db/dbShapes.cc +++ b/src/db/db/dbShapes.cc @@ -1127,10 +1127,20 @@ void Shapes::reset_bbox_dirty () void Shapes::update () { + std::unique_ptr locker; + + // If not in a layout context, we should lock here against multiple calls from different threads. + // In a layout context, the Layout object will do that for us. + if (layout () == 0) { + static tl::Mutex lock; + locker.reset (new tl::MutexLocker (&lock)); + } + for (tl::vector::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) { (*l)->sort (); (*l)->update_bbox (); } + set_dirty (false); } diff --git a/src/db/unit_tests/dbFillToolTests.cc b/src/db/unit_tests/dbFillToolTests.cc index 97ebbfefb..4ce7b53bb 100644 --- a/src/db/unit_tests/dbFillToolTests.cc +++ b/src/db/unit_tests/dbFillToolTests.cc @@ -345,3 +345,35 @@ TEST(5) CHECKPOINT(); db::compare_layouts (_this, ly, tl::testdata () + "/algo/fill_tool_au5.oas", db::WriteOAS); } + +// issue #2087 +TEST(6) +{ + db::Layout ly; + { + std::string fn (tl::testdata ()); + fn += "/algo/fill_tool6.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type fill_cell = ly.cell_by_name ("FILL_CELL").second; + db::cell_index_type top_cell = ly.cell_by_name ("TOP").second; + unsigned int fill_layer = ly.get_layer (db::LayerProperties (1, 0)); + + db::Region fill_region (db::RecursiveShapeIterator (ly, ly.cell (top_cell), fill_layer)); + + db::Region remaining_polygons; + + db::Vector rs (2500, 0); + db::Vector cs (650, 2500); + db::Box fc_box = ly.cell (fill_cell).bbox (); + db::fill_region (&ly.cell (top_cell), fill_region, fill_cell, fc_box, rs, cs, db::Point (), false, &remaining_polygons); + + unsigned int l100 = ly.insert_layer (db::LayerProperties (100, 0)); + remaining_polygons.insert_into (&ly, top_cell, l100); + + CHECKPOINT(); + db::compare_layouts (_this, ly, tl::testdata () + "/algo/fill_tool_au6.oas", db::WriteOAS); +} diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index 25f47c22d..5e37dd784 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -5460,8 +5460,17 @@ CODE # as the reference point. The reference point will also defined the footprint of the fill cell - more precisely # the lower left corner. When step vectors are given, the fill cell's footprint is taken to be a rectangle # having the horizontal and vertical step pitch for width and height respectively. This way the fill cells - # will be arrange seamlessly. However, the cell's dimensions can be changed, so that the fill cells + # will be arrange seamlessly. + # + # However, the cell's dimensions can be changed, so that the fill cells # can overlap or there is a space between the cells. To change the dimensions use the "dim" method. + # This example will use a fill cell footprint of 1x1 micrometers, regardless of the step pitch: + # + # @code + # p = fill_pattern("FILL_CELL") + # p.shape(1, 0, box(0.0, 0.0, 1.0, 1.0)) + # p.dim(1.0, 1.0) + # @/code # # The following example specifies a fill cell with an active area of -0.5 .. 1.5 in both directions # (2 micron width and height). With these dimensions the fill cell's footprint is independent of the @@ -5474,6 +5483,18 @@ CODE # p.dim(2.0, 2.0) # @/code # + # Finally, the fill cell can be given a margin: this is a space around the fill cell which needs + # to be inside the fill region. Hence, the margin can be used to implement a distance, the fill + # cells (more precisely: their footprints) will maintain to the outside border of the fill region. + # The following example implements a margin of 200 nm in horizontal and 250 nm in vertical direction: + # + # @code + # p = fill_pattern("FILL_CELL") + # p.shape(1, 0, box(0.0, 0.0, 1.0, 1.0)) + # p.dim(1.0, 1.0) + # p.margin(0.2, 0.25) + # @/code + # # With these ingredients will can use the fill function. The first example fills the polygons # of "to_fill" with an orthogonal pattern of 1x1 micron rectangles with a pitch of 2 microns: # @@ -5574,6 +5595,7 @@ CODE fill_cell = pattern.create_cell(@engine._output_layout, @engine) top_cell = @engine._output_cell fc_box = dbu_trans * pattern.cell_box(row_step.x, column_step.y) + fill_margin = dbu_trans * pattern.fill_margin rs = dbu_trans * row_step cs = dbu_trans * column_step origin = origin ? dbu_trans * origin : nil @@ -5604,6 +5626,7 @@ CODE tp.var("rs", rs) tp.var("cs", cs) tp.var("origin", origin) + tp.var("fill_margin", fill_margin) tp.var("fc_index", fc_index) tp.var("repeat", repeat) tp.var("with_left", with_left) @@ -5616,8 +5639,8 @@ CODE tile_box = tile_box & tc_box; var left = with_left ? Region.new : nil; repeat ? - (region & tile_box).fill_multi(top_cell, fc_index, fc_box, rs, cs, Vector.new, left, _tile.bbox) : - (region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, left, Vector.new, left, _tile.bbox); + (region & tile_box).fill_multi(top_cell, fc_index, fc_box, rs, cs, fill_margin, left, _tile.bbox) : + (region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, left, fill_margin, left, _tile.bbox); with_left && _output(#{result_arg}, left) ) END @@ -5639,9 +5662,9 @@ END @engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do if repeat - self.data.fill_multi(top_cell, fc_index, fc_box, rs, cs, RBA::Vector::new, result) + self.data.fill_multi(top_cell, fc_index, fc_box, rs, cs, fill_margin, result) else - self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, RBA::Vector::new, result) + self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, fill_margin, result) end end diff --git a/src/drc/drc/built-in-macros/_drc_tags.rb b/src/drc/drc/built-in-macros/_drc_tags.rb index 56cf18023..710626f53 100644 --- a/src/drc/drc/built-in-macros/_drc_tags.rb +++ b/src/drc/drc/built-in-macros/_drc_tags.rb @@ -335,6 +335,7 @@ module DRC @shapes = [] @origin = nil @dim = nil + @margin = RBA::DVector::new end def create_cell(layout, engine) @@ -350,7 +351,11 @@ module DRC def cell_box(def_w, def_h) o = @origin || self._computed_origin d = @dim || RBA::DVector::new(def_w, def_h) - RBA::DBox::new(o, o + d) + RBA::DBox::new(o, o + d).enlarged(@margin) + end + + def fill_margin + -@margin end def default_xpitch @@ -454,6 +459,20 @@ module DRC end + def margin(w, h) + + if !w.is_a?(1.class) && !w.is_a?(1.0.class) + raise("w argument not numeric FillCell#dim") + end + if !h.is_a?(1.class) && !h.is_a?(1.0.class) + raise("h argument not numeric FillCell#dim") + end + @margin = RBA::DVector::new(w, h) + + self + + end + end # A wrapper for the fill step definition diff --git a/src/drc/unit_tests/drcFullTests.cc b/src/drc/unit_tests/drcFullTests.cc new file mode 100644 index 000000000..36aecd8a7 --- /dev/null +++ b/src/drc/unit_tests/drcFullTests.cc @@ -0,0 +1,70 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2025 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "tlUnitTest.h" +#include "dbReader.h" +#include "dbTestSupport.h" +#include "lymMacro.h" + +TEST(1_IHPMetal1Fill) +{ + test_is_long_runner (); + + std::string rs = tl::testdata (); + rs += "/drc/drcFullTest_1.drc"; + + std::string input = tl::testdata (); + input += "/drc/drcFullTest_1.oas"; + + std::string au = tl::testdata (); + au += "/drc/drcFullTest_au1.oas"; + + std::string output = this->tmp_file ("tmp.oas"); + + { + // Set some variables + lym::Macro config; + config.set_text (tl::sprintf ( + "$drc_force_gc = true\n" + "$drc_test_source = '%s'\n" + "$drc_test_target = '%s'\n" + , input, output) + ); + config.set_interpreter (lym::Macro::Ruby); + EXPECT_EQ (config.run (), 0); + } + + lym::Macro drc; + drc.load_from (rs); + EXPECT_EQ (drc.run (), 0); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + db::compare_layouts (_this, layout, au, db::NoNormalization); +} + diff --git a/src/drc/unit_tests/unit_tests.pro b/src/drc/unit_tests/unit_tests.pro index 30b2d3db0..b65797945 100644 --- a/src/drc/unit_tests/unit_tests.pro +++ b/src/drc/unit_tests/unit_tests.pro @@ -10,6 +10,7 @@ SOURCES = \ drcBasicTests.cc \ drcGenericTests.cc \ drcSimpleTests.cc \ + drcFullTests.cc \ drcSuiteTests.cc \ INCLUDEPATH += $$DRC_INC $$TL_INC $$RDB_INC $$DB_INC $$GSI_INC $$LYM_INC diff --git a/testdata/algo/fill_tool6.gds b/testdata/algo/fill_tool6.gds new file mode 100644 index 000000000..708e35256 Binary files /dev/null and b/testdata/algo/fill_tool6.gds differ diff --git a/testdata/algo/fill_tool_au5.oas b/testdata/algo/fill_tool_au5.oas index f4040eedc..1a190bc74 100644 Binary files a/testdata/algo/fill_tool_au5.oas and b/testdata/algo/fill_tool_au5.oas differ diff --git a/testdata/algo/fill_tool_au6.oas b/testdata/algo/fill_tool_au6.oas new file mode 100644 index 000000000..8d679848d Binary files /dev/null and b/testdata/algo/fill_tool_au6.oas differ diff --git a/testdata/drc/drcFullTest_1.drc b/testdata/drc/drcFullTest_1.drc new file mode 100644 index 000000000..8c77cc4f9 --- /dev/null +++ b/testdata/drc/drcFullTest_1.drc @@ -0,0 +1,58 @@ + +source($drc_test_source) +target($drc_test_target) + +verbose + +ncpu = 4 + +chip = input(189, 4) +chip.output(189, 4) + +# NOTE: this must not happen in tiled mode as the sealring +# is only visible as a whole in flat mode +sealring = source.cell("sealring") + +metal1_seal = sealring.input(8, 0) +metal1_seal_inner = metal1_seal.holes +# NOTE: metal1_seal_outer is empty if there is no sealring -> +# the full chip will be filled +metal1_seal_outer = chip.interacting(metal1_seal_inner) - metal1_seal_inner + +# Everything else can be done in tiled mode + +tiles(500) +tile_borders(2.0) +threads(ncpu) + +metal1 = input(8, 0) +metal1.output(8, 0) +metal1_fill = input(8, 22) +metal1_nofill = input(8, 23) + metal1_seal_outer + +metal1_dist = 0.42 +min_space_to_fill = 1.0 + +pattern = fill_pattern("METAL1_FILL1") +pattern.shape(8, 22, box(0.0, 0.0, 5.0, 5.0)) +pattern.dim(5.0, 5.0) +pattern.margin(metal1_dist, metal1_dist) + +to_fill = chip - metal1_nofill - metal1 + +to_fill = to_fill.fill_with_left(pattern, hstep(7.0, 0), vstep(1.5, 7.0), multi_origin) + +pattern = fill_pattern("METAL1_FILL2") +pattern.shape(8, 22, box(0.0, 0.0, 2.0, 2.0)) +pattern.dim(2.0, 2.0) +pattern.margin(metal1_dist, metal1_dist) + +to_fill = to_fill.fill_with_left(pattern, hstep(2.42, 0), vstep(0.65, 2.42), multi_origin) + +pattern = fill_pattern("METAL1_FILL3") +pattern.shape(8, 22, box(0.0, 0.0, 1.2, 1.2)) +pattern.dim(1.2, 1.2) +pattern.margin(metal1_dist, metal1_dist) + +to_fill = to_fill.fill_with_left(pattern, hstep(1.62, 0), vstep(0.3, 1.62), multi_origin) + diff --git a/testdata/drc/drcFullTest_1.oas b/testdata/drc/drcFullTest_1.oas new file mode 100644 index 000000000..57116b1d2 Binary files /dev/null and b/testdata/drc/drcFullTest_1.oas differ diff --git a/testdata/drc/drcFullTest_au1.oas b/testdata/drc/drcFullTest_au1.oas new file mode 100644 index 000000000..437274197 Binary files /dev/null and b/testdata/drc/drcFullTest_au1.oas differ diff --git a/testdata/drc/drcSimpleTests_40.drc b/testdata/drc/drcSimpleTests_40.drc index de7f810f1..2a20e4798 100644 --- a/testdata/drc/drcSimpleTests_40.drc +++ b/testdata/drc/drcSimpleTests_40.drc @@ -14,18 +14,22 @@ f2 = extent - l1.sized(1.0) p1 = fill_pattern("PAT1").shape(100, 0, box(0, 0, 1.um, 1.um)).origin(-0.5.um, -0.5.um) p2 = fill_pattern("PAT2").shape(100, 1, box(0, 0, 1.um, 1.um)).origin(-0.5.um, -0.5.um) p3 = fill_pattern("PAT3").shape(100, 2, box(0, 0, 1.um, 1.um)).shape(1000, 0, box(-0.5.um, -0.5.um, 1.5.um, 1.5.um)) +p4 = fill_pattern("PAT4").shape(100, 3, box(0, 0, 1.um, 1.um)).dim(1.um, 1.um).margin(2.um, 4.um) p11 = fill_pattern("PAT11").shape(101, 0, box(0, 0, 1.um, 1.um)).origin(-0.5.um, -0.5.um) p12 = fill_pattern("PAT12").shape(101, 1, box(0, 0, 1.um, 1.um)).origin(-0.5.um, -0.5.um) p13 = fill_pattern("PAT13").shape(101, 2, box(0, 0, 1.um, 1.um)).shape(1000, 0, box(-0.5.um, -0.5.um, 1.5.um, 1.5.um)) +p14 = fill_pattern("PAT14").shape(101, 3, box(0, 0, 1.um, 1.um)).dim(1.um, 1.um).margin(2.um, 4.um) f1.fill(p1, hstep(2.0, 1.0), vstep(-1.0, 2.0)) f1.fill(p2, hstep(2.0, 1.0), vstep(-1.0, 2.0), auto_origin) f1.fill(p3) +f1.fill(p4, hstep(2.0, 0), vstep(0, 2.0)) f2.fill(p11, hstep(2.0, 1.0), vstep(-1.0, 2.0)) f2.fill(p12, hstep(2.0, 1.0), vstep(-1.0, 2.0), auto_origin) f2.fill(p13) +f2.fill(p14, hstep(2.0, 0), vstep(0, 2.0)) l1.output(1, 0) f1.output(10, 0) diff --git a/testdata/drc/drcSimpleTests_42.drc b/testdata/drc/drcSimpleTests_42.drc index fa9bce1fb..2cc27c21e 100644 --- a/testdata/drc/drcSimpleTests_42.drc +++ b/testdata/drc/drcSimpleTests_42.drc @@ -11,8 +11,12 @@ l1 = input(1, 0) f1 = l1 p1 = fill_pattern("PAT1").shape(100, 0, box(0, 0, 1.um, 1.um)).origin(-0.5.um, -0.5.um) +p2 = fill_pattern("PAT1").shape(100, 1, box(0, 0, 1.um, 1.um)).dim(1.um, 1.um) +p3 = fill_pattern("PAT1").shape(100, 2, box(0, 0, 1.um, 1.um)).dim(1.um, 1.um).margin(1.um, 2.um) -f1.fill_with_left(p1, hstep(2.0, 1.0), vstep(-1.0, 2.0)).output(100, 0) +f1.fill_with_left(p1, hstep(2.0, 1.0), vstep(-1.0, 2.0)).output(101, 0) +f1.fill_with_left(p2, hstep(2.0, 1.0), vstep(-1.0, 2.0)).output(101, 1) +f1.fill_with_left(p3, hstep(2.0, 1.0), vstep(-1.0, 2.0)).output(101, 2) l1.output(1, 0) f1.output(10, 0) diff --git a/testdata/drc/drcSimpleTests_au40.gds b/testdata/drc/drcSimpleTests_au40.gds index 04a9f564c..862f21aa3 100644 Binary files a/testdata/drc/drcSimpleTests_au40.gds and b/testdata/drc/drcSimpleTests_au40.gds differ diff --git a/testdata/drc/drcSimpleTests_au42.gds b/testdata/drc/drcSimpleTests_au42.gds index 01f2a2f5a..0325c8c07 100644 Binary files a/testdata/drc/drcSimpleTests_au42.gds and b/testdata/drc/drcSimpleTests_au42.gds differ