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 (receiver) {
if (m_has_layers) { receiver->enter_cell (this, cell (), m_local_region_stack.back (), m_local_complex_region_stack.empty () ? 0 : &m_local_complex_region_stack.back ());
m_current_layer = m_layers.size ();
}
m_shape = shape_iterator ();
m_inst = inst_iterator ();
} else {
new_cell (receiver);
} }
new_cell (receiver);
} }
void 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 ())) { 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); 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)) {
all_of_instance = 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 { } 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 // 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 (); 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 ();
if (receiver) { } else {
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 = m_inst->cell_inst ().begin ();
}
} }
new_inst_member (receiver); new_inst_member (receiver);
if (! m_inst_array.at_end ()) { if (! m_inst_array.at_end ()) {
break; break;
} else { } else {
@ -921,8 +920,12 @@ RecursiveShapeIterator::new_inst_member (RecursiveShapeReceiver *receiver) const
} }
if (! m_inst_array.at_end () && receiver) { while (! 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 ()); 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 * @brief Enters a cell
* *
* This method is called when the recursive shape iterator * This method is called when the recursive shape iterator
* enters a new cell. This method can return false. In this * enters a new cell. It is not called for the top cell. When it is called, "iter->trans()"
* 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()"
* will already be updated. * will already be updated.
* *
* @param iter The iterator * @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 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" * @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 * @brief Leaves the current cell
@ -798,8 +795,10 @@ public:
* ... * ...
* *
* The "all" parameter is true, if all instances of the array will be addressed. * 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 * @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 * See "new_inst" for a description. This method adds the "trans" parameter
* which holds the complex transformation for this particular instance of * which holds the complex transformation for this particular instance of
* the array. * 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 * @brief Delivers a shape

View File

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