From 47a845884ddc49675369c0f2bee12bf03fa3553c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 29 Mar 2021 22:44:39 +0200 Subject: [PATCH] Added tests --- src/db/db/dbFillTool.cc | 2 +- src/drc/drc/built-in-macros/_drc_layer.rb | 28 ++++++++++++++++------ src/drc/drc/built-in-macros/_drc_tags.rb | 23 +++++++++++++++--- src/drc/unit_tests/drcSimpleTests.cc | 9 +++++++ testdata/drc/drcSimpleTests_44.drc | 19 +++++++++++++++ testdata/drc/drcSimpleTests_44.gds | Bin 0 -> 1034 bytes testdata/drc/drcSimpleTests_45.drc | 21 ++++++++++++++++ testdata/drc/drcSimpleTests_45.gds | Bin 0 -> 1034 bytes testdata/drc/drcSimpleTests_au44.gds | Bin 0 -> 10234 bytes testdata/drc/drcSimpleTests_au45.gds | Bin 0 -> 27202 bytes 10 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 testdata/drc/drcSimpleTests_44.drc create mode 100644 testdata/drc/drcSimpleTests_44.gds create mode 100644 testdata/drc/drcSimpleTests_45.drc create mode 100644 testdata/drc/drcSimpleTests_45.gds create mode 100644 testdata/drc/drcSimpleTests_au44.gds create mode 100644 testdata/drc/drcSimpleTests_au45.gds diff --git a/src/db/db/dbFillTool.cc b/src/db/db/dbFillTool.cc index d6d216d2b..855be54b5 100644 --- a/src/db/db/dbFillTool.cc +++ b/src/db/db/dbFillTool.cc @@ -140,7 +140,7 @@ public: db::Vector dr = m_row_step * long ((rows_per_columns > 0 ? -(ir + 1) : ir) + m_row_steps); db::Vector dc = m_column_step * long ((columns_per_rows > 0 ? -(ic + 1) : ic) + m_column_steps); - am.reinitialize (db::Point (fp_left, fp_bottom) + dr + dc, db::Vector (ddx, ddy), db::Vector (dx, dy), nx, ny); + am.reinitialize (db::Point (fp_left, fp_bottom) + dr + dc, db::Vector (ddx, ddy), m_dim, nx, ny); if (db::rasterize (fp, am)) { m_area_maps.push_back (db::AreaMap ()); diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index 8189edeb6..025546f31 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -4286,7 +4286,21 @@ CODE # @/code # # Without a reference point given, the lower left corner of the fill pattern's bounding box will be used - # as the reference point. + # as the reference point. The reference point will also defined the footprint of the fill cell - more precisely + # the lower left corner. The fill cell's foot print is taken to be a rectangle having the horizontal and vertical + # step pitch for width and height respectively. The dimension can be changed however so that the fill cells + # can overlap or there can be spacing between the cells. To change the dimensions use the "dim" method. + # + # 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 + # step pitch: + # + # @code + # p = fill_pattern("FILL_CELL") + # p.shape(1, 0, box(0.0, 0.0, 1.0, 1.0)) + # p.origin(-0.5, -0.5) + # p.dim(2.0, 2.0) + # @/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: @@ -4388,7 +4402,7 @@ CODE fill_cell = pattern.create_cell(@engine._output_layout, @engine) top_cell = @engine._output_cell - ko = dbu_trans * pattern.cell_origin + fc_box = dbu_trans * pattern.cell_box(row_step.x, column_step.y) rs = dbu_trans * row_step cs = dbu_trans * column_step origin = origin ? dbu_trans * origin : nil @@ -4415,7 +4429,7 @@ CODE tp.input("region", self.data) tp.var("top_cell", top_cell) - tp.var("ko", ko) + tp.var("fc_box", fc_box) tp.var("rs", rs) tp.var("cs", cs) tp.var("origin", origin) @@ -4426,10 +4440,10 @@ CODE var tc_box = _frame.bbox; var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box; !tile_box.empty && ( - tile_box = tile_box.enlarged(Vector.new(rs.x, cs.y)); + tile_box = tile_box.enlarged(Vector.new(max(rs.x, fc_box.width), max(cs.y, fc_box.height))); tile_box = tile_box & tc_box; var left = Region.new; - (region & tile_box).fill(top_cell, fc_index, ko, rs, cs, origin, left, Vector.new, left, _tile.bbox); + (region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, left, Vector.new, left, _tile.bbox); _output(#{result_arg}, left) ) END @@ -4441,7 +4455,7 @@ END tile_box.right = tile_box.right + rs.x - 1; tile_box.top = tile_box.top + cs.y - 1; tile_box = tile_box & tc_box; - (region & tile_box).fill(top_cell, fc_index, ko, rs, cs, origin, nil, Vector.new, nil, _tile.bbox) + (region & tile_box).fill(top_cell, fc_index, fc_box, rs, cs, origin, nil, Vector.new, nil, _tile.bbox) ) END end @@ -4462,7 +4476,7 @@ END end @engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do - self.data.fill(top_cell, fc_index, ko, rs, cs, origin, result, RBA::Vector::new, result) + self.data.fill(top_cell, fc_index, fc_box, rs, cs, origin, result, RBA::Vector::new, 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 f6711fe40..964172d85 100644 --- a/src/drc/drc/built-in-macros/_drc_tags.rb +++ b/src/drc/drc/built-in-macros/_drc_tags.rb @@ -188,6 +188,7 @@ module DRC @cell_name = name @shapes = [] @origin = nil + @dim = nil end def create_cell(layout, engine) @@ -200,13 +201,15 @@ module DRC cell end - def cell_origin - @origin || self._computed_origin + 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) end def _computed_origin b = self.bbox - return b.empty? ? RBA::DVector::new : (b.p1 - RBA::DPoint::new) + return b.empty? ? RBA::DPoint::new : b.p1 end def bbox @@ -279,6 +282,20 @@ module DRC end + def dim(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 + @dim = RBA::DVector::new(w, h) + + self + + end + end # A wrapper for the fill step definition diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index 632800289..36b46732a 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -1213,3 +1213,12 @@ TEST(43_fillWithLeftTiled) run_test (_this, "43", false); } +TEST(44_fillWithOverlappingBoxes) +{ + run_test (_this, "44", false); +} + +TEST(45_fillWithOverlappingBoxesTiled) +{ + run_test (_this, "45", false); +} diff --git a/testdata/drc/drcSimpleTests_44.drc b/testdata/drc/drcSimpleTests_44.drc new file mode 100644 index 000000000..34d4e997a --- /dev/null +++ b/testdata/drc/drcSimpleTests_44.drc @@ -0,0 +1,19 @@ + +source $drc_test_source +target $drc_test_target + +if $drc_test_deep + deep +end + +l1 = input(1, 0) + +f1 = l1 + +p1 = fill_pattern("PAT1").shape(100, 0, box(0, 0, 1.um, 1.um)).origin(-1.um, -1.um).dim(3.um, 3.um) + +f1.fill_with_left(p1, hstep(2.0, 1.0), vstep(-1.0, 2.0)).output(100, 0) + +l1.output(1, 0) +f1.output(10, 0) + diff --git a/testdata/drc/drcSimpleTests_44.gds b/testdata/drc/drcSimpleTests_44.gds new file mode 100644 index 0000000000000000000000000000000000000000..e9e05712b8d946a42dfe312ab50be1bf52c31332 GIT binary patch literal 1034 zcmaLVPe@cz6vy%JdGmbQBGVjq6NI2aNKp~yCNOLv83~!yw26>#71&CGiZ(&32o3Cy z(JqJ}h$u;jh!`rcR!R`Gs$HPaDiZOWd*{rwnCDx}XSlz24v%vW8A)=6k|fQ)D6oSf zUF`b*KP^c%Jahz#g{H#;xB8A%o~-r{&hLHvpgc;cX_LAv8$B@sX$xdq6NIca0fyTO z`U^6-5`8!im0rZ1X@-xjh&%Nq=C0SNX?srp&polfseR?-T;1t&$f@gyJJl6)*ZNoM z^ZHB24_G=t@ZWai;B9c1pCdc(fx9$@baw0eZnaM9bNdh7h_f-J4;lPjxBEVFaSmL| z$KS-<)JLlIdHvbF4rj{*udc%JL*QQf0~43Qwew5oV{Uq#+Nl3CyWf{3c%k=bzB;X5 zs43+~@cJEY$QN$LTn*=Mf7T57`=>EiLtfcZGvuGX##{~g;+~ozU%VT0)4xk?^!;H! zZ65mu;#~G0jdOCxzQ=jEc5d@>y-v;RFWZW7e}cLf>7BSA=JFL->8NXa)%GFomuY)f ft#8!7*XBR727mRg%=K?D+f&!i)lje3l%{L|FIm3{ literal 0 HcmV?d00001 diff --git a/testdata/drc/drcSimpleTests_45.drc b/testdata/drc/drcSimpleTests_45.drc new file mode 100644 index 000000000..910f0c971 --- /dev/null +++ b/testdata/drc/drcSimpleTests_45.drc @@ -0,0 +1,21 @@ + +source $drc_test_source +target $drc_test_target + +if $drc_test_deep + deep +end + +tiles(5, 5) + +l1 = input(1, 0) + +f1 = l1 + +p1 = fill_pattern("PAT1").shape(100, 0, box(0, 0, 1.um, 1.um)).origin(-1.um, -1.um).dim(3.um, 3.um) + +f1.fill_with_left(p1, hstep(2.0, 1.0), vstep(-1.0, 2.0)).output(100, 0) + +l1.output(1, 0) +f1.output(10, 0) + diff --git a/testdata/drc/drcSimpleTests_45.gds b/testdata/drc/drcSimpleTests_45.gds new file mode 100644 index 0000000000000000000000000000000000000000..e9e05712b8d946a42dfe312ab50be1bf52c31332 GIT binary patch literal 1034 zcmaLVPe@cz6vy%JdGmbQBGVjq6NI2aNKp~yCNOLv83~!yw26>#71&CGiZ(&32o3Cy z(JqJ}h$u;jh!`rcR!R`Gs$HPaDiZOWd*{rwnCDx}XSlz24v%vW8A)=6k|fQ)D6oSf zUF`b*KP^c%Jahz#g{H#;xB8A%o~-r{&hLHvpgc;cX_LAv8$B@sX$xdq6NIca0fyTO z`U^6-5`8!im0rZ1X@-xjh&%Nq=C0SNX?srp&polfseR?-T;1t&$f@gyJJl6)*ZNoM z^ZHB24_G=t@ZWai;B9c1pCdc(fx9$@baw0eZnaM9bNdh7h_f-J4;lPjxBEVFaSmL| z$KS-<)JLlIdHvbF4rj{*udc%JL*QQf0~43Qwew5oV{Uq#+Nl3CyWf{3c%k=bzB;X5 zs43+~@cJEY$QN$LTn*=Mf7T57`=>EiLtfcZGvuGX##{~g;+~ozU%VT0)4xk?^!;H! zZ65mu;#~G0jdOCxzQ=jEc5d@>y-v;RFWZW7e}cLf>7BSA=JFL->8NXa)%GFomuY)f ft#8!7*XBR727mRg%=K?D+f&!i)lje3l%{L|FIm3{ literal 0 HcmV?d00001 diff --git a/testdata/drc/drcSimpleTests_au44.gds b/testdata/drc/drcSimpleTests_au44.gds new file mode 100644 index 0000000000000000000000000000000000000000..f47f36f1824e5f8eb51bc7d4071995a9fbe68124 GIT binary patch literal 10234 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 literal 0 HcmV?d00001