From 2bfccca4628207c1238fb7207ee099d708b9ce52 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 13 Nov 2018 23:40:08 +0100 Subject: [PATCH] WIP: enhanced recursive shape iterator's push mode. --- src/db/db/dbRecursiveShapeIterator.cc | 41 +++---- src/db/db/dbRecursiveShapeIterator.h | 15 +-- src/db/unit_tests/dbRecursiveShapeIterator.cc | 100 ++++++++++++------ 3 files changed, 98 insertions(+), 58 deletions(-) diff --git a/src/db/db/dbRecursiveShapeIterator.cc b/src/db/db/dbRecursiveShapeIterator.cc index 9942a0c2c..2c9216776 100644 --- a/src/db/db/dbRecursiveShapeIterator.cc +++ b/src/db/db/dbRecursiveShapeIterator.cc @@ -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; + } } } diff --git a/src/db/db/dbRecursiveShapeIterator.h b/src/db/db/dbRecursiveShapeIterator.h index de4103630..c992f085c 100644 --- a/src/db/db/dbRecursiveShapeIterator.h +++ b/src/db/db/dbRecursiveShapeIterator.h @@ -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 diff --git a/src/db/unit_tests/dbRecursiveShapeIterator.cc b/src/db/unit_tests/dbRecursiveShapeIterator.cc index fff996a2c..03dc7f918 100644 --- a/src/db/unit_tests/dbRecursiveShapeIterator.cc +++ b/src/db/unit_tests/dbRecursiveShapeIterator.cc @@ -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 ®ion, const box_tree_type *complex_region) + virtual bool new_inst (const db::RecursiveShapeIterator *iter, const db::CellInstArray &inst, const db::Box ®ion, 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 ®ion, 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" );