WIP: enhanced recursive shape iterator's push mode.

This commit is contained in:
Matthias Koefferlein 2018-11-13 23:40:08 +01:00
parent f346e70746
commit 2bfccca462
3 changed files with 98 additions and 58 deletions

View File

@ -763,15 +763,11 @@ RecursiveShapeIterator::down (RecursiveShapeReceiver *receiver) const
}
if (receiver && ! receiver->enter_cell (this, cell (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ())) {
if (m_has_layers) {
m_current_layer = m_layers.size ();
}
m_shape = shape_iterator ();
m_inst = inst_iterator ();
} else {
new_cell (receiver);
if (receiver) {
receiver->enter_cell (this, cell (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ());
}
new_cell (receiver);
}
void
@ -880,21 +876,24 @@ RecursiveShapeIterator::new_inst (RecursiveShapeReceiver *receiver) const
}
}
bool all_of_instance = true;
if (m_local_region_stack.back () != box_type::world () && ! m_inst->cell_inst ().bbox (m_box_convert).inside (m_local_region_stack.back ())) {
m_inst_array = m_inst->cell_inst ().begin_touching (m_local_region_stack.back (), m_box_convert);
all_of_instance = false;
if (receiver && ! receiver->new_inst (this, m_inst->cell_inst (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back (), false)) {
m_inst_array = inst_array_iterator ();
} else {
m_inst_array = m_inst->cell_inst ().begin_touching (m_local_region_stack.back (), m_box_convert);
}
} else {
m_inst_array = m_inst->cell_inst ().begin ();
// TODO: optimization potential: only report all_of_instance == false, if not entirely within the complex region
all_of_instance = m_local_complex_region_stack.empty ();
}
if (receiver) {
receiver->new_inst (this, m_inst->cell_inst (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back (), all_of_instance);
bool all_of_instance = m_local_complex_region_stack.empty ();
if (receiver && ! receiver->new_inst (this, m_inst->cell_inst (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back (), all_of_instance)) {
m_inst_array = inst_array_iterator ();
} else {
m_inst_array = m_inst->cell_inst ().begin ();
}
}
new_inst_member (receiver);
if (! m_inst_array.at_end ()) {
break;
} else {
@ -921,8 +920,12 @@ RecursiveShapeIterator::new_inst_member (RecursiveShapeReceiver *receiver) const
}
if (! m_inst_array.at_end () && receiver) {
receiver->new_inst_member (this, m_inst->cell_inst (), m_inst->complex_trans (*m_inst_array), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ());
while (! m_inst_array.at_end () && receiver) {
if (receiver->new_inst_member (this, m_inst->cell_inst (), m_inst->complex_trans (*m_inst_array), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ())) {
break;
} else {
++m_inst_array;
}
}
}

View File

@ -758,10 +758,7 @@ public:
* @brief Enters a cell
*
* This method is called when the recursive shape iterator
* enters a new cell. This method can return false. In this
* case, the cell is skipped together with it's subcells.
*
* This method is not called for the top cell. When it is called, "iter->trans()"
* enters a new cell. It is not called for the top cell. When it is called, "iter->trans()"
* will already be updated.
*
* @param iter The iterator
@ -769,7 +766,7 @@ public:
* @param region The clip box as seen from "cell" or db::Box::world if there is no clip box
* @param complex_region A complex clip region if one is supplied together with "region"
*/
virtual bool enter_cell (const RecursiveShapeIterator * /*iter*/, const db::Cell * /*cell*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) { return true; }
virtual void enter_cell (const RecursiveShapeIterator * /*iter*/, const db::Cell * /*cell*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) { }
/**
* @brief Leaves the current cell
@ -798,8 +795,10 @@ public:
* ...
*
* The "all" parameter is true, if all instances of the array will be addressed.
*
* If this method returns false, the instance (the whole array) is skipped and the cell is not entered.
*/
virtual void new_inst (const RecursiveShapeIterator * /*iter*/, const db::CellInstArray & /*inst*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool /*all*/) { }
virtual bool new_inst (const RecursiveShapeIterator * /*iter*/, const db::CellInstArray & /*inst*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool /*all*/) { return true; }
/**
* @brief Enters a new array member of the instance
@ -807,8 +806,10 @@ public:
* See "new_inst" for a description. This method adds the "trans" parameter
* which holds the complex transformation for this particular instance of
* the array.
*
* If this method returns false, this array instance (but not the whole array) is skipped and the cell is not entered.
*/
virtual void new_inst_member (const RecursiveShapeIterator * /*iter*/, const db::CellInstArray & /*inst*/, const db::ICplxTrans & /*trans*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) { }
virtual bool new_inst_member (const RecursiveShapeIterator * /*iter*/, const db::CellInstArray & /*inst*/, const db::ICplxTrans & /*trans*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/) { return true; }
/**
* @brief Delivers a shape

View File

@ -908,10 +908,9 @@ public:
virtual void begin (const db::RecursiveShapeIterator * /*iter*/) { m_text += "begin\n"; }
virtual void end (const db::RecursiveShapeIterator * /*iter*/) { m_text += "end\n"; }
virtual bool enter_cell (const db::RecursiveShapeIterator *iter, const db::Cell *cell, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
virtual void enter_cell (const db::RecursiveShapeIterator *iter, const db::Cell *cell, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
{
m_text += std::string ("enter_cell(") + iter->layout ()->cell_name (cell->cell_index ()) + ")\n";
return true;
}
virtual void leave_cell (const db::RecursiveShapeIterator *iter, const db::Cell *cell)
@ -919,18 +918,20 @@ public:
m_text += std::string ("leave_cell(") + iter->layout ()->cell_name (cell->cell_index ()) + ")\n";
}
virtual void new_inst (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool all)
virtual bool new_inst (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool all)
{
m_text += std::string ("new_inst(") + iter->layout ()->cell_name (inst.object ().cell_index ());
if (all) {
m_text += ",all";
}
m_text += ")\n";
return true;
}
virtual void new_inst_member (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::ICplxTrans &trans, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
virtual bool new_inst_member (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::ICplxTrans &trans, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
{
m_text += std::string ("new_inst_member(") + iter->layout ()->cell_name (inst.object ().cell_index ()) + "," + tl::to_string (trans) + ")\n";
return true;
}
virtual void shape (const db::RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans &trans)
@ -942,22 +943,39 @@ private:
std::string m_text;
};
class ReceiverRejectingACell
class ReceiverRejectingACellInstanceArray
: public LoggingReceiver
{
public:
ReceiverRejectingACell (db::cell_index_type rejected) : m_rejected (rejected) { }
ReceiverRejectingACellInstanceArray (db::cell_index_type rejected) : m_rejected (rejected) { }
virtual bool enter_cell (const db::RecursiveShapeIterator *iter, const db::Cell *cell, const db::Box &region, const box_tree_type *complex_region)
virtual bool new_inst (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::Box &region, const box_tree_type *complex_region, bool all)
{
LoggingReceiver::enter_cell (iter, cell, region, complex_region);
return cell->cell_index () != m_rejected;
LoggingReceiver::new_inst (iter, inst, region, complex_region, all);
return inst.object ().cell_index () != m_rejected;
}
private:
db::cell_index_type m_rejected;
};
class ReceiverRejectingACellInstance
: public LoggingReceiver
{
public:
ReceiverRejectingACellInstance (db::cell_index_type rejected, const db::ICplxTrans &trans_rejected) : m_rejected (rejected), m_trans_rejected (trans_rejected) { }
virtual bool new_inst_member (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::ICplxTrans &trans, const db::Box &region, const box_tree_type *complex_region)
{
LoggingReceiver::new_inst_member (iter, inst, trans, region, complex_region);
return inst.object ().cell_index () != m_rejected || trans != m_trans_rejected;
}
private:
db::cell_index_type m_rejected;
db::ICplxTrans m_trans_rejected;
};
// Push mode with cells
TEST(10)
{
@ -1066,7 +1084,7 @@ TEST(10)
"end\n"
);
ReceiverRejectingACell rr1 (c2.cell_index ());
ReceiverRejectingACellInstanceArray rr1 (c2.cell_index ());
db::RecursiveShapeIterator ir1 (g, c0, 0);
ir1.push (&rr1);
@ -1076,89 +1094,107 @@ TEST(10)
"new_inst_member($2,r0 *1 0,0)\n"
"enter_cell($2)\n"
"new_inst($3,all)\n"
"new_inst_member($3,r0 *1 0,0)\n"
"enter_cell($3)\n"
"leave_cell($3)\n"
"leave_cell($2)\n"
"new_inst_member($2,r0 *1 0,6000)\n"
"enter_cell($2)\n"
"new_inst($3,all)\n"
"leave_cell($2)\n"
"new_inst_member($2,r0 *1 6000,0)\n"
"enter_cell($2)\n"
"new_inst($3,all)\n"
"leave_cell($2)\n"
"new_inst_member($2,r0 *1 6000,6000)\n"
"enter_cell($2)\n"
"new_inst($3,all)\n"
"leave_cell($2)\n"
"end\n"
);
ReceiverRejectingACellInstance rri1 (c2.cell_index (), db::ICplxTrans ());
db::RecursiveShapeIterator iri1 (g, c0, 0);
iri1.push (&rri1);
EXPECT_EQ (rri1.text (),
"begin\n"
"new_inst($2,all)\n"
"new_inst_member($2,r0 *1 0,0)\n"
"enter_cell($2)\n"
"new_inst($3,all)\n"
"new_inst_member($3,r0 *1 0,0)\n" // -> skipped
"new_inst_member($3,r0 *1 0,2000)\n"
"enter_cell($3)\n"
"shape(box (1000,-500;2000,500),r0 *1 0,2000)\n"
"leave_cell($3)\n"
"new_inst_member($3,r0 *1 3000,1000)\n"
"enter_cell($3)\n"
"shape(box (1000,-500;2000,500),r0 *1 3000,1000)\n"
"leave_cell($3)\n"
"new_inst_member($3,r0 *1 3000,3000)\n"
"enter_cell($3)\n"
"shape(box (1000,-500;2000,500),r0 *1 3000,3000)\n"
"leave_cell($3)\n"
"leave_cell($2)\n"
"new_inst_member($2,r0 *1 0,6000)\n"
"enter_cell($2)\n"
"new_inst($3,all)\n"
"new_inst_member($3,r0 *1 0,0)\n"
"enter_cell($3)\n"
"leave_cell($3)\n"
"new_inst_member($3,r0 *1 0,2000)\n"
"enter_cell($3)\n"
"shape(box (1000,-500;2000,500),r0 *1 0,8000)\n"
"leave_cell($3)\n"
"new_inst_member($3,r0 *1 3000,1000)\n"
"enter_cell($3)\n"
"shape(box (1000,-500;2000,500),r0 *1 3000,7000)\n"
"leave_cell($3)\n"
"new_inst_member($3,r0 *1 3000,3000)\n"
"enter_cell($3)\n"
"shape(box (1000,-500;2000,500),r0 *1 3000,9000)\n"
"leave_cell($3)\n"
"leave_cell($2)\n"
"new_inst_member($2,r0 *1 6000,0)\n"
"enter_cell($2)\n"
"new_inst($3,all)\n"
"new_inst_member($3,r0 *1 0,0)\n"
"enter_cell($3)\n"
"leave_cell($3)\n"
"new_inst_member($3,r0 *1 0,2000)\n"
"enter_cell($3)\n"
"shape(box (1000,-500;2000,500),r0 *1 6000,2000)\n"
"leave_cell($3)\n"
"new_inst_member($3,r0 *1 3000,1000)\n"
"enter_cell($3)\n"
"shape(box (1000,-500;2000,500),r0 *1 9000,1000)\n"
"leave_cell($3)\n"
"new_inst_member($3,r0 *1 3000,3000)\n"
"enter_cell($3)\n"
"shape(box (1000,-500;2000,500),r0 *1 9000,3000)\n"
"leave_cell($3)\n"
"leave_cell($2)\n"
"new_inst_member($2,r0 *1 6000,6000)\n"
"enter_cell($2)\n"
"new_inst($3,all)\n"
"new_inst_member($3,r0 *1 0,0)\n"
"enter_cell($3)\n"
"leave_cell($3)\n"
"new_inst_member($3,r0 *1 0,2000)\n"
"enter_cell($3)\n"
"shape(box (1000,-500;2000,500),r0 *1 6000,8000)\n"
"leave_cell($3)\n"
"new_inst_member($3,r0 *1 3000,1000)\n"
"enter_cell($3)\n"
"shape(box (1000,-500;2000,500),r0 *1 9000,7000)\n"
"leave_cell($3)\n"
"new_inst_member($3,r0 *1 3000,3000)\n"
"enter_cell($3)\n"
"shape(box (1000,-500;2000,500),r0 *1 9000,9000)\n"
"leave_cell($3)\n"
"leave_cell($2)\n"
"end\n"
);
ReceiverRejectingACell rr2 (c1.cell_index ());
ReceiverRejectingACellInstanceArray rr2 (c1.cell_index ());
db::RecursiveShapeIterator ir2 (g, c0, 0);
ir2.push (&rr2);
EXPECT_EQ (rr2.text (),
"begin\n"
"new_inst($2,all)\n"
"new_inst_member($2,r0 *1 0,0)\n"
"enter_cell($2)\n"
"leave_cell($2)\n"
"new_inst_member($2,r0 *1 0,6000)\n"
"enter_cell($2)\n"
"leave_cell($2)\n"
"new_inst_member($2,r0 *1 6000,0)\n"
"enter_cell($2)\n"
"leave_cell($2)\n"
"new_inst_member($2,r0 *1 6000,6000)\n"
"enter_cell($2)\n"
"leave_cell($2)\n"
"end\n"
);