From b725f5fb0f0e5bdac7e2c280cd69706991f0428b Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 29 Mar 2021 20:58:16 +0200 Subject: [PATCH] fill_with_left, implementation + tests --- src/drc/drc/built-in-macros/_drc_layer.rb | 78 ++++++++++++++++++---- src/drc/drc/built-in-macros/_drc_tags.rb | 9 ++- src/drc/unit_tests/drcSimpleTests.cc | 10 +++ src/gsi/gsi/gsiExpression.cc | 18 +++-- testdata/drc/drcSimpleTests_42.drc | 19 ++++++ testdata/drc/drcSimpleTests_42.gds | Bin 0 -> 1034 bytes testdata/drc/drcSimpleTests_43.drc | 21 ++++++ testdata/drc/drcSimpleTests_43.gds | Bin 0 -> 1034 bytes 8 files changed, 137 insertions(+), 18 deletions(-) create mode 100644 testdata/drc/drcSimpleTests_42.drc create mode 100644 testdata/drc/drcSimpleTests_42.gds create mode 100644 testdata/drc/drcSimpleTests_43.drc create mode 100644 testdata/drc/drcSimpleTests_43.gds diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index 3f0ecd7dc..8189edeb6 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -4302,13 +4302,38 @@ CODE # pattern = fill_pattern("FILL_CELL").shape(1, 0, box(0.0, 0.0, 1.0, 1.0)).origin(-0.5, -0.5) # to_fill.fill(pattern, hstep(2.0, 1.0), vstep(-1.0, 2.0), auto_origin) # @/code + # + # The fill function can only work with a target layout for output. + # It will not work for report output. + # + # The layers generated by the fill cells is only available for input later in the + # script if the output layout is identical to the input layouts. + # If you need the area missed by the fill function, try \fill_with_left. def fill(*args) + self._fill(false, *args) + end + + # %DRC% + # @name fill + # @brief Fills the region with regular pattern of shapes + # @synopsis layer.fill_with_left([ options ]) + # + # This method has the same call syntax and functionality than \fill. Other than this method + # it will return the area not covered by fill cells as a DRC layer. + + def fill_with_left(*args) + self._fill(true, *args) + end + + def _fill(with_left, *args) + + m = with_left ? "fill_with_left" : "fill" # generation of new cells not tested in deep mode - @deep && raise("fill command not supported in deep mode currently") + @deep && raise("#{m} command not supported in deep mode currently") - m = "fill" + (@engine._output_layout && @engine._output_cell) || raise("#{m} command needs an output layout and output cell") source = @engine.source row_step = nil @@ -4359,6 +4384,8 @@ CODE dbu_trans = RBA::VCplxTrans::new(1.0 / @engine.dbu) + result = nil + fill_cell = pattern.create_cell(@engine._output_layout, @engine) top_cell = @engine._output_cell ko = dbu_trans * pattern.cell_origin @@ -4379,6 +4406,13 @@ CODE tp.tile_border(bx, by) tp.threads = (@engine.threads || 1) + result_arg = "nil" + if with_left + result = RBA::Region::new + result_arg = "result" + tp.output(result_arg, result) + end + tp.input("region", self.data) tp.var("top_cell", top_cell) tp.var("ko", ko) @@ -4387,16 +4421,30 @@ CODE tp.var("origin", origin) tp.var("fc_index", fc_index) - tp.queue(<<"END") -var tc_box = _frame.bbox; -var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box; -!tile_box.empty && ( - 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) -) + if with_left + tp.queue(<<"END") + 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 & tc_box; + var left = Region.new; + (region & tile_box).fill(top_cell, fc_index, ko, rs, cs, origin, left, Vector.new, left, _tile.bbox); + _output(#{result_arg}, left) + ) END + else + tp.queue(<<"END") + var tc_box = _frame.bbox; + var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box; + !tile_box.empty && ( + 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) + ) +END + end begin @engine._output_layout.start_changes @@ -4409,14 +4457,20 @@ END else + if with_left + result = RBA::Region::new + end + @engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do - self.data.fill(top_cell, fc_index, ko, rs, cs, origin) + self.data.fill(top_cell, fc_index, ko, rs, cs, origin, result, RBA::Vector::new, result) end end self.data.disable_progress + return result ? DRCLayer::new(@engine, result) : nil + end # %DRC% diff --git a/src/drc/drc/built-in-macros/_drc_tags.rb b/src/drc/drc/built-in-macros/_drc_tags.rb index 2f31c1401..f6711fe40 100644 --- a/src/drc/drc/built-in-macros/_drc_tags.rb +++ b/src/drc/drc/built-in-macros/_drc_tags.rb @@ -187,7 +187,7 @@ module DRC def initialize(name) @cell_name = name @shapes = [] - @origin = RBA::DVector::new + @origin = nil end def create_cell(layout, engine) @@ -201,7 +201,12 @@ module DRC end def cell_origin - @origin + @origin || self._computed_origin + end + + def _computed_origin + b = self.bbox + return b.empty? ? RBA::DVector::new : (b.p1 - RBA::DPoint::new) end def bbox diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index 9e7bec8bd..632800289 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -1203,3 +1203,13 @@ TEST(41_fillTiled) run_test (_this, "41", false); } +TEST(42_fillWithLeft) +{ + run_test (_this, "42", false); +} + +TEST(43_fillWithLeftTiled) +{ + run_test (_this, "43", false); +} + diff --git a/src/gsi/gsi/gsiExpression.cc b/src/gsi/gsi/gsiExpression.cc index f27433a35..b844158a6 100644 --- a/src/gsi/gsi/gsiExpression.cc +++ b/src/gsi/gsi/gsiExpression.cc @@ -1504,9 +1504,14 @@ VariantUserClassImpl::execute_gsi (const tl::ExpressionParserContext & /*context tl::Heap heap; size_t narg = 0; for (gsi::MethodBase::argument_iterator a = meth->begin_arguments (); a != meth->end_arguments () && narg < args.size (); ++a, ++narg) { - // Note: this const_cast is ugly, but it will basically enable "out" parameters - // TODO: clean this up. - gsi::do_on_type () (a->type (), &arglist, const_cast (&args [narg]), *a, &heap); + try { + // Note: this const_cast is ugly, but it will basically enable "out" parameters + // TODO: clean this up. + gsi::do_on_type () (a->type (), &arglist, const_cast (&args [narg]), *a, &heap); + } catch (tl::Exception &ex) { + std::string msg = ex.msg () + tl::sprintf (tl::to_string (tr (" (argument '%s')")), a->spec ()->name ()); + throw tl::Exception (msg); + } } SerialArgs retlist (meth->retsize ()); @@ -1518,7 +1523,12 @@ VariantUserClassImpl::execute_gsi (const tl::ExpressionParserContext & /*context throw tl::Exception (tl::sprintf (tl::to_string (tr ("Iterators not supported yet (method %s, class %s)")), method.c_str (), mp_cls->name ())); } else { out = tl::Variant (); - gsi::do_on_type () (meth->ret_type ().type (), &out, &retlist, meth->ret_type (), &heap); + try { + gsi::do_on_type () (meth->ret_type ().type (), &out, &retlist, meth->ret_type (), &heap); + } catch (tl::Exception &ex) { + std::string msg = ex.msg () + tl::to_string (tr (" (return value)")); + throw tl::Exception (msg); + } } } diff --git a/testdata/drc/drcSimpleTests_42.drc b/testdata/drc/drcSimpleTests_42.drc new file mode 100644 index 000000000..fa9bce1fb --- /dev/null +++ b/testdata/drc/drcSimpleTests_42.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(-0.5.um, -0.5.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_42.gds b/testdata/drc/drcSimpleTests_42.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_43.drc b/testdata/drc/drcSimpleTests_43.drc new file mode 100644 index 000000000..732a68ed4 --- /dev/null +++ b/testdata/drc/drcSimpleTests_43.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(-0.5.um, -0.5.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_43.gds b/testdata/drc/drcSimpleTests_43.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