mirror of https://github.com/KLayout/klayout.git
WIP: network processor: net backannotation into original hierarchy.
This commit is contained in:
parent
6a2ddcda82
commit
df44c364ea
|
|
@ -1241,7 +1241,148 @@ hier_clusters<T>::clusters_per_cell (db::cell_index_type cell_index)
|
|||
return c->second;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static
|
||||
void put_or_propagate (const hier_clusters<T> &hc, incoming_cluster_connections<T> &inc, size_t cluster_id, const local_cluster<T> &cluster, db::Layout &layout, db::cell_index_type ci, const std::map<unsigned int, unsigned int> &lm, const db::ICplxTrans &trans)
|
||||
{
|
||||
db::Cell &target_cell = layout.cell (ci);
|
||||
|
||||
if (cluster_id > 0 && inc.has_incoming (ci, cluster_id)) {
|
||||
|
||||
typedef std::pair<db::cell_index_type, db::InstElement> reference_type;
|
||||
std::map<reference_type, bool> references;
|
||||
|
||||
for (db::Cell::parent_inst_iterator pi = target_cell.begin_parent_insts (); ! pi.at_end (); ++pi) {
|
||||
db::Instance i = pi->child_inst ();
|
||||
for (db::CellInstArray::iterator ii = i.cell_inst ().begin (); ! ii.at_end (); ++ii) {
|
||||
references.insert (std::make_pair (reference_type ((*pi).parent_cell_index (), db::InstElement (i, ii)), false));
|
||||
}
|
||||
}
|
||||
|
||||
const typename incoming_cluster_connections<T>::incoming_connections &connections = inc.incoming (ci, cluster_id);
|
||||
for (typename incoming_cluster_connections<T>::incoming_connections::const_iterator x = connections.begin (); x != connections.end (); ++x) {
|
||||
typename std::map<reference_type, bool>::iterator r = references.find (reference_type (x->parent_cell (), x->inst ()));
|
||||
if (r != references.end () && ! r->second) {
|
||||
put_or_propagate (hc, inc, x->parent_cluster_id (), cluster, layout, r->first.first, lm, r->first.second.complex_trans () * trans);
|
||||
r->second = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (typename std::map<reference_type, bool>::const_iterator r = references.begin (); r != references.end (); ++r) {
|
||||
if (! r->second) {
|
||||
put_or_propagate (hc, inc, 0, cluster, layout, r->first.first, lm, r->first.second.complex_trans () * trans);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (typename std::map<unsigned int, unsigned int>::const_iterator m = lm.begin (); m != lm.end (); ++m) {
|
||||
db::Shapes shapes;
|
||||
for (typename local_cluster<T>::shape_iterator s = cluster.begin (m->first); ! s.at_end (); ++s) {
|
||||
shapes.insert (*s);
|
||||
}
|
||||
tl::ident_map<db::properties_id_type> pm;
|
||||
target_cell.shapes (m->second).insert_transformed (shapes, trans, pm);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
hier_clusters<T>::return_to_hierarchy (db::Layout &layout, db::Cell &cell, const std::map<unsigned int, unsigned int> &lm) const
|
||||
{
|
||||
incoming_cluster_connections<T> inc (layout, cell, *this);
|
||||
|
||||
for (db::Layout::bottom_up_iterator c = layout.begin_bottom_up (); c != layout.end_bottom_up (); ++c) {
|
||||
const db::connected_clusters<T> &cc = clusters_per_cell (*c);
|
||||
for (typename db::connected_clusters<T>::const_iterator lc = cc.begin (); lc != cc.end (); ++lc) {
|
||||
put_or_propagate (*this, inc, lc->id (), *lc, layout, *c, lm, db::ICplxTrans ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC hier_clusters<db::PolygonRef>;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// incoming_cluster_connections implementation
|
||||
|
||||
template <class T>
|
||||
incoming_cluster_connections<T>::incoming_cluster_connections (const db::Layout &layout, const db::Cell &cell, const hier_clusters<T> &hc)
|
||||
: mp_layout (const_cast<db::Layout *> (&layout)), mp_hc (const_cast<hier_clusters<T> *> (&hc))
|
||||
{
|
||||
cell.collect_called_cells (m_called_cells);
|
||||
m_called_cells.insert (cell.cell_index ());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
incoming_cluster_connections<T>::has_incoming (db::cell_index_type ci, size_t cluster_id) const
|
||||
{
|
||||
std::map<db::cell_index_type, std::map<size_t, incoming_connections> >::const_iterator i = m_incoming.find (ci);
|
||||
if (i == m_incoming.end ()) {
|
||||
ensure_computed (ci);
|
||||
i = m_incoming.find (ci);
|
||||
tl_assert (i != m_incoming.end ());
|
||||
}
|
||||
|
||||
tl_assert (i != m_incoming.end ());
|
||||
return (i->second.find (cluster_id) != i->second.end ());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const typename incoming_cluster_connections<T>::incoming_connections &
|
||||
incoming_cluster_connections<T>::incoming (db::cell_index_type ci, size_t cluster_id) const
|
||||
{
|
||||
std::map<db::cell_index_type, std::map<size_t, incoming_connections> >::const_iterator i = m_incoming.find (ci);
|
||||
if (i == m_incoming.end ()) {
|
||||
ensure_computed (ci);
|
||||
i = m_incoming.find (ci);
|
||||
tl_assert (i != m_incoming.end ());
|
||||
}
|
||||
|
||||
std::map<size_t, incoming_connections>::const_iterator ii = i->second.find (cluster_id);
|
||||
if (ii != i->second.end ()) {
|
||||
return ii->second;
|
||||
} else {
|
||||
static incoming_connections empty;
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
incoming_cluster_connections<T>::ensure_computed (db::cell_index_type ci) const
|
||||
{
|
||||
tl_assert (mp_layout.get () != 0);
|
||||
m_incoming.insert (std::make_pair (ci, std::map<size_t, incoming_connections> ()));
|
||||
|
||||
const db::Cell &cell = mp_layout->cell (ci);
|
||||
for (db::Cell::parent_cell_iterator pc = cell.begin_parent_cells (); pc != cell.end_parent_cells (); ++pc) {
|
||||
if (m_called_cells.find (*pc) != m_called_cells.end ()) {
|
||||
ensure_computed_parent (*pc);
|
||||
}
|
||||
}
|
||||
|
||||
m_called_cells.erase (ci);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
incoming_cluster_connections<T>::ensure_computed_parent (db::cell_index_type ci) const
|
||||
{
|
||||
ensure_computed (ci);
|
||||
|
||||
const connected_clusters<T> &cc = ((const hier_clusters<T> *) mp_hc.get ())->clusters_per_cell (ci);
|
||||
for (typename connected_clusters<T>::connections_iterator x = cc.begin_connections (); x != cc.end_connections (); ++x) {
|
||||
for (typename connected_clusters<T>::connections_type::const_iterator xx = x->second.begin (); xx != x->second.end (); ++xx) {
|
||||
m_incoming [xx->inst ().inst_ptr.cell_index ()][xx->id ()].push_back (IncomingClusterInstance (ci, x->first, xx->inst ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// explicit instantiations
|
||||
template class DB_PUBLIC incoming_cluster_connections<db::PolygonRef>;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -443,6 +443,7 @@ public:
|
|||
typedef std::list<ClusterInstance> connections_type;
|
||||
typedef typename local_clusters<T>::box_type box_type;
|
||||
typedef connected_clusters_iterator<T> all_iterator;
|
||||
typedef typename std::map<typename local_cluster<T>::id_type, connections_type>::const_iterator connections_iterator;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
|
|
@ -488,6 +489,24 @@ public:
|
|||
return connected_clusters_iterator<T> (*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the connections
|
||||
*
|
||||
* The iterated object is a pair or (cluster id, connections_type).
|
||||
*/
|
||||
connections_iterator begin_connections () const
|
||||
{
|
||||
return m_connections.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the connections
|
||||
*/
|
||||
connections_iterator end_connections () const
|
||||
{
|
||||
return m_connections.end ();
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename> friend class connected_clusters_iterator;
|
||||
|
||||
|
|
@ -519,6 +538,7 @@ template <typename> class cell_clusters_box_converter;
|
|||
*/
|
||||
template <class T>
|
||||
class DB_PUBLIC hier_clusters
|
||||
: public tl::Object
|
||||
{
|
||||
public:
|
||||
typedef typename local_cluster<T>::box_type box_type;
|
||||
|
|
@ -543,6 +563,18 @@ public:
|
|||
*/
|
||||
connected_clusters<T> &clusters_per_cell (db::cell_index_type cell_index);
|
||||
|
||||
/**
|
||||
* @brief Writes the net shapes back to the original hierarchy
|
||||
*
|
||||
* The layout object is supposed to be the original layout or one with identical cell indexes.
|
||||
* "lm" is a layer mapping table from the connection layer indexes to the target layer
|
||||
* indexes.
|
||||
*
|
||||
* The backannotation process usually involves propagation of shapes up in the hierarchy
|
||||
* to resolve variants.
|
||||
*/
|
||||
void return_to_hierarchy (db::Layout &layout, db::Cell &cell, const std::map<unsigned int, unsigned int> &lm) const;
|
||||
|
||||
/**
|
||||
* @brief Clears this collection
|
||||
*/
|
||||
|
|
@ -557,6 +589,103 @@ private:
|
|||
std::map<db::cell_index_type, connected_clusters<T> > m_per_cell_clusters;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A connection to a cluster from a parent cluster
|
||||
*/
|
||||
class DB_PUBLIC IncomingClusterInstance
|
||||
{
|
||||
public:
|
||||
IncomingClusterInstance (db::cell_index_type pc, size_t parent_cluster_id, const db::InstElement &inst)
|
||||
: m_parent_cell (pc), m_parent_cluster_id (parent_cluster_id), m_inst (inst)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
IncomingClusterInstance ()
|
||||
: m_parent_cell (0), m_parent_cluster_id (0), m_inst ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the cell index of the parent cell
|
||||
*/
|
||||
size_t parent_cell () const
|
||||
{
|
||||
return m_parent_cell;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the cluster ID from which the cluster is connected to
|
||||
* The parent cluster lives in the parent cell
|
||||
*/
|
||||
size_t parent_cluster_id () const
|
||||
{
|
||||
return m_parent_cluster_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the instance path
|
||||
*/
|
||||
const db::InstElement &inst () const
|
||||
{
|
||||
return m_inst;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Equality
|
||||
*/
|
||||
bool operator== (const IncomingClusterInstance &other) const
|
||||
{
|
||||
return m_parent_cluster_id == other.m_parent_cluster_id && m_parent_cell == other.m_parent_cell && m_inst == other.m_inst;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Less operator
|
||||
*/
|
||||
bool operator< (const IncomingClusterInstance &other) const
|
||||
{
|
||||
if (m_parent_cluster_id != other.m_parent_cluster_id) {
|
||||
return m_parent_cluster_id < other.m_parent_cluster_id;
|
||||
}
|
||||
if (m_parent_cell != other.m_parent_cell) {
|
||||
return m_parent_cell < other.m_parent_cell;
|
||||
}
|
||||
return m_inst < other.m_inst;
|
||||
}
|
||||
|
||||
private:
|
||||
db::cell_index_type m_parent_cell;
|
||||
size_t m_parent_cluster_id;
|
||||
db::InstElement m_inst;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A class holding the parent relationships for clusters of cells
|
||||
*
|
||||
* This class can be used to quickly identify the connections made to a specific cluster from a parent cluster.
|
||||
*/
|
||||
template <class T>
|
||||
class incoming_cluster_connections
|
||||
{
|
||||
public:
|
||||
typedef std::list<IncomingClusterInstance> incoming_connections;
|
||||
|
||||
incoming_cluster_connections (const db::Layout &layout, const db::Cell &cell, const hier_clusters<T> &hc);
|
||||
|
||||
bool has_incoming (db::cell_index_type ci, size_t cluster_id) const;
|
||||
const incoming_connections &incoming (db::cell_index_type ci, size_t cluster_id) const;
|
||||
|
||||
private:
|
||||
mutable std::set<db::cell_index_type> m_called_cells;
|
||||
mutable std::map<db::cell_index_type, std::map<size_t, incoming_connections> > m_incoming;
|
||||
tl::weak_ptr<db::Layout> mp_layout;
|
||||
tl::weak_ptr<hier_clusters<T> > mp_hc;
|
||||
|
||||
void ensure_computed (db::cell_index_type ci) const;
|
||||
void ensure_computed_parent (db::cell_index_type ci) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -546,57 +546,129 @@ static void run_hc_test (tl::TestBase *_this, const std::string &file, const std
|
|||
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/" + au_file);
|
||||
}
|
||||
|
||||
static void run_hc_test_with_backannotation (tl::TestBase *_this, const std::string &file, const std::string &au_file)
|
||||
{
|
||||
db::Layout ly;
|
||||
unsigned int l1 = 0, l2 = 0, l3 = 0;
|
||||
|
||||
{
|
||||
db::LayerProperties p;
|
||||
db::LayerMap lmap;
|
||||
|
||||
p.layer = 1;
|
||||
p.datatype = 0;
|
||||
lmap.map (db::LDPair (p.layer, p.datatype), l1 = ly.insert_layer ());
|
||||
ly.set_properties (l1, p);
|
||||
|
||||
p.layer = 2;
|
||||
p.datatype = 0;
|
||||
lmap.map (db::LDPair (p.layer, p.datatype), l2 = ly.insert_layer ());
|
||||
ly.set_properties (l2, p);
|
||||
|
||||
p.layer = 3;
|
||||
p.datatype = 0;
|
||||
lmap.map (db::LDPair (p.layer, p.datatype), l3 = ly.insert_layer ());
|
||||
ly.set_properties (l3, p);
|
||||
|
||||
db::LoadLayoutOptions options;
|
||||
options.get_options<db::CommonReaderOptions> ().layer_map = lmap;
|
||||
options.get_options<db::CommonReaderOptions> ().create_other_layers = false;
|
||||
|
||||
std::string fn (tl::testsrc ());
|
||||
fn += "/testdata/algo/";
|
||||
fn += file;
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly, options);
|
||||
}
|
||||
|
||||
normalize_layer (ly, l1);
|
||||
normalize_layer (ly, l2);
|
||||
normalize_layer (ly, l3);
|
||||
|
||||
// connect 1 to 1, 1 to 2 and 1 to 3, but *not* 2 to 3
|
||||
db::Connectivity conn;
|
||||
conn.connect (l1, l1);
|
||||
conn.connect (l2, l2);
|
||||
conn.connect (l3, l3);
|
||||
conn.connect (l1, l2);
|
||||
conn.connect (l1, l3);
|
||||
|
||||
db::hier_clusters<db::PolygonRef> hc;
|
||||
hc.build (ly, ly.cell (*ly.begin_top_down ()), db::ShapeIterator::Polygons, conn);
|
||||
|
||||
std::map<unsigned int, unsigned int> lm;
|
||||
lm[l1] = ly.insert_layer (db::LayerProperties (101, 0));
|
||||
lm[l2] = ly.insert_layer (db::LayerProperties (102, 0));
|
||||
lm[l3] = ly.insert_layer (db::LayerProperties (103, 0));
|
||||
hc.return_to_hierarchy (ly, ly.cell (*ly.begin_top_down ()), lm);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/" + au_file);
|
||||
}
|
||||
|
||||
TEST(41_HierClusters)
|
||||
{
|
||||
run_hc_test (_this, "hc_test_l1.gds", "hc_test_au1.gds");
|
||||
run_hc_test_with_backannotation (_this, "hc_test_l1.gds", "hc_test_au1b.gds");
|
||||
}
|
||||
|
||||
TEST(42_HierClusters)
|
||||
{
|
||||
run_hc_test (_this, "hc_test_l2.gds", "hc_test_au2.gds");
|
||||
run_hc_test_with_backannotation (_this, "hc_test_l2.gds", "hc_test_au2b.gds");
|
||||
}
|
||||
|
||||
TEST(43_HierClusters)
|
||||
{
|
||||
run_hc_test (_this, "hc_test_l3.gds", "hc_test_au3.gds");
|
||||
run_hc_test_with_backannotation (_this, "hc_test_l3.gds", "hc_test_au3b.gds");
|
||||
}
|
||||
|
||||
TEST(44_HierClusters)
|
||||
{
|
||||
run_hc_test (_this, "hc_test_l4.gds", "hc_test_au4.gds");
|
||||
run_hc_test_with_backannotation (_this, "hc_test_l4.gds", "hc_test_au4b.gds");
|
||||
}
|
||||
|
||||
TEST(45_HierClusters)
|
||||
{
|
||||
run_hc_test (_this, "hc_test_l5.gds", "hc_test_au5.gds");
|
||||
run_hc_test_with_backannotation (_this, "hc_test_l5.gds", "hc_test_au5b.gds");
|
||||
}
|
||||
|
||||
TEST(46_HierClusters)
|
||||
{
|
||||
run_hc_test (_this, "hc_test_l6.gds", "hc_test_au6.gds");
|
||||
run_hc_test_with_backannotation (_this, "hc_test_l6.gds", "hc_test_au6b.gds");
|
||||
}
|
||||
|
||||
TEST(47_HierClusters)
|
||||
{
|
||||
run_hc_test (_this, "hc_test_l7.gds", "hc_test_au7.gds");
|
||||
run_hc_test_with_backannotation (_this, "hc_test_l7.gds", "hc_test_au7b.gds");
|
||||
}
|
||||
|
||||
TEST(48_HierClusters)
|
||||
{
|
||||
run_hc_test (_this, "hc_test_l8.gds", "hc_test_au8.gds");
|
||||
run_hc_test_with_backannotation (_this, "hc_test_l8.gds", "hc_test_au8b.gds");
|
||||
}
|
||||
|
||||
TEST(49_HierClusters)
|
||||
{
|
||||
run_hc_test (_this, "hc_test_l9.gds", "hc_test_au9.gds");
|
||||
run_hc_test_with_backannotation (_this, "hc_test_l9.gds", "hc_test_au9b.gds");
|
||||
}
|
||||
|
||||
TEST(50_HierClusters)
|
||||
{
|
||||
run_hc_test (_this, "hc_test_l10.gds", "hc_test_au10.gds");
|
||||
run_hc_test_with_backannotation (_this, "hc_test_l10.gds", "hc_test_au10b.gds");
|
||||
}
|
||||
|
||||
TEST(51_HierClusters)
|
||||
{
|
||||
run_hc_test (_this, "hc_test_l11.gds", "hc_test_au11.gds");
|
||||
run_hc_test_with_backannotation (_this, "hc_test_l4.gds", "hc_test_au4b.gds");
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue