Tiling processor enabling for text input/output, updated tests.

This commit is contained in:
Matthias Koefferlein 2020-05-23 16:23:40 +02:00
parent 5135d76367
commit 81750ed3d8
15 changed files with 250 additions and 31 deletions

View File

@ -180,7 +180,7 @@ AsIfFlatEdges::pull_generic (const Edges &edges) const
{
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
AddressableEdgeDelivery e (begin (), true);
AddressableEdgeDelivery e (begin (), has_valid_edges ());
for ( ; ! e.at_end (); ++e) {
scanner.insert (e.operator-> (), 1);
@ -507,7 +507,7 @@ AsIfFlatEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Co
db::box_scanner<db::Edge, size_t> scanner (report_progress (), progress_desc ());
scanner.reserve (size () + (other ? other->size () : 0));
AddressableEdgeDelivery e (begin_merged (), has_valid_edges ());
AddressableEdgeDelivery e (begin_merged (), has_valid_merged_edges ());
size_t n = 0;
for ( ; ! e.at_end (); ++e) {

View File

@ -342,7 +342,7 @@ AsIfFlatTexts::pull_generic (const Region &other) const
db::box_scanner2<db::Text, size_t, db::Polygon, size_t> scanner (report_progress (), progress_desc ());
AddressableTextDelivery e (begin (), true);
AddressableTextDelivery e (begin (), has_valid_texts ());
for ( ; ! e.at_end (); ++e) {
scanner.insert1 (e.operator-> (), 0);

View File

@ -164,6 +164,34 @@ private:
const db::ICplxTrans m_trans;
};
/**
* @brief A helper class for the generic implementation of the text collection insert functionality
*/
class TextsInserter
{
public:
TextsInserter (db::Texts *texts, const db::ICplxTrans &trans)
: mp_texts (texts), m_trans (trans)
{
// .. nothing yet ..
}
template <class T>
void operator() (const T &)
{
// .. discard anything except Texts ..
}
void operator() (const db::Text &t)
{
mp_texts->insert (t.transformed (m_trans));
}
private:
db::Texts *mp_texts;
const db::ICplxTrans m_trans;
};
class TileLayoutOutputReceiver
: public db::TileOutputReceiver
{
@ -271,6 +299,26 @@ private:
db::EdgePairs *mp_edge_pairs;
};
class TileTextsOutputReceiver
: public db::TileOutputReceiver
{
public:
TileTextsOutputReceiver (db::Texts *texts)
: mp_texts (texts)
{
// .. nothing yet ..
}
void put (size_t /*ix*/, size_t /*iy*/, const db::Box &tile, size_t /*id*/, const tl::Variant &obj, double /*dbu*/, const db::ICplxTrans &trans, bool clip)
{
TextsInserter inserter (mp_texts, trans);
insert_var (inserter, obj, tile, clip);
}
private:
db::Texts *mp_texts;
};
class TilingProcessorJob
: public tl::JobBase
{
@ -395,6 +443,7 @@ private:
TilingProcessorJob *mp_job;
void do_perform (const TilingProcessorTask *task);
void make_input_var (const TilingProcessor::InputSpec &is, const db::RecursiveShapeIterator *iter, tl::Eval &eval, double sf);
};
class TilingProcessorReceiverFunction
@ -452,6 +501,24 @@ public:
}
};
void
TilingProcessorWorker::make_input_var (const TilingProcessor::InputSpec &is, const db::RecursiveShapeIterator *iter, tl::Eval &eval, double sf)
{
if (! iter) {
iter = &is.iter;
}
if (is.type == TilingProcessor::TypeRegion) {
eval.set_var (is.name, tl::Variant (db::Region (*iter, db::ICplxTrans (sf) * is.trans, is.merged_semantics)));
} else if (is.type == TilingProcessor::TypeEdges) {
eval.set_var (is.name, tl::Variant (db::Edges (*iter, db::ICplxTrans (sf) * is.trans, is.merged_semantics)));
} else if (is.type == TilingProcessor::TypeEdgePairs) {
eval.set_var (is.name, tl::Variant (db::EdgePairs (*iter, db::ICplxTrans (sf) * is.trans)));
} else if (is.type == TilingProcessor::TypeTexts) {
eval.set_var (is.name, tl::Variant (db::Texts (*iter, db::ICplxTrans (sf) * is.trans)));
}
}
void
TilingProcessorWorker::do_perform (const TilingProcessorTask *tile_task)
{
@ -492,11 +559,7 @@ TilingProcessorWorker::do_perform (const TilingProcessorTask *tile_task)
if (! mp_job->has_tiles ()) {
if (i->region) {
eval.set_var (i->name, tl::Variant (db::Region (i->iter, db::ICplxTrans (sf) * i->trans, i->merged_semantics)));
} else {
eval.set_var (i->name, tl::Variant (db::Edges (i->iter, db::ICplxTrans (sf) * i->trans, i->merged_semantics)));
}
make_input_var (*i, 0, eval, sf);
} else {
@ -509,11 +572,7 @@ TilingProcessorWorker::do_perform (const TilingProcessorTask *tile_task)
iter.confine_region (region_dbu);
}
if (i->region) {
eval.set_var (i->name, tl::Variant (db::Region (iter, db::ICplxTrans (sf) * i->trans, i->merged_semantics)));
} else {
eval.set_var (i->name, tl::Variant (db::Edges (iter, db::ICplxTrans (sf) * i->trans, i->merged_semantics)));
}
make_input_var (*i, &iter, eval, sf);
}
@ -559,7 +618,7 @@ TilingProcessor::TilingProcessor ()
}
void
TilingProcessor::input (const std::string &name, const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans, bool as_region, bool merged_semantics)
TilingProcessor::input (const std::string &name, const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans, Type type, bool merged_semantics)
{
if (m_inputs.empty () && iter.layout ()) {
m_dbu = iter.layout ()->dbu ();
@ -568,7 +627,7 @@ TilingProcessor::input (const std::string &name, const db::RecursiveShapeIterato
m_inputs.back ().name = name;
m_inputs.back ().iter = iter;
m_inputs.back ().trans = trans;
m_inputs.back ().region = as_region;
m_inputs.back ().type = type;
m_inputs.back ().merged_semantics = merged_semantics;
}
@ -699,7 +758,17 @@ TilingProcessor::output (const std::string &name, db::EdgePairs &edge_pairs)
m_outputs.back ().receiver = new TileEdgePairsOutputReceiver (&edge_pairs);
}
void
void
TilingProcessor::output (const std::string &name, db::Texts &texts)
{
m_top_eval.set_var (name, m_outputs.size ());
m_outputs.push_back (OutputSpec ());
m_outputs.back ().name = name;
m_outputs.back ().id = 0;
m_outputs.back ().receiver = new TileTextsOutputReceiver (&texts);
}
void
TilingProcessor::output (const std::string &name, db::Edges &edges)
{
m_top_eval.set_var (name, m_outputs.size ());

View File

@ -346,6 +346,20 @@ void insert (X &inserter, const db::EdgePairs &data, const db::Box &tile, bool c
}
}
/**
* @brief Delivery of tiling processor output
* This utility is put between the container and the receiver.
* The inserter is an object having an operator() that takes the object.
* This function is responsible for preparing (i.e. clipping) and delivering the output.
*/
template <class X>
void insert (X &inserter, const db::Texts &data, const db::Box &tile, bool clip)
{
for (db::Texts::const_iterator o = data.begin (); ! o.at_end (); ++o) {
insert (inserter, *o, tile, clip);
}
}
/**
* @brief Delivery of tiling processor output
* This utility is put between the container and the receiver.
@ -364,6 +378,9 @@ bool insert_var (X &inserter, const tl::Variant &obj, const db::Box &tile, bool
} else if (obj.is_user<db::Edges> ()) {
insert (inserter, obj.to_user<db::Edges> (), tile, clip);
return true;
} else if (obj.is_user<db::Texts> ()) {
insert (inserter, obj.to_user<db::Texts> (), tile, clip);
return true;
} else if (obj.is_user<db::Box> ()) {
insert (inserter, obj.to_user<db::Box> (), tile, clip);
return true;
@ -417,6 +434,8 @@ bool insert_var (X &inserter, const tl::Variant &obj, const db::Box &tile, bool
class DB_PUBLIC TilingProcessor
{
public:
enum Type { TypeRegion, TypeEdges, TypeEdgePairs, TypeTexts };
/**
* @brief Constructor
*/
@ -441,7 +460,7 @@ public:
* The transformation can be used to convert between database units.
* If "as_region" is false, the input is taken as edge input.
*/
void input (const std::string &name, const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans = db::ICplxTrans (), bool as_region = true, bool merged_semantics = true);
void input (const std::string &name, const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans = db::ICplxTrans (), Type type = TypeRegion, bool merged_semantics = true);
/**
* @brief Specifies the output
@ -489,6 +508,14 @@ public:
*/
void output (const std::string &name, db::EdgePairs &edge_pairs);
/**
* @brief Specifies output to an text collection
*
* This version will specify output to a Texts object.
* Only texts will be stored.
*/
void output (const std::string &name, db::Texts &texts);
/**
* @brief Specifies output to an edge collection
*
@ -624,11 +651,11 @@ private:
struct InputSpec
{
InputSpec () : region (false), merged_semantics (false) { }
InputSpec () : type (TilingProcessor::TypeRegion), merged_semantics (false) { }
std::string name;
db::RecursiveShapeIterator iter;
db::ICplxTrans trans;
bool region;
TilingProcessor::Type type;
bool merged_semantics;
};

View File

@ -255,6 +255,11 @@ static void tp_output_edge_pairs (db::TilingProcessor *proc, const std::string &
proc->output (name, edge_pairs);
}
static void tp_output_texts (db::TilingProcessor *proc, const std::string &name, db::Texts &texts)
{
proc->output (name, texts);
}
static void tp_output_double (db::TilingProcessor *proc, const std::string &name, double *v)
{
proc->output (name, 0, new DoubleCollectingTileOutputReceiver (v), db::ICplxTrans ());
@ -311,25 +316,49 @@ static void tp_input7 (db::TilingProcessor *proc, const std::string &name, const
static void tp_input8 (db::TilingProcessor *proc, const std::string &name, const db::Region &region)
{
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = region.begin_iter ();
proc->input (name, it.first, it.second, true /*as polygons*/, region.merged_semantics ());
proc->input (name, it.first, it.second, db::TilingProcessor::TypeRegion, region.merged_semantics ());
}
static void tp_input9 (db::TilingProcessor *proc, const std::string &name, const db::Region &region, const db::ICplxTrans &trans)
{
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = region.begin_iter ();
proc->input (name, it.first, trans * it.second, true /*as polygons*/, region.merged_semantics ());
proc->input (name, it.first, trans * it.second, db::TilingProcessor::TypeRegion, region.merged_semantics ());
}
static void tp_input10 (db::TilingProcessor *proc, const std::string &name, const db::Edges &edges)
{
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = edges.begin_iter ();
proc->input (name, it.first, it.second, false /*not as polygons*/, edges.merged_semantics ());
proc->input (name, it.first, it.second, db::TilingProcessor::TypeEdges, edges.merged_semantics ());
}
static void tp_input11 (db::TilingProcessor *proc, const std::string &name, const db::Edges &edges, const db::ICplxTrans &trans)
{
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = edges.begin_iter ();
proc->input (name, it.first, trans * it.second, false /*not as polygons*/, edges.merged_semantics ());
proc->input (name, it.first, trans * it.second, db::TilingProcessor::TypeEdges, edges.merged_semantics ());
}
static void tp_input12 (db::TilingProcessor *proc, const std::string &name, const db::EdgePairs &edge_pairs)
{
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = edge_pairs.begin_iter ();
proc->input (name, it.first, it.second, db::TilingProcessor::TypeEdgePairs);
}
static void tp_input13 (db::TilingProcessor *proc, const std::string &name, const db::EdgePairs &edge_pairs, const db::ICplxTrans &trans)
{
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = edge_pairs.begin_iter ();
proc->input (name, it.first, trans * it.second, db::TilingProcessor::TypeEdgePairs);
}
static void tp_input14 (db::TilingProcessor *proc, const std::string &name, const db::Texts &texts)
{
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = texts.begin_iter ();
proc->input (name, it.first, it.second, db::TilingProcessor::TypeTexts);
}
static void tp_input15 (db::TilingProcessor *proc, const std::string &name, const db::Texts &texts, const db::ICplxTrans &trans)
{
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = texts.begin_iter ();
proc->input (name, it.first, trans * it.second, db::TilingProcessor::TypeTexts);
}
Class<db::TilingProcessor> decl_TilingProcessor ("db", "TilingProcessor",
@ -385,16 +414,16 @@ Class<db::TilingProcessor> decl_TilingProcessor ("db", "TilingProcessor",
method_ext ("input", &tp_input8, gsi::arg ("name"), gsi::arg ("region"),
"@brief Specifies input for the tiling processor\n"
"This method will establish an input channel for the processor. This version receives input from a \\Region object. "
"Regions don't always come with a database unit, hence a database unit should be specified with the \\dbu= method if only "
"regions and edges are used as input.\n"
"Regions don't always come with a database unit, hence a database unit should be specified with the \\dbu= method unless "
"a layout object is specified as input too.\n"
"\n"
"The name specifies the variable under which the input can be used in the scripts."
) +
method_ext ("input", &tp_input9, gsi::arg ("name"), gsi::arg ("region"), gsi::arg ("trans"),
"@brief Specifies input for the tiling processor\n"
"This method will establish an input channel for the processor. This version receives input from a \\Region object. "
"Regions don't always come with a database unit, hence a database unit should be specified with the \\dbu= method if only "
"regions and edges are used as input.\n"
"Regions don't always come with a database unit, hence a database unit should be specified with the \\dbu= method unless "
"a layout object is specified as input too.\n"
"\n"
"The name specifies the variable under which the input can be used in the scripts."
"\n"
@ -403,22 +432,62 @@ Class<db::TilingProcessor> decl_TilingProcessor ("db", "TilingProcessor",
method_ext ("input", &tp_input10, gsi::arg ("name"), gsi::arg ("edges"),
"@brief Specifies input for the tiling processor\n"
"This method will establish an input channel for the processor. This version receives input from an \\Edges object. "
"Edge collections don't always come with a database unit, hence a database unit should be specified with the \\dbu= method if only "
"regions and edges are used as input.\n"
"Edge collections don't always come with a database unit, hence a database unit should be specified with the \\dbu= method unless "
"a layout object is specified as input too.\n"
"\n"
"The name specifies the variable under which the input can be used in the scripts."
) +
method_ext ("input", &tp_input11, gsi::arg ("name"), gsi::arg ("edges"), gsi::arg ("trans"),
"@brief Specifies input for the tiling processor\n"
"This method will establish an input channel for the processor. This version receives input from an \\Edges object. "
"Edge collections don't always come with a database unit, hence a database unit should be specified with the \\dbu= method if only "
"regions and edges are used as input.\n"
"Edge collections don't always come with a database unit, hence a database unit should be specified with the \\dbu= method unless "
"a layout object is specified as input too.\n"
"\n"
"The name specifies the variable under which the input can be used in the scripts."
"\n"
"This variant allows one to specify an additional transformation too. It has been introduced in version 0.23.2.\n"
"\n"
) +
method_ext ("input", &tp_input12, gsi::arg ("name"), gsi::arg ("edge_pairs"),
"@brief Specifies input for the tiling processor\n"
"This method will establish an input channel for the processor. This version receives input from an \\EdgePairs object. "
"Edge pair collections don't always come with a database unit, hence a database unit should be specified with the \\dbu= method unless "
"a layout object is specified as input too.\n"
"\n"
"The name specifies the variable under which the input can be used in the scripts."
"\n"
"This variant has been introduced in version 0.27.\n"
) +
method_ext ("input", &tp_input13, gsi::arg ("name"), gsi::arg ("edge_pairs"), gsi::arg ("trans"),
"@brief Specifies input for the tiling processor\n"
"This method will establish an input channel for the processor. This version receives input from an \\EdgePairs object. "
"Edge pair collections don't always come with a database unit, hence a database unit should be specified with the \\dbu= method unless "
"a layout object is specified as input too.\n"
"\n"
"The name specifies the variable under which the input can be used in the scripts."
"\n"
"This variant has been introduced in version 0.27.\n"
) +
method_ext ("input", &tp_input14, gsi::arg ("name"), gsi::arg ("texts"),
"@brief Specifies input for the tiling processor\n"
"This method will establish an input channel for the processor. This version receives input from an \\Texts object. "
"Text collections don't always come with a database unit, hence a database unit should be specified with the \\dbu= method unless "
"a layout object is specified as input too.\n"
"\n"
"The name specifies the variable under which the input can be used in the scripts."
"\n"
"This variant has been introduced in version 0.27.\n"
) +
method_ext ("input", &tp_input15, gsi::arg ("name"), gsi::arg ("texts"), gsi::arg ("trans"),
"@brief Specifies input for the tiling processor\n"
"This method will establish an input channel for the processor. This version receives input from an \\Texts object. "
"Text collections don't always come with a database unit, hence a database unit should be specified with the \\dbu= method unless "
"a layout object is specified as input too.\n"
"\n"
"The name specifies the variable under which the input can be used in the scripts."
"\n"
"This variant has been introduced in version 0.27.\n"
) +
method ("var", &db::TilingProcessor::var, gsi::arg ("name"), gsi::arg ("value"),
"@brief Defines a variable for the tiling processor script\n"
"\n"
@ -525,6 +594,20 @@ Class<db::TilingProcessor> decl_TilingProcessor ("db", "TilingProcessor",
"@param name The name of the channel\n"
"@param edge_pairs The \\EdgePairs object to which the data is sent\n"
) +
method_ext ("output", &tp_output_texts, gsi::arg ("name"), gsi::arg ("texts"),
"@brief Specifies output to an \\Texts object\n"
"This method will establish an output channel to an \\Texts object. The output sent to that channel "
"will be put into the specified edge pair collection.\n"
"Only \\Text objects are accepted. Other objects are discarded.\n"
"\n"
"The name is the name which must be used in the _output function of the scripts in order to "
"address that channel.\n"
"\n"
"@param name The name of the channel\n"
"@param texts The \\Texts object to which the data is sent\n"
"\n"
"This variant has been introduced in version 0.27."
) +
method_ext ("output", &tp_output_double, gsi::arg ("name"), gsi::arg ("sum"),
"@brief Specifies output to single value\n"
"This method will establish an output channel which sums up float data delivered by calling the _output function.\n"

BIN
testdata/drc/.drcSuiteTests.drc.swp vendored Normal file

Binary file not shown.

BIN
testdata/drc/.drctest.drc.swp vendored Normal file

Binary file not shown.

View File

@ -15,8 +15,10 @@ def run_testsuite(dm, ic, tiled = false, hier = false)
lb = 100
a = polygons(RBA::LayerInfo::new(1, 0))
at = labels(1)
b = polygons(2)
c = polygons(3)
d = polygons(4)
x = polygons(10)
y = polygons(11)
empty = polygons(1000)
@ -605,6 +607,44 @@ def run_testsuite(dm, ic, tiled = false, hier = false)
p = b.edges.intersections(c.edges)
p.output(lb + 5, dm)
lb += 10 #450
message "--- texts and filters #{lb}"
p = at
p.output(lb, dm)
p = at.texts
p.output(lb + 1, dm)
p = at.texts("A*")
p.output(lb + 2, dm)
p = at.texts(pattern("A*"))
p.output(lb + 3, dm)
p = at.texts(pattern("A*"), as_dots)
p.output(lb + 4, dm)
p = at.texts(text("A*"), as_boxes)
p.output(lb + 5, dm)
p = at.texts_not("A*")
p.output(lb + 6, dm)
p = at.texts_not(pattern("A*"))
p.output(lb + 7, dm)
p = at.texts_not(pattern("A*"), as_dots)
p.output(lb + 8, dm)
p = at.texts_not(text("A*"), as_boxes)
p.output(lb + 9, dm)
lb += 10 #460
message "--- texts and polygon booleans and interactions #{lb}"
p = at & d
p.output(lb, dm)
p = d.interacting(at)
p.output(lb + 1, dm)
p = at.interacting(d)
p.output(lb + 2, dm)
p = d.pull_interacting(at)
p.output(lb + 3, dm)
p = at.pull_interacting(d)
p.output(lb + 4, dm)
end
if $drc_test_mode == 1

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.