mirror of https://github.com/KLayout/klayout.git
264 lines
9.0 KiB
C++
264 lines
9.0 KiB
C++
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
KLayout Layout Viewer
|
||
|
|
Copyright (C) 2006-2016 Matthias Koefferlein
|
||
|
|
|
||
|
|
This program is free software; you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU General Public License as published by
|
||
|
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
This program is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU General Public License
|
||
|
|
along with this program; if not, write to the Free Software
|
||
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
#include "dbCellGraphUtils.h"
|
||
|
|
#include "dbMatrix.h"
|
||
|
|
#include "dbRecursiveShapeIterator.h"
|
||
|
|
#include "tlString.h"
|
||
|
|
#include "utHead.h"
|
||
|
|
|
||
|
|
TEST(1)
|
||
|
|
{
|
||
|
|
db::Manager m;
|
||
|
|
db::Layout g (&m);
|
||
|
|
db::Cell &c0 (g.cell (g.add_cell ()));
|
||
|
|
db::Cell &c1 (g.cell (g.add_cell ()));
|
||
|
|
db::Cell &c2 (g.cell (g.add_cell ()));
|
||
|
|
db::Cell &c3 (g.cell (g.add_cell ()));
|
||
|
|
db::Cell &c4 (g.cell (g.add_cell ()));
|
||
|
|
|
||
|
|
db::Trans tt;
|
||
|
|
c0.insert (db::CellInstArray (db::CellInst (c1.cell_index ()), tt, db::Vector(), db::Vector(), 5, 2));
|
||
|
|
c0.insert (db::CellInstArray (db::CellInst (c2.cell_index ()), tt));
|
||
|
|
c4.insert (db::CellInstArray (db::CellInst (c2.cell_index ()), tt, db::Vector(), db::Vector(), 3, 4));
|
||
|
|
c0.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), tt));
|
||
|
|
c2.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), tt));
|
||
|
|
c2.insert (db::CellInstArray (db::CellInst (c3.cell_index ()), tt));
|
||
|
|
|
||
|
|
{
|
||
|
|
db::CellCounter cc (&g);
|
||
|
|
|
||
|
|
EXPECT_EQ (cc.weight (c0.cell_index ()), 1);
|
||
|
|
EXPECT_EQ (cc.weight (c1.cell_index ()), 10);
|
||
|
|
EXPECT_EQ (cc.weight (c2.cell_index ()), 13);
|
||
|
|
EXPECT_EQ (cc.weight (c3.cell_index ()), 27);
|
||
|
|
EXPECT_EQ (cc.weight (c4.cell_index ()), 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
db::CellCounter cc (&g);
|
||
|
|
|
||
|
|
EXPECT_EQ (cc.weight (c4.cell_index ()), 1);
|
||
|
|
EXPECT_EQ (cc.weight (c3.cell_index ()), 27);
|
||
|
|
EXPECT_EQ (cc.weight (c0.cell_index ()), 1);
|
||
|
|
EXPECT_EQ (cc.weight (c1.cell_index ()), 10);
|
||
|
|
EXPECT_EQ (cc.weight (c2.cell_index ()), 13);
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
db::CellCounter cc (&g);
|
||
|
|
|
||
|
|
EXPECT_EQ (cc.weight (c4.cell_index ()), 1);
|
||
|
|
EXPECT_EQ (cc.weight (c3.cell_index ()), 27);
|
||
|
|
EXPECT_EQ (cc.weight (c2.cell_index ()), 13);
|
||
|
|
EXPECT_EQ (cc.weight (c0.cell_index ()), 1);
|
||
|
|
EXPECT_EQ (cc.weight (c1.cell_index ()), 10);
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
db::CellCounter cc (&g, c2.cell_index ());
|
||
|
|
EXPECT_EQ (cc.weight (c3.cell_index ()), 2);
|
||
|
|
EXPECT_EQ (cc.weight (c2.cell_index ()), 1);
|
||
|
|
EXPECT_EQ (cc.weight (c4.cell_index ()), 0);
|
||
|
|
EXPECT_EQ (cc.weight (c0.cell_index ()), 0);
|
||
|
|
EXPECT_EQ (cc.weight (c1.cell_index ()), 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
db::CellCounter cc (&g, c3.cell_index ());
|
||
|
|
EXPECT_EQ (cc.weight (c3.cell_index ()), 1);
|
||
|
|
EXPECT_EQ (cc.weight (c4.cell_index ()), 0);
|
||
|
|
EXPECT_EQ (cc.weight (c0.cell_index ()), 0);
|
||
|
|
EXPECT_EQ (cc.weight (c1.cell_index ()), 0);
|
||
|
|
EXPECT_EQ (cc.weight (c2.cell_index ()), 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
db::CellCounter cc (&g, c0.cell_index ());
|
||
|
|
|
||
|
|
EXPECT_EQ (cc.weight (c4.cell_index ()), 0);
|
||
|
|
EXPECT_EQ (cc.weight (c3.cell_index ()), 3);
|
||
|
|
EXPECT_EQ (cc.weight (c2.cell_index ()), 1);
|
||
|
|
EXPECT_EQ (cc.weight (c0.cell_index ()), 1);
|
||
|
|
EXPECT_EQ (cc.weight (c1.cell_index ()), 10);
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
db::CellCounter cc (&g, c4.cell_index ());
|
||
|
|
|
||
|
|
EXPECT_EQ (cc.weight (c4.cell_index ()), 1);
|
||
|
|
EXPECT_EQ (cc.weight (c3.cell_index ()), 24);
|
||
|
|
EXPECT_EQ (cc.weight (c2.cell_index ()), 12);
|
||
|
|
EXPECT_EQ (cc.weight (c0.cell_index ()), 0);
|
||
|
|
EXPECT_EQ (cc.weight (c1.cell_index ()), 0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class InstanceReferenceSum
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
InstanceReferenceSum (const db::Layout &, const db::Cell &)
|
||
|
|
: m_count (0)
|
||
|
|
{
|
||
|
|
// .. nothing yet ..
|
||
|
|
}
|
||
|
|
|
||
|
|
InstanceReferenceSum (size_t count, const db::Matrix2d &m, const db::DVector &p)
|
||
|
|
: m_count (count), m_m (m), m_p (p)
|
||
|
|
{
|
||
|
|
// .. nothing yet ..
|
||
|
|
}
|
||
|
|
|
||
|
|
InstanceReferenceSum transformed (const db::CellInstArray &inst) const
|
||
|
|
{
|
||
|
|
db::Matrix2d m_res;
|
||
|
|
db::DVector p_res;
|
||
|
|
|
||
|
|
m_res += db::Matrix2d (inst.complex_trans ()) * double (inst.size ());
|
||
|
|
|
||
|
|
for (db::CellInstArray::iterator a = inst.begin (); ! a.at_end (); ++a) {
|
||
|
|
p_res += db::DVector ((*a).disp ());
|
||
|
|
}
|
||
|
|
|
||
|
|
if (m_count == 0) {
|
||
|
|
return InstanceReferenceSum (inst.size (), m_res, m_p + p_res);
|
||
|
|
} else {
|
||
|
|
return InstanceReferenceSum (m_count * inst.size (), m_m * m_res, m_p + m_m * p_res);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void add (const InstanceReferenceSum &other)
|
||
|
|
{
|
||
|
|
m_count += other.m_count;
|
||
|
|
m_p += db::DVector (other.m_p);
|
||
|
|
m_m += other.m_m;
|
||
|
|
}
|
||
|
|
|
||
|
|
size_t n () const { return m_count; }
|
||
|
|
const db::DVector &p () const { return m_p; }
|
||
|
|
const db::Matrix2d &m () const { return m_m; }
|
||
|
|
|
||
|
|
private:
|
||
|
|
size_t m_count;
|
||
|
|
db::Matrix2d m_m;
|
||
|
|
db::DVector m_p;
|
||
|
|
};
|
||
|
|
|
||
|
|
TEST(2)
|
||
|
|
{
|
||
|
|
for (int pass = 0; pass < 3; ++pass) {
|
||
|
|
|
||
|
|
db::Layout g;
|
||
|
|
db::Cell &a0 (g.cell (g.add_cell ("a0")));
|
||
|
|
// db::Cell &a1 (g.cell (g.add_cell ("a1")));
|
||
|
|
// db::Cell &a2 (g.cell (g.add_cell ("a2")));
|
||
|
|
// db::Cell &a3 (g.cell (g.add_cell ("a3")));
|
||
|
|
db::Cell &a4 (g.cell (g.add_cell ("a4")));
|
||
|
|
g.insert_layer (0);
|
||
|
|
a4.shapes (0).insert (db::Box (0, 0, 0, 0));
|
||
|
|
|
||
|
|
if (pass == 0) {
|
||
|
|
a0.insert (db::CellInstArray (db::CellInst (a4.cell_index ()), db::Trans (1/*r90*/), db::Vector(0, 10), db::Vector(10, 0), 5, 2));
|
||
|
|
} else if (pass == 1) {
|
||
|
|
a0.insert (db::CellInstArray (db::CellInst (a4.cell_index ()), db::ICplxTrans (1.0, 90.0, false, db::Vector(0, 0)), db::Vector(0, 10), db::Vector(10, 0), 5, 2));
|
||
|
|
} else if (pass == 2) {
|
||
|
|
a0.insert (db::CellInstArray (db::CellInst (a4.cell_index ()), db::ICplxTrans (0.1, 90.0, false, db::Vector(0, 0)), db::Vector(0, 10), db::Vector(10, 0), 5, 2));
|
||
|
|
}
|
||
|
|
|
||
|
|
db::Layout h;
|
||
|
|
db::Cell &b0 (h.cell (h.add_cell ("b0")));
|
||
|
|
db::Cell &b1 (h.cell (h.add_cell ("b1")));
|
||
|
|
db::Cell &b2 (h.cell (h.add_cell ("b2")));
|
||
|
|
db::Cell &b3 (h.cell (h.add_cell ("b3")));
|
||
|
|
db::Cell &b4 (h.cell (h.add_cell ("b4")));
|
||
|
|
h.insert_layer (0);
|
||
|
|
b4.shapes (0).insert (db::Box (0, 0, 0, 0));
|
||
|
|
|
||
|
|
if (pass < 2) {
|
||
|
|
b0.insert (db::CellInstArray (db::CellInst (b4.cell_index ()), db::Trans (1/*r90*/), db::Vector(0, 10), db::Vector(10, 0), 5, 1));
|
||
|
|
b0.insert (db::CellInstArray (db::CellInst (b1.cell_index ()), db::Trans (db::Vector (10, 0))));
|
||
|
|
b1.insert (db::CellInstArray (db::CellInst (b2.cell_index ()), db::Trans ()));
|
||
|
|
b1.insert (db::CellInstArray (db::CellInst (b2.cell_index ()), db::Trans (db::Vector (0, 20))));
|
||
|
|
b1.insert (db::CellInstArray (db::CellInst (b3.cell_index ()), db::Trans (db::Vector (0, 40))));
|
||
|
|
b2.insert (db::CellInstArray (db::CellInst (b3.cell_index ()), db::Trans (db::Vector (0, 0))));
|
||
|
|
b2.insert (db::CellInstArray (db::CellInst (b3.cell_index ()), db::Trans (db::Vector (0, 10))));
|
||
|
|
b3.insert (db::CellInstArray (db::CellInst (b4.cell_index ()), db::Trans (1/*r90*/)));
|
||
|
|
} else {
|
||
|
|
b0.insert (db::CellInstArray (db::CellInst (b4.cell_index ()), db::ICplxTrans (0.1, 90.0, false, db::Vector(0, 0)), db::Vector(0, 10), db::Vector(10, 0), 5, 1));
|
||
|
|
b0.insert (db::CellInstArray (db::CellInst (b1.cell_index ()), db::ICplxTrans (0.1, 0.0, false, db::Vector(10, 0))));
|
||
|
|
b1.insert (db::CellInstArray (db::CellInst (b2.cell_index ()), db::Trans ()));
|
||
|
|
b1.insert (db::CellInstArray (db::CellInst (b2.cell_index ()), db::Trans (db::Vector (0, 200))));
|
||
|
|
b1.insert (db::CellInstArray (db::CellInst (b3.cell_index ()), db::Trans (db::Vector (0, 400))));
|
||
|
|
b2.insert (db::CellInstArray (db::CellInst (b3.cell_index ()), db::Trans (db::Vector (0, 0))));
|
||
|
|
b2.insert (db::CellInstArray (db::CellInst (b3.cell_index ()), db::Trans (db::Vector (0, 100))));
|
||
|
|
b3.insert (db::CellInstArray (db::CellInst (b4.cell_index ()), db::Trans (1/*r90*/)));
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
|
||
|
|
db::InstanceStatistics<InstanceReferenceSum> rp (&g, a0.cell_index ());
|
||
|
|
InstanceReferenceSum v = rp.value (a4.cell_index ());
|
||
|
|
|
||
|
|
db::DPoint p;
|
||
|
|
db::Matrix2d m;
|
||
|
|
size_t n = 0;
|
||
|
|
for (db::RecursiveShapeIterator s (g, a0, 0); ! s.at_end (); ++s) {
|
||
|
|
db::Point q = s.trans () * s.shape ().bbox ().center ();
|
||
|
|
p += db::DVector (db::DPoint (q));
|
||
|
|
m += db::Matrix2d (s.trans ());
|
||
|
|
++n;
|
||
|
|
}
|
||
|
|
|
||
|
|
EXPECT_EQ (v.n (), n);
|
||
|
|
EXPECT_EQ (v.p ().to_string (), p.to_string ());
|
||
|
|
EXPECT_EQ (v.m ().to_string (), m.to_string ());
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
|
||
|
|
db::InstanceStatistics<InstanceReferenceSum> rp (&h, b0.cell_index ());
|
||
|
|
InstanceReferenceSum v = rp.value (b4.cell_index ());
|
||
|
|
|
||
|
|
db::DPoint p;
|
||
|
|
db::Matrix2d m;
|
||
|
|
size_t n = 0;
|
||
|
|
for (db::RecursiveShapeIterator s (h, b0, 0); ! s.at_end (); ++s) {
|
||
|
|
db::Point q = s.trans () * s.shape ().bbox ().center ();
|
||
|
|
p += db::DVector (db::DPoint (q));
|
||
|
|
m += db::Matrix2d (s.trans ());
|
||
|
|
++n;
|
||
|
|
}
|
||
|
|
|
||
|
|
EXPECT_EQ (v.n (), n);
|
||
|
|
EXPECT_EQ (v.p ().to_string (), p.to_string ());
|
||
|
|
EXPECT_EQ (v.m ().to_string (), m.to_string ());
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|