WIP: network processor: net backannotation into original hierarchy.

This commit is contained in:
Matthias Koefferlein 2018-12-08 01:55:02 +01:00
parent 6a2ddcda82
commit df44c364ea
13 changed files with 342 additions and 0 deletions

View File

@ -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>;
}

View File

@ -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

View File

@ -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");
}

BIN
testdata/algo/hc_test_au10b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/hc_test_au1b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/hc_test_au2b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/hc_test_au3b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/hc_test_au4b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/hc_test_au5b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/hc_test_au6b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/hc_test_au7b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/hc_test_au8b.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/hc_test_au9b.gds vendored Normal file

Binary file not shown.