DRC support for fill, experimental

This commit is contained in:
Matthias Koefferlein 2021-03-29 13:28:43 +02:00
parent 94ffc0483e
commit 76982a3206
6 changed files with 211 additions and 26 deletions

View File

@ -101,6 +101,11 @@ struct box_defs
return std::hfunc (*box);
}
static const C &bbox (const C *box)
{
return *box;
}
static gsi::Methods methods ()
{
return
@ -172,6 +177,12 @@ struct box_defs
method ("p2=", &C::set_p2, gsi::arg ("p"),
"@brief Sets the upper right point of the box\n"
) +
method_ext ("bbox", &bbox,
"@brief Returns the bounding box\n"
"This method is provided for consistency of the shape API is returns the box itself.\n"
"\n"
"This method has been introduced in version 0.27."
) +
method_ext ("contains?", &box_defs<C>::contains, gsi::arg ("x"), gsi::arg ("y"),
"@brief Returns true if the box contains the given point\n"
"\n"

View File

@ -1298,21 +1298,21 @@ static void move_tree_shapes3 (db::Cell *cell, db::Cell &source_cell, const db::
static void
fill_region (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point *origin,
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
{
db::fill_region (cell, fr, fill_cell_index, fc_box, origin ? *origin : db::Point (), origin == 0 || !glue_box.empty (), remaining_parts, fill_margin, remaining_polygons, glue_box);
db::fill_region (cell, fr, fill_cell_index, fc_box, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box);
}
static void
fill_region_skew (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point *origin,
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
{
db::fill_region (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, origin ? *origin : db::Point (), origin == 0 || !glue_box.empty (), remaining_parts, fill_margin, remaining_polygons, glue_box);
db::fill_region (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box);
}
static void
fill_region_multi (db::Cell *cell, const db::Region &fr, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step,
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box)
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box)
{
db::fill_region_repeat (cell, fr, fill_cell_index, kernel_origin, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box);
}
@ -1846,7 +1846,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
) +
gsi::method_ext ("fill_region", &fill_region_skew, gsi::arg ("region"),
gsi::arg ("fill_cell_index"),
gsi::arg ("kernel_origin"),
gsi::arg ("fc_origin"),
gsi::arg ("row_step"),
gsi::arg ("column_step"),
gsi::arg ("origin", &default_origin, "(0, 0)"),
@ -1857,23 +1857,22 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"@brief Fills the given region with cells of the given type (skew step version)\n"
"@param region The region to fill\n"
"@param fill_cell_index The fill cell to place\n"
"@param kernel_origin The fill cell's footprint\n"
"@param row_step The fill cell's footprint\n"
"@param column_step The fill cell's footprint\n"
"@param fc_origin The location of the reference point of the fill cell\n"
"@param row_step The 'rows' step vector\n"
"@param column_step The 'columns' step vector\n"
"@param origin The global origin of the fill pattern or nil to allow local (per-polygon) optimization\n"
"@param remaining_parts See explanation in other version\n"
"@param fill_margin See explanation in other version\n"
"@param remaining_polygons See explanation in other version\n"
"\n"
"This version is similar to the version providing a rectangular fill kernel, but it offers a more generic, diamond-shaped kernel.\n"
"The kerne is defined by an origin and two vectors (row_step and column_step) which span the diamond.\n"
"This version will try to fit as many of these diamond-shaped kernels into the region to fill.\n"
"This version is similar to the version providing a rectangular fill kernel, but it offers more generic stepping of the fill cell.\n"
"The step pattern is defined by an origin and two vectors (row_step and column_step) which span the axes of the fill cell pattern.\n"
"\n"
"This variant has been introduced in version 0.27.\n"
) +
gsi::method_ext ("fill_region_multi", &fill_region_multi, gsi::arg ("region"),
gsi::arg ("fill_cell_index"),
gsi::arg ("kernel_origin"),
gsi::arg ("fc_origin"),
gsi::arg ("row_step"),
gsi::arg ("column_step"),
gsi::arg ("fill_margin", db::Vector ()),

View File

@ -32,6 +32,7 @@
#include "dbShapes.h"
#include "dbDeepShapeStore.h"
#include "dbRegion.h"
#include "dbFillTool.h"
#include "dbRegionProcessors.h"
#include "dbCompoundOperation.h"
#include "tlGlobPattern.h"
@ -675,6 +676,29 @@ tl::Variant complex_op (db::Region *region, db::CompoundRegionOperationNode *nod
}
}
static void
fill_region (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Box &fc_box, const db::Point *origin,
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
{
db::fill_region (cell, *fr, fill_cell_index, fc_box, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box);
}
static void
fill_region_skew (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step, const db::Point *origin,
db::Region *remaining_parts, const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Box &glue_box)
{
db::fill_region (cell, *fr, fill_cell_index, kernel_origin, row_step, column_step, origin ? *origin : db::Point (), origin == 0, remaining_parts, fill_margin, remaining_polygons, glue_box);
}
static void
fill_region_multi (const db::Region *fr, db::Cell *cell, db::cell_index_type fill_cell_index, const db::Vector &kernel_origin, const db::Vector &row_step, const db::Vector &column_step,
const db::Vector &fill_margin, db::Region *remaining_polygons, const db::Point &origin, const db::Box &glue_box)
{
db::fill_region_repeat (cell, *fr, fill_cell_index, kernel_origin, row_step, column_step, fill_margin, remaining_polygons, origin, glue_box);
}
static db::Point default_origin;
// provided by gsiDeclDbPolygon.cc:
int td_simple ();
int po_any ();
@ -2748,6 +2772,51 @@ Class<db::Region> decl_Region (decl_dbShapeCollection, "db", "Region",
"See \\base_verbosity= for details.\n"
"\n"
"This method has been introduced in version 0.26.\n"
) +
gsi::method_ext ("fill", &fill_region, gsi::arg ("in_cell"),
gsi::arg ("fill_cell_index"),
gsi::arg ("fc_box"),
gsi::arg ("origin", &default_origin, "(0, 0)"),
gsi::arg ("remaining_parts", (db::Region *)0, "nil"),
gsi::arg ("fill_margin", db::Vector ()),
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
gsi::arg ("glue_box", db::Box ()),
"@brief A mapping of \\Cell#fill_region to the Region class\n"
"\n"
"This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n"
"\n"
"This method has been introduced in version 0.27.\n"
) +
gsi::method_ext ("fill", &fill_region_skew, gsi::arg ("in_cell"),
gsi::arg ("fill_cell_index"),
gsi::arg ("fc_origin"),
gsi::arg ("row_step"),
gsi::arg ("column_step"),
gsi::arg ("origin", &default_origin, "(0, 0)"),
gsi::arg ("remaining_parts", (db::Region *)0, "nil"),
gsi::arg ("fill_margin", db::Vector ()),
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
gsi::arg ("glue_box", db::Box ()),
"@brief A mapping of \\Cell#fill_region to the Region class\n"
"\n"
"This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n"
"\n"
"This method has been introduced in version 0.27.\n"
) +
gsi::method_ext ("fill_multi", &fill_region_multi, gsi::arg ("in_cell"),
gsi::arg ("fill_cell_index"),
gsi::arg ("fc_origin"),
gsi::arg ("row_step"),
gsi::arg ("column_step"),
gsi::arg ("fill_margin", db::Vector ()),
gsi::arg ("remaining_polygons", (db::Region *)0, "nil"),
gsi::arg ("origin", db::Point ()),
gsi::arg ("glue_box", db::Box ()),
"@brief A mapping of \\Cell#fill_region to the Region class\n"
"\n"
"This method is equivalent to \\Cell#fill_region, but is based on Region (with the cell being the first parameter).\n"
"\n"
"This method has been introduced in version 0.27.\n"
),
"@brief A region (a potentially complex area consisting of multiple polygons)\n"
"\n\n"

View File

@ -211,16 +211,16 @@ module DRC
end
end
def fill_cell(name)
def fill_pattern(name)
DRCFillCell::new(name)
end
def hstep(x, y = nil)
DRCFillStep(true, x, y)
DRCFillStep::new(true, x, y)
end
def vstep(x, y = nil)
DRCFillStep(false, x, y)
DRCFillStep::new(false, x, y)
end
def auto_origin
@ -1967,7 +1967,7 @@ CODE
end
# disable progress again
if obj.is_a?(RBA::Region)
if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts)
obj.disable_progress
end
@ -2022,7 +2022,7 @@ CODE
end
# disable progress again
if obj.is_a?(RBA::Region)
if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts)
obj.disable_progress
end
@ -2065,7 +2065,7 @@ CODE
end
# disable progress again
if obj.is_a?(RBA::Region)
if obj.is_a?(RBA::Region) || obj.is_a?(RBA::Edges) || obj.is_a?(RBA::EdgePairs) || obj.is_a?(RBA::Texts)
obj.disable_progress
end
@ -2084,6 +2084,22 @@ CODE
obj.send(method, *args)
end
end
def _bx
@bx
end
def _by
@by
end
def _tx
@tx
end
def _ty
@ty
end
def _start

View File

@ -3898,6 +3898,9 @@ CODE
def fill(*args)
# generation of new cells not tested in deep mode
@deep && raise("fill command not supported in deep mode currently")
m = "fill"
source = @engine.source
@ -3922,12 +3925,12 @@ CODE
if row_step
raise("Duplicate hstep specification for '#{m}' at argument ##{ai+1}")
end
row_step = a
row_step = a.step
else
if column_step
raise("Duplicate vstep specification for '#{m}' at argument ##{ai+1}")
end
column_step = a
column_step = a.step
end
elsif a.is_a?(DRCFillOrigin)
origin = a.origin
@ -3937,7 +3940,7 @@ CODE
end
if !pattern
raise("No fill pattern given for '#{m}'")
raise("No fill pattern given for '#{m}' (use 'fill_pattern')")
end
if !row_step
@ -3947,7 +3950,64 @@ CODE
column_step = RBA::DVector::new(0, pattern.bbox.height)
end
dbu_trans = RBA::VCplxTrans::new(1.0 / @engine.dbu)
fill_cell = pattern.create_cell(source.layout)
top_cell = source.cell_obj
ko = dbu_trans * pattern.cell_origin
rs = dbu_trans * row_step
cs = dbu_trans * column_step
origin = origin ? dbu_trans * origin : nil
fc_index = fill_cell.cell_index
if @engine._tx && @engine._ty
tp = RBA::TilingProcessor::new
tp.dbu = @engine.dbu
tp.scale_to_dbu = false
tp.tile_size(@engine._tx, @engine._ty)
bx = [ @engine._bx || 0.0, row_step.x ].max
by = [ @engine._by || 0.0, column_step.y ].max
tp.tile_border(bx, by)
tp.threads = (@engine.threads || 1)
tp.input("region", self.data)
tp.var("top_cell", top_cell)
tp.var("ko", ko)
tp.var("rs", rs)
tp.var("cs", cs)
tp.var("origin", origin)
tp.var("fc_index", fc_index)
tp.queue(<<"END")
var tc_box = top_cell.bbox;
var tile_box = _tile ? (tc_box & _tile.bbox) : top_cell.bbox;
!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
begin
source.layout.start_changes
@engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do
tp.execute("Tiled \"#{m}\" in: #{@engine.src_line}")
end
ensure
source.layout.end_changes
end
else
@engine.run_timed("\"#{m}\" in: #{@engine.src_line}", self.data) do
self.data.fill(top_cell, fc_index, ko, rs, cs, origin)
end
end
self.data.disable_progress
end

View File

@ -190,6 +190,27 @@ module DRC
@origin = RBA::DVector::new
end
def create_cell(layout)
cell = layout.create_cell(@cell_name)
@shapes.each do |s|
li = layout.layer(s[0])
s[1].each { |t| cell.shapes(li).insert(t) }
end
cell
end
def cell_origin
@origin
end
def bbox
box = RBA::DBox::new
@shapes.each do |s|
s[1].each { |t| box += t.bbox }
end
box
end
def shape(*args)
layer = nil
@ -201,7 +222,6 @@ module DRC
if a.is_a?(1.class)
if !layer
layer = a
datatype = 0
elsif !datatype
datatype = a
else
@ -223,17 +243,24 @@ module DRC
if !shapes.empty?
li = RBA::LayerInfo::new
layer && li.layer = layer
datatype && li.datatype = datatype
name && li.name = name
if layer
li.layer = layer
li.datatype = datatype || 0
end
if name
li.name = name
end
@shapes << [ li, shapes ]
end
self
end
def origin(x, y)
if !x.is_a?(1.class) && !x.is_a?(1.0.class)
raise("x argument not numeric FillCell#origin")
end
@ -241,6 +268,9 @@ module DRC
raise("y argument not numeric FillCell#origin")
end
@origin = RBA::DVector::new(x, y)
self
end
end