WIP: first steps for network processor.

This commit is contained in:
Matthias Koefferlein 2018-12-01 09:38:16 +01:00
parent 970f22960f
commit 3609bdda81
5 changed files with 435 additions and 2 deletions

View File

@ -140,7 +140,8 @@ SOURCES = \
dbHierarchyBuilder.cc \
dbLocalOperation.cc \
dbHierProcessor.cc \
dbDeepRegion.cc
dbDeepRegion.cc \
dbHierNetworkProcessor.cc
HEADERS = \
dbArray.h \

View File

@ -0,0 +1,217 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2018 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 "dbHierNetworkProcessor.h"
#include "dbShape.h"
#include "dbShapes.h"
#include "dbInstElement.h"
#include "dbPolygon.h"
#include "dbPolygonTools.h"
#include "dbBoxConvert.h"
#include <vector>
#include <map>
namespace db
{
// ------------------------------------------------------------------------------
// Connectivity implementation
Connectivity::Connectivity ()
{
// .. nothing yet ..
}
void
Connectivity::connect (unsigned int la, unsigned int lb)
{
m_connected [la].insert (lb);
m_connected [lb].insert (la);
m_all_layers.insert (la);
m_all_layers.insert (lb);
}
void
Connectivity::connect (unsigned int l)
{
m_connected [l].insert (l);
m_all_layers.insert (l);
}
Connectivity::layer_iterator
Connectivity::begin_layers ()
{
return m_all_layers.begin ();
}
Connectivity::layer_iterator
Connectivity::end_layers ()
{
return m_all_layers.end ();
}
Connectivity::layers_type s_empty_layers;
Connectivity::layer_iterator
Connectivity::begin_connected (unsigned int layer)
{
std::map<unsigned int, layers_type>::const_iterator i = m_connected.find (layer);
if (i == m_connected.end ()) {
return s_empty_layers.begin ();
} else {
return i->second.begin ();
}
}
Connectivity::layer_iterator
Connectivity::end_connected (unsigned int layer)
{
std::map<unsigned int, layers_type>::const_iterator i = m_connected.find (layer);
if (i == m_connected.end ()) {
return s_empty_layers.end ();
} else {
return i->second.end ();
}
}
static bool
interaction_test (const db::PolygonRef &a, const db::PolygonRef &b)
{
// TODO: this could be part of db::interact (including transformation)
if (a.obj ().is_box () && b.obj ().is_box ()) {
return db::interact (a.obj ().box ().transformed (b.trans ().inverted () * a.trans ()), b.obj ().box ());
} else {
return db::interact (a.obj ().transformed (b.trans ().inverted () * a.trans ()), b.obj ());
}
}
template <class T>
bool Connectivity::interacts (const T &a, unsigned int la, T &b, unsigned int lb) const
{
std::map<unsigned int, layers_type>::const_iterator i = m_connected.find (la);
if (i == m_connected.end () || i->second.find (lb) == i->second.end ()) {
return false;
} else {
return interaction_test (a, b);
}
}
// explicit instantiations
template DB_PUBLIC bool Connectivity::interacts<db::PolygonRef> (const db::PolygonRef &a, unsigned int la, db::PolygonRef &b, unsigned int lb) const;
// ------------------------------------------------------------------------------
// ...
#if 0
/**
* @brief Represents a cluster of shapes
*
* A cluster of shapes is a set of shapes which are connected in terms
* of a given connectivity.
*/
class LocalCluster
{
public:
typedef size_t id_type;
LocalCluster ();
void connect (const db::Shape &a, unsigned int la, const db::Shape &b, unsigned int lb);
id_type id () const;
// @@@ Trans is the transformation of the cluster to the shape (instance transformation)
void interacts (const db::Shape &s, unsigned int ls, const db::ICplxTrans &trans, const Connectivity &conn);
const db::Box &bbox () const;
private:
friend class LocalClusters;
void set_id (id_type id);
};
/**
* @brief Represents a collection of clusters in a cell
*
* After all shapes in a cell are connected, the cluster collection is filled if
* disconnected clusters.
*/
class LocalClusters
{
public:
LocalClusters ();
// @@@ needs to be fast(!)
LocalCluster::id_type cluster_id_for_shape (const db::Shape &s, unsigned int ls) const;
const LocalCluster &cluster (LocalCluster::id_type id) const;
LocalCluster &create_cluster ();
void remove_cluster (LocalCluster::id_type id);
cluster_iterator find (const db::Box &region);
// @@@ Trans is the transformation of the clusters to the shape (instance transformation)
std::vector<unsigned int> interacting_clusters (const db::Shape &s, unsigned int ls, const db::ICplxTrans &trans, const Connectivity &conn) const;
// @@@ Trans is the transformation of the clusters to the clusters looked up (instance transformation)
std::vector<unsigned int> interacting_clusters (const LocalClusters &c, const db::ICplxTrans &trans, const Connectivity &conn) const;
};
/**
* @brief Represents all clusters in a cell and their connections to child cells
*
* Connections to indirect children are made through empty dummy clusters.
* Also, connections between two clusters of different children without
* mediating cluster on cell level are made through empty dummy clusters.
* Hence, there is always a cluster in the parent cell which connects to
* clusters from child cells.
*/
class HierarchicalClusters
{
public:
HierarchicalClusters ();
LocalClusters &local ();
// build local clusters
// determine local to cell cluster interactions -> top-down connection, maybe across dummy
// identify cell overlaps
// determine cell-to-cell cluster interactions -> make dummy cluster to connect both, connect to each child
// maybe across dummy cluster
// shall be called bottom-up
void build_clusters (const db::Cell &cell, const Connectivity &conn);
// @@@ trans is the transformation from child to this (instance transformation)
// used by child clusters to verify whether they are connected somewhere in the parent
LocalCluster::id_type is_connected_to (LocalCluster::id_type id, const db::InstElement &trans) const;
// connections to subcells (== pins?)
const std::vector<std::pair<LocalCluster::id_type, db::InstElement> > &top_down_connections (LocalCluster::id_type) const;
// propagate all connected clusters to their parents
// -> creates new local clusters, removes them from their local set
// used by the merge step to form local-only clusters
// can be called bottom-up
void propagate_connected ();
};
#endif
}

View File

@ -0,0 +1,97 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2018 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
*/
#ifndef HDR_dbHierNetworkProcessor
#define HDR_dbHierNetworkProcessor
#include "dbCommon.h"
#include <map>
#include <set>
namespace db {
/**
* @brief Defines the connectivity
*
* Connectivity is defined in terms of layers. Certain layer pairs
* are connected when shapes on their layers interact.
* Connectivity includes intra-layer connectivity - i.e.
* shapes on a layer are not connected by default. They need to
* be connected explicitly using "connect(layer)".
*/
class DB_PUBLIC Connectivity
{
public:
typedef std::set<unsigned int> layers_type;
typedef layers_type::const_iterator layer_iterator;
/**
* @brief Creates a connectivity object without any connections
*/
Connectivity ();
/**
* @brief Adds inter-layer connectivity
*/
void connect (unsigned int la, unsigned int lb);
/**
* @brief Adds intra-layer connectivity for layer l
*/
void connect (unsigned int l);
/**
* @brief Begin iterator for the layers involved
*/
layer_iterator begin_layers ();
/**
* @brief End iterator for the layers involved
*/
layer_iterator end_layers ();
/**
* @brief Begin iterator for the layers connected to a specific layer
*/
layer_iterator begin_connected (unsigned int layer);
/**
* @brief End iterator for the layers connected to a specific layer
*/
layer_iterator end_connected (unsigned int layer);
/**
* @brief Returns true, if the given shapes on the given layers interact
*/
template <class T>
bool interacts (const T &a, unsigned int la, T &b, unsigned int lb) const;
private:
layers_type m_all_layers;
std::map<unsigned int, layers_type> m_connected;
};
}
#endif

View File

@ -0,0 +1,117 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2018 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 "tlUnitTest.h"
#include "dbHierNetworkProcessor.h"
#include "dbTestSupport.h"
#include "dbShapeRepository.h"
#include "dbPolygon.h"
#include "dbPath.h"
#include "dbText.h"
static std::string l2s (db::Connectivity::layer_iterator b, db::Connectivity::layer_iterator e)
{
std::string s;
for (db::Connectivity::layer_iterator i = b; i != e; ++i) {
if (! s.empty ()) {
s += ",";
}
s += tl::to_string (*i);
}
return s;
}
TEST(1_Connectivity)
{
db::Connectivity conn;
EXPECT_EQ (l2s (conn.begin_layers (), conn.end_layers ()), "");
conn.connect (0);
EXPECT_EQ (l2s (conn.begin_layers (), conn.end_layers ()), "0");
EXPECT_EQ (l2s (conn.begin_connected (0), conn.end_connected (0)), "0");
EXPECT_EQ (l2s (conn.begin_connected (1), conn.end_connected (1)), "");
conn.connect (0, 1);
EXPECT_EQ (l2s (conn.begin_layers (), conn.end_layers ()), "0,1");
EXPECT_EQ (l2s (conn.begin_connected (0), conn.end_connected (0)), "0,1");
EXPECT_EQ (l2s (conn.begin_connected (1), conn.end_connected (1)), "0");
conn.connect (1);
EXPECT_EQ (l2s (conn.begin_connected (1), conn.end_connected (1)), "0,1");
conn.connect (0, 2);
conn.connect (2);
EXPECT_EQ (l2s (conn.begin_connected (0), conn.end_connected (0)), "0,1,2");
EXPECT_EQ (l2s (conn.begin_connected (1), conn.end_connected (1)), "0,1");
EXPECT_EQ (l2s (conn.begin_connected (2), conn.end_connected (2)), "0,2");
}
TEST(2_ShapeInteractions)
{
db::Connectivity conn;
conn.connect (0);
conn.connect (1);
conn.connect (0, 1);
db::Polygon poly;
tl::from_string ("(0,0;0,1000;1000,1000;1000,0)", poly);
db::GenericRepository repo;
db::PolygonRef ref1 (poly, repo);
db::PolygonRef ref2 (poly.transformed (db::Trans (db::Vector (0, 10))), repo);
db::PolygonRef ref3 (poly.transformed (db::Trans (db::Vector (0, 2000))), repo);
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 0), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 1), true);
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 0), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 0), false);
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 1), false);
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 2), false);
}
TEST(2_ShapeInteractionsRealPolygon)
{
db::Connectivity conn;
conn.connect (0);
conn.connect (1);
conn.connect (0, 1);
db::Polygon poly;
tl::from_string ("(0,0;0,1000;500,1000;500,1500;1000,1500;1000,0)", poly);
db::GenericRepository repo;
db::PolygonRef ref1 (poly, repo);
db::PolygonRef ref2 (poly.transformed (db::Trans (db::Vector (0, 10))), repo);
db::PolygonRef ref3 (poly.transformed (db::Trans (db::Vector (0, 2000))), repo);
db::PolygonRef ref4 (poly.transformed (db::Trans (db::Vector (0, 1500))), repo);
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 0), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 1), true);
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 0), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 0), false);
EXPECT_EQ (conn.interacts (ref1, 0, ref4, 0), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 1), false);
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 2), false);
}

View File

@ -57,7 +57,8 @@ SOURCES = \
dbRecursiveShapeIteratorTests.cc \
dbHierProcessorTests.cc \
dbDeepRegionTests.cc \
dbDeepShapeStoreTests.cc
dbDeepShapeStoreTests.cc \
dbHierNetworkProcessorTests.cc
INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC
DEPENDPATH += $$TL_INC $$DB_INC $$GSI_INC