Enabled deep mode for DRC

This commit is contained in:
Matthias Koefferlein 2019-02-17 23:21:23 +01:00
parent 311318c578
commit b91edbabde
19 changed files with 291 additions and 37 deletions

View File

@ -284,5 +284,17 @@ AsIfFlatEdgePairs::insert_into (Layout *layout, db::cell_index_type into_cell, u
}
}
void
AsIfFlatEdgePairs::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
{
// improves performance when inserting an original layout into the same layout
db::LayoutLocker locker (layout);
db::Shapes &shapes = layout->cell (into_cell).shapes (into_layer);
for (EdgePairsIterator e (begin ()); ! e.at_end (); ++e) {
shapes.insert (e->to_simple_polygon (enl));
}
}
}

View File

@ -69,6 +69,7 @@ public:
virtual bool less (const EdgePairs &other) const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
protected:
void update_bbox (const db::Box &box);

View File

@ -327,4 +327,10 @@ void DeepEdgePairs::insert_into (Layout *layout, db::cell_index_type into_cell,
m_deep_layer.insert_into (layout, into_cell, into_layer);
}
void DeepEdgePairs::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
{
m_deep_layer.insert_into_as_polygons (layout, into_cell, into_layer, enl);
}
}

View File

@ -78,6 +78,7 @@ public:
virtual bool less (const EdgePairs &other) const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
const DeepLayer &deep_layer () const
{

View File

@ -146,6 +146,13 @@ DeepLayer::insert_into (db::Layout *into_layout, db::cell_index_type into_cell,
const_cast<db::DeepShapeStore *> (mp_store.get ())->insert (*this, into_layout, into_cell, into_layer);
}
void
DeepLayer::insert_into_as_polygons (db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
{
check_dss ();
const_cast<db::DeepShapeStore *> (mp_store.get ())->insert_as_polygons (*this, into_layout, into_cell, into_layer, enl);
}
bool DeepLayer::operator< (const DeepLayer &other) const
{
if (mp_store.get () != other.mp_store.get ()) {
@ -596,5 +603,38 @@ DeepShapeStore::insert (const DeepLayer &deep_layer, db::Layout *into_layout, db
db::copy_shapes (*into_layout, source_layout, trans, source_cells, cm.table (), lm);
}
void
DeepShapeStore::insert_as_polygons (const DeepLayer &deep_layer, db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl)
{
// prepare a temporary layer with the polygons
DeepLayer tmp = deep_layer.derived ();
db::Layout &layout = const_cast<db::Layout &> (deep_layer.layout ());
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
db::Shapes &out = c->shapes (tmp.layer ());
for (db::Shapes::shape_iterator s = c->shapes (deep_layer.layer ()); ! s.at_end (); ++s) {
if (s->is_edge_pair ()) {
out.insert (s->edge_pair ().to_simple_polygon (enl));
} else if (s->is_path () || s->is_polygon () || s->is_box ()) {
db::Polygon poly;
s->polygon (poly);
out.insert (poly);
}
}
}
// and insert this one
insert (tmp, into_layout, into_cell, into_layer);
}
}

View File

@ -136,6 +136,12 @@ public:
*/
void insert_into (Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) const;
/**
* @brief Inserts the edge pairs layer into the given layout, starting from the given cell and into the given layer
* The edge pairs are converted to polygons with the given enlargement.
*/
void insert_into_as_polygons (db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
/**
* @brief Creates a derived new deep layer
* Derived layers use the same layout and context, but are initially
@ -280,6 +286,13 @@ public:
*/
void insert (const DeepLayer &layer, db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer);
/**
* @brief Inserts the deep layer's edge pairs into some target layout
*
* The edge pairs are converted to polygons with the given enlargement.
*/
void insert_as_polygons (const DeepLayer &deep_layer, db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl);
/**
* @brief Gets the cell mapping suitable to returning a layout from the deep shape store into the original layout hierarchy
*

View File

@ -662,6 +662,16 @@ public:
return mp_delegate->insert_into (layout, into_cell, into_layer);
}
/**
* @brief Inserts the edge pair collection into the given layout, cell and layer as polygons with the given enlargement
* If the edge pair collection is a hierarchical region, the hierarchy is copied into the
* layout's hierarchy.
*/
void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
{
return mp_delegate->insert_into_as_polygons (layout, into_cell, into_layer, enl);
}
private:
EdgePairsDelegate *mp_delegate;

View File

@ -110,6 +110,7 @@ public:
virtual bool less (const EdgePairs &other) const = 0;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const = 0;
virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const = 0;
protected:
const std::string &progress_desc () const

View File

@ -75,6 +75,7 @@ public:
virtual bool less (const EdgePairs &other) const;
virtual void insert_into (Layout *, db::cell_index_type, unsigned int) const { }
virtual void insert_into_as_polygons (Layout *, db::cell_index_type, unsigned int, db::Coord) const { }
private:
EmptyEdgePairs &operator= (const EmptyEdgePairs &other);

View File

@ -180,6 +180,15 @@ const db::RecursiveShapeIterator *FlatEdgePairs::iter () const
return 0;
}
void
FlatEdgePairs::insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const
{
db::Shapes &out = layout->cell (into_cell).shapes (into_layer);
for (EdgePairsIterator p (begin ()); ! p.at_end (); ++p) {
out.insert (p->to_simple_polygon (enl));
}
}
void
FlatEdgePairs::insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const
{

View File

@ -114,6 +114,7 @@ public:
virtual const db::RecursiveShapeIterator *iter () const;
virtual void insert_into (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer) const;
virtual void insert_into_as_polygons (Layout *layout, db::cell_index_type into_cell, unsigned int into_layer, db::Coord enl) const;
void insert (const db::EdgePair &edge_pair);
void insert (const db::Shape &shape);

View File

@ -26,6 +26,7 @@
#include "dbEdgePairs.h"
#include "dbEdges.h"
#include "dbRegion.h"
#include "dbDeepEdgePairs.h"
namespace gsi
{
@ -158,6 +159,11 @@ static void insert_e (db::EdgePairs *e, const db::EdgePairs &a)
}
}
static bool is_deep (const db::EdgePairs *ep)
{
return dynamic_cast<const db::DeepEdgePairs *> (ep->delegate ()) != 0;
}
Class<db::EdgePairs> decl_EdgePairs ("db", "EdgePairs",
constructor ("new", &new_v,
"@brief Default constructor\n"
@ -225,6 +231,22 @@ Class<db::EdgePairs> decl_EdgePairs ("db", "EdgePairs",
"\n"
"This constructor has been introduced in version 0.26."
) +
method ("insert_into", &db::EdgePairs::insert_into, gsi::arg ("layout"), gsi::arg ("cell_index"), gsi::arg ("layer"),
"@brief Inserts this edge pairs into the given layout, below the given cell and into the given layer.\n"
"If the edge pair collection is a hierarchical one, a suitable hierarchy will be built below the top cell or "
"and existing hierarchy will be reused.\n"
"\n"
"This method has been introduced in version 0.26."
) +
method ("insert_into_as_polygons", &db::EdgePairs::insert_into_as_polygons, gsi::arg ("layout"), gsi::arg ("cell_index"), gsi::arg ("layer"), gsi::arg ("e"),
"@brief Inserts this edge pairs into the given layout, below the given cell and into the given layer.\n"
"If the edge pair collection is a hierarchical one, a suitable hierarchy will be built below the top cell or "
"and existing hierarchy will be reused.\n"
"\n"
"The edge pairs will be converted to polygons with the enlargement value given be 'e'.\n"
"\n"
"This method has been introduced in version 0.26."
) +
method ("insert", (void (db::EdgePairs::*) (const db::Edge &, const db::Edge &)) &db::EdgePairs::insert,
"@brief Inserts an edge pair into the collection\n"
"@args first, second\n"
@ -233,6 +255,11 @@ Class<db::EdgePairs> decl_EdgePairs ("db", "EdgePairs",
"@brief Inserts an edge pair into the collection\n"
"@args edge_pair\n"
) +
method_ext ("is_deep?", &is_deep,
"@brief Returns true if the edge pair collection is a deep (hierarchical) one\n"
"\n"
"This method has been added in version 0.26."
) +
method ("+", &db::EdgePairs::operator+,
"@brief Returns the combined edge pair collection of self and the other one\n"
"\n"

View File

@ -25,6 +25,7 @@
#include "dbDeepShapeStore.h"
#include "dbEdges.h"
#include "dbDeepEdges.h"
#include "dbRegion.h"
#include "dbLayoutUtils.h"
@ -373,6 +374,11 @@ static void insert_s (db::Edges *e, const db::Shapes &a)
insert_st (e, a, db::UnitTrans ());
}
static bool is_deep (const db::Edges *e)
{
return dynamic_cast<const db::DeepEdges *> (e->delegate ()) != 0;
}
Class<db::Edges> dec_Edges ("db", "Edges",
constructor ("new", &new_v,
"@brief Default constructor\n"
@ -495,6 +501,13 @@ Class<db::Edges> dec_Edges ("db", "Edges",
"r = RBA::Edges::new(layout.begin_shapes(cell, layer), dss, RBA::ICplxTrans::new(layout.dbu / dbu), false)\n"
"@/code\n"
) +
method ("insert_into", &db::Edges::insert_into, gsi::arg ("layout"), gsi::arg ("cell_index"), gsi::arg ("layer"),
"@brief Inserts this edge collection into the given layout, below the given cell and into the given layer.\n"
"If the edge collection is a hierarchical one, a suitable hierarchy will be built below the top cell or "
"and existing hierarchy will be reused.\n"
"\n"
"This method has been introduced in version 0.26."
) +
method_ext ("with_length", with_length1, gsi::arg ("length"), gsi::arg ("inverse"),
"@brief Filter the edges by length\n"
"Filters the edges in the edge collection by length. If \"inverse\" is false, only "
@ -1377,6 +1390,11 @@ Class<db::Edges> dec_Edges ("db", "Edges",
"This method returns all edges in self which can not be found in the other edge collection with exactly the same "
"geometry."
) +
method_ext ("is_deep?", &is_deep,
"@brief Returns true if the edge collection is a deep (hierarchical) one\n"
"\n"
"This method has been added in version 0.26."
) +
method ("is_merged?", &db::Edges::is_merged,
"@brief Returns true if the edge collection is merged\n"
"If the region is merged, coincident edges have been merged into single edges. You can ensure merged state "

View File

@ -23,6 +23,7 @@
#include "gsiDecl.h"
#include "dbRegion.h"
#include "dbDeepRegion.h"
#include "dbPolygonTools.h"
#include "dbLayoutUtils.h"
#include "dbShapes.h"
@ -715,6 +716,11 @@ static Container *decompose_trapezoids (const db::Region *r, int mode)
return shapes.release ();
}
static bool is_deep (const db::Region *region)
{
return dynamic_cast<const db::DeepRegion *> (region->delegate ()) != 0;
}
// provided by gsiDeclDbPolygon.cc:
int td_simple ();
int po_any ();
@ -832,6 +838,13 @@ Class<db::Region> decl_Region ("db", "Region",
"\n"
"This method has been introduced in version 0.25."
) +
method ("insert_into", &db::Region::insert_into, gsi::arg ("layout"), gsi::arg ("cell_index"), gsi::arg ("layer"),
"@brief Inserts this region into the given layout, below the given cell and into the given layer.\n"
"If the region is a hierarchical one, a suitable hierarchy will be built below the top cell or "
"and existing hierarchy will be reused.\n"
"\n"
"This method has been introduced in version 0.26."
) +
factory_ext ("texts", &texts<BoxDelivery>, gsi::arg ("expr", std::string ("*")), gsi::arg ("as_pattern", true),
"@hide\n"
"This method is provided for DRC implementation only."
@ -2316,6 +2329,11 @@ Class<db::Region> decl_Region ("db", "Region",
"@brief Return the bounding box of the region\n"
"The bounding box is the box enclosing all points of all polygons.\n"
) +
method_ext ("is_deep?", &is_deep,
"@brief Returns true if the region is a deep (hierarchical) one\n"
"\n"
"This method has been added in version 0.26."
) +
method ("is_merged?", &db::Region::is_merged,
"@brief Returns true if the region is merged\n"
"If the region is merged, polygons will not touch or overlap. You can ensure merged state "

View File

@ -2280,6 +2280,15 @@ CODE
@data.is_a?(RBA::EdgePairs)
end
# %DRC%
# @name is_deep?
# @brief Returns true, if the layer is a deep (hierarchical) layer
# @synopsis layer.is_deep?
def is_deep?
@data.is_deep?
end
# %DRC%
# @name area
# @brief Returns the total area of the polygons in the region
@ -2347,6 +2356,20 @@ CODE
@engine._cmd(@data, :length) * @engine.dbu.to_f
end
# %DRC%
# @name flatten
# @brief Flattens the layer
# @synopsis layer.flatten
#
# If the layer already is a flat one, this method does nothing.
# If the layer is a hierarchical layer (an original layer or
# a derived layer in deep mode), this method will convert it
# to a flat collection of polygons, edges or edge pairs.
def flatten
@engine._cmd(@data, :flatten)
end
# %DRC%
# @name is_merged?
# @brief Returns true, if the polygons of the layer are merged
@ -3596,13 +3619,15 @@ CODE
@output_layout = nil
@output_rdb = nil
@output_rdb_file = nil
@output_rdb_cell_id = nil
@output_rdb_cell = nil
@used_output_layers = {}
@output_layers = []
@vnum = 1
@layout_sources = {}
@lnum = 1
@log_file = nil
@dss = nil
@deep = false
@verbose = false
@ -3821,11 +3846,14 @@ CODE
#
# In tiling mode, the memory requirements are usually smaller (depending on the
# choice of the tile size) and multi-CPU support is enabled (see \threads).
# To disable tiling mode use \flat.
# To disable tiling mode use \flat or \deep.
#
# Tiling mode will disable deep mode (see \deep).
def tiles(tx, ty = nil)
@tx = tx.to_f
@ty = (ty || tx).to_f
@deep = false
end
# %DRC%
@ -3837,6 +3865,38 @@ CODE
@tx != nil
end
# %DRC%
# @name deep
# @brief Enters deep (hierarchical) mode
# @synopsis deep
#
# In deep mode, the operations will be performed in a hierarchical fashion.
# Sometimes this reduces the time and memory required for an operation, but this
# will also add some overhead for the hierarchical analysis.
#
# "deepness" is a property of layers. Layers created with "input" while in
# deep mode carry hierarchy. Operations involving such layers at the only
# or the first argument are carried out in hierarchical mode.
#
# Hierarchical mode has some more implications, like "merged_semantics" being
# implied always. Sometimes cell variants will be created.
#
# Deep mode can be cancelled with \tiles or \flat.
def deep
@deep = true
@tx = @ty = nil
end
# %DRC%
# @name is_deep?
# @brief Returns true, if in deep mode
# @synopsis is_deep?
def is_deep?
@deep
end
# %DRC%
# @name tile_borders
# @brief Specifies a minimum tile border
@ -3878,6 +3938,7 @@ CODE
def flat
@tx = @ty = nil
@deep = false
end
# %DRC%
@ -4131,7 +4192,7 @@ CODE
cn || raise("No cell name specified - either the source was not specified before 'report' or there is no default source. In the latter case, specify a cell name as the third parameter of 'report'")
@output_rdb_cell_id = @output_rdb.create_cell(cn).rdb_id
@output_rdb_cell = @output_rdb.create_cell(cn)
@output_rdb.generator = $0
@output_rdb.top_cell_name = cn
@output_rdb.description = description
@ -4153,15 +4214,15 @@ CODE
if @output_rdb
cell_id = nil
cell = nil
@output_rdb.each_cell do |c|
if c.name == cellname
cell_id = c.rdb_id
cell = c
end
end
cell_id ||= @output_rdb.create_cell(cellname).rdb_id
@output_rdb_cell_id = cell_id
cell ||= @output_rdb.create_cell(cellname)
@output_rdb_cell = cell
else
@ -4716,7 +4777,13 @@ CODE
sf = layout.dbu / self.dbu
if (sf - 1.0).abs &gt; 1e-6
if @deep
raise("DBU scaling (" + ("%.12g" % layout.dbu) + " to " + ("%.12g" % self.dbu) + ") is not supported in deep mode currently")
end
r = RBA::Region::new(iter, RBA::ICplxTrans::new(sf.to_f))
elsif @deep
@dss ||= RBA::DeepShapeStore::new
r = RBA::Region::new(iter, @dss)
else
r = RBA::Region::new(iter)
end
@ -4750,9 +4817,9 @@ CODE
args[1] &amp;&amp; cat.description = args[1]
if data.is_a?(RBA::RecursiveShapeIterator)
@output_rdb.create_items(@output_rdb_cell_id, cat.rdb_id, data)
cat.scan_shapes(data)
else
@output_rdb.create_items(@output_rdb_cell_id, cat.rdb_id, RBA::CplxTrans::new(self.dbu), data)
cat.scan_collection(@output_rdb_cell, RBA::CplxTrans::new(self.dbu), data)
end
else
@ -4793,40 +4860,59 @@ CODE
li = output.insert_layer(info)
end
tmp = li
# make sure the output has the right database unit
output.dbu = self.dbu
begin
if data.is_deep?
# mark the layer as used
if !@used_output_layers[li]
@output_layers.push(li)
# Note: to avoid issues with output onto the input layer, we
# output to a temp layer and later swap both. The simple implementation
# did a clear here and the effect of that was that the data potentially
# got invalidated.
tmp = output.insert_layer(RBA::LayerInfo::new)
@used_output_layers[li] = true
end
# make sure the output has the right database unit
output.dbu = self.dbu
# insert the data into the output layer
if data.is_a?(RBA::EdgePairs)
output_cell.shapes(tmp).insert_as_polygons(data, 1)
data.insert_into_as_polygons(output, output_cell.cell_index, li, 1)
else
output_cell.shapes(tmp).insert(data)
data.insert_into(output, output_cell.cell_index, li)
end
# make the temp layer the output layer
if tmp != li
output.swap_layers(tmp, li)
else
tmp = li
begin
if !@used_output_layers[li]
@output_layers.push(li)
# Note: to avoid issues with output onto the input layer, we
# output to a temp layer and later swap both. The simple implementation
# did a clear here and the effect of that was that the data potentially
# got invalidated.
tmp = output.insert_layer(RBA::LayerInfo::new)
@used_output_layers[li] = true
end
# insert the data into the output layer
if data.is_a?(RBA::EdgePairs)
output_cell.shapes(tmp).insert_as_polygons(data, 1)
else
output_cell.shapes(tmp).insert(data)
end
# make the temp layer the output layer
if tmp != li
output.swap_layers(tmp, li)
end
ensure
# clean up the original layer if requested
if tmp != li
output.delete_layer(tmp)
end
end
ensure
# clean up the original layer if requested
if tmp != li
output.delete_layer(tmp)
end
end
end

View File

@ -317,7 +317,7 @@ Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
"\n"
"This method has been introduced in version 0.23. The flat mode argument has been added in version 0.26.\n"
) +
gsi::method_ext ("scan_region", &scan_region, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("region"), gsi::arg ("flat", false),
gsi::method_ext ("scan_collection", &scan_region, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("region"), gsi::arg ("flat", false),
"@brief Turns the given region into a hierarchical or flat report database\n"
"The exact behavior depends on the nature of the region. If the region is a hierarchical (original or deep) region "
"and the 'flat' argument is false, this method will produce a hierarchical report database in the given category. "
@ -331,15 +331,15 @@ Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
"\n"
"This method has been introduced in version 0.26.\n"
) +
gsi::method_ext ("scan_edges", &scan_edges, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edges"), gsi::arg ("flat", false),
gsi::method_ext ("scan_collection", &scan_edges, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edges"), gsi::arg ("flat", false),
"@brief Turns the given edge collection into a hierarchical or flat report database\n"
"This method behaves like the \\scan_region method, except that is accepts an edge collection.\n"
"This a another flavour of \\scan_collection accepting an edge collection.\n"
"\n"
"This method has been introduced in version 0.26.\n"
) +
gsi::method_ext ("scan_edge_pairs", &scan_edge_pairs, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edge_pairs"), gsi::arg ("flat", false),
gsi::method_ext ("scan_collection", &scan_edge_pairs, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edge_pairs"), gsi::arg ("flat", false),
"@brief Turns the given edge pair collection into a hierarchical or flat report database\n"
"This method behaves like the \\scan_region method, except that is accepts an edge pair collection.\n"
"This a another flavour of \\scan_collection accepting an edge pair collection.\n"
"\n"
"This method has been introduced in version 0.26.\n"
) +

View File

@ -279,6 +279,12 @@ ValueBase::create_from_shape (const db::Shape &shape, const db::CplxTrans &trans
shape.edge (edge);
return new rdb::Value <db::DEdge> (edge.transformed (trans));
} else if (shape.is_edge_pair ()) {
db::EdgePair edge_pair;
shape.edge_pair (edge_pair);
return new rdb::Value <db::DEdgePair> (edge_pair.transformed (trans));
} else {
return 0;
}

View File

@ -103,6 +103,10 @@ public:
virtual void begin (const db::RecursiveShapeIterator *iter)
{
if (! iter->top_cell () || ! iter->layout ()) {
return;
}
db::cell_index_type ci = iter->top_cell ()->cell_index ();
const rdb::Cell *rdb_cell = cell_for_id (iter->layout (), ci);

View File

@ -793,7 +793,7 @@ class RDB_TestClass < TestBase
rdb = RBA::ReportDatabase.new("neu")
cat = rdb.create_category("l1")
r = RBA::Region::new(c1.begin_shapes_rec(l1))
cat.scan_region(rdb.create_cell("TOP"), RBA::CplxTrans::new(0.001), r) # hierarchical scan
cat.scan_collection(rdb.create_cell("TOP"), RBA::CplxTrans::new(0.001), r) # hierarchical scan
assert_equal(cat.num_items, 3)
cn = []
rdb.each_cell { |c| cn << c.to_s_test }
@ -805,7 +805,7 @@ class RDB_TestClass < TestBase
rdb = RBA::ReportDatabase.new("neu")
cat = rdb.create_category("l1")
r = RBA::Region::new(c1.begin_shapes_rec(l1))
cat.scan_region(rdb.create_cell("TOP"), RBA::CplxTrans::new(0.001), r, true) # flat scan
cat.scan_collection(rdb.create_cell("TOP"), RBA::CplxTrans::new(0.001), r, true) # flat scan
assert_equal(cat.num_items, 3)
cn = []
rdb.each_cell { |c| cn << c.to_s_test }
@ -817,7 +817,7 @@ class RDB_TestClass < TestBase
rdb = RBA::ReportDatabase.new("neu")
cat = rdb.create_category("l1")
r = RBA::Region::new(c1.begin_shapes_rec(l1)).merged
cat.scan_region(rdb.create_cell("TOP"), RBA::CplxTrans::new(0.001), r, true) # flat scan
cat.scan_collection(rdb.create_cell("TOP"), RBA::CplxTrans::new(0.001), r, true) # flat scan
assert_equal(cat.num_items, 1)
cn = []
rdb.each_cell { |c| cn << c.to_s_test }