mirror of https://github.com/KLayout/klayout.git
fill_with_left, implementation + tests
This commit is contained in:
parent
f0386b616a
commit
b725f5fb0f
|
|
@ -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)
|
# 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)
|
# to_fill.fill(pattern, hstep(2.0, 1.0), vstep(-1.0, 2.0), auto_origin)
|
||||||
# @/code
|
# @/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)
|
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
|
# 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
|
source = @engine.source
|
||||||
row_step = nil
|
row_step = nil
|
||||||
|
|
@ -4359,6 +4384,8 @@ CODE
|
||||||
|
|
||||||
dbu_trans = RBA::VCplxTrans::new(1.0 / @engine.dbu)
|
dbu_trans = RBA::VCplxTrans::new(1.0 / @engine.dbu)
|
||||||
|
|
||||||
|
result = nil
|
||||||
|
|
||||||
fill_cell = pattern.create_cell(@engine._output_layout, @engine)
|
fill_cell = pattern.create_cell(@engine._output_layout, @engine)
|
||||||
top_cell = @engine._output_cell
|
top_cell = @engine._output_cell
|
||||||
ko = dbu_trans * pattern.cell_origin
|
ko = dbu_trans * pattern.cell_origin
|
||||||
|
|
@ -4379,6 +4406,13 @@ CODE
|
||||||
tp.tile_border(bx, by)
|
tp.tile_border(bx, by)
|
||||||
tp.threads = (@engine.threads || 1)
|
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.input("region", self.data)
|
||||||
tp.var("top_cell", top_cell)
|
tp.var("top_cell", top_cell)
|
||||||
tp.var("ko", ko)
|
tp.var("ko", ko)
|
||||||
|
|
@ -4387,6 +4421,19 @@ CODE
|
||||||
tp.var("origin", origin)
|
tp.var("origin", origin)
|
||||||
tp.var("fc_index", fc_index)
|
tp.var("fc_index", fc_index)
|
||||||
|
|
||||||
|
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")
|
tp.queue(<<"END")
|
||||||
var tc_box = _frame.bbox;
|
var tc_box = _frame.bbox;
|
||||||
var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box;
|
var tile_box = _tile ? (tc_box & _tile.bbox) : tc_box;
|
||||||
|
|
@ -4397,6 +4444,7 @@ var tile_box = _tile ? (tc_box & _tile.bbox) : 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, ko, rs, cs, origin, nil, Vector.new, nil, _tile.bbox)
|
||||||
)
|
)
|
||||||
END
|
END
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@engine._output_layout.start_changes
|
@engine._output_layout.start_changes
|
||||||
|
|
@ -4409,14 +4457,20 @@ END
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
if with_left
|
||||||
|
result = RBA::Region::new
|
||||||
|
end
|
||||||
|
|
||||||
@engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do
|
@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
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
self.data.disable_progress
|
self.data.disable_progress
|
||||||
|
|
||||||
|
return result ? DRCLayer::new(@engine, result) : nil
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# %DRC%
|
# %DRC%
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ module DRC
|
||||||
def initialize(name)
|
def initialize(name)
|
||||||
@cell_name = name
|
@cell_name = name
|
||||||
@shapes = []
|
@shapes = []
|
||||||
@origin = RBA::DVector::new
|
@origin = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_cell(layout, engine)
|
def create_cell(layout, engine)
|
||||||
|
|
@ -201,7 +201,12 @@ module DRC
|
||||||
end
|
end
|
||||||
|
|
||||||
def cell_origin
|
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
|
end
|
||||||
|
|
||||||
def bbox
|
def bbox
|
||||||
|
|
|
||||||
|
|
@ -1203,3 +1203,13 @@ TEST(41_fillTiled)
|
||||||
run_test (_this, "41", false);
|
run_test (_this, "41", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(42_fillWithLeft)
|
||||||
|
{
|
||||||
|
run_test (_this, "42", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(43_fillWithLeftTiled)
|
||||||
|
{
|
||||||
|
run_test (_this, "43", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1504,9 +1504,14 @@ VariantUserClassImpl::execute_gsi (const tl::ExpressionParserContext & /*context
|
||||||
tl::Heap heap;
|
tl::Heap heap;
|
||||||
size_t narg = 0;
|
size_t narg = 0;
|
||||||
for (gsi::MethodBase::argument_iterator a = meth->begin_arguments (); a != meth->end_arguments () && narg < args.size (); ++a, ++narg) {
|
for (gsi::MethodBase::argument_iterator a = meth->begin_arguments (); a != meth->end_arguments () && narg < args.size (); ++a, ++narg) {
|
||||||
|
try {
|
||||||
// Note: this const_cast is ugly, but it will basically enable "out" parameters
|
// Note: this const_cast is ugly, but it will basically enable "out" parameters
|
||||||
// TODO: clean this up.
|
// TODO: clean this up.
|
||||||
gsi::do_on_type<writer> () (a->type (), &arglist, const_cast<tl::Variant *> (&args [narg]), *a, &heap);
|
gsi::do_on_type<writer> () (a->type (), &arglist, const_cast<tl::Variant *> (&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 ());
|
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 ()));
|
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Iterators not supported yet (method %s, class %s)")), method.c_str (), mp_cls->name ()));
|
||||||
} else {
|
} else {
|
||||||
out = tl::Variant ();
|
out = tl::Variant ();
|
||||||
|
try {
|
||||||
gsi::do_on_type<reader> () (meth->ret_type ().type (), &out, &retlist, meth->ret_type (), &heap);
|
gsi::do_on_type<reader> () (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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
Binary file not shown.
|
|
@ -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)
|
||||||
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue