Skip to content

Commit

Permalink
Issue 1609 (#1613)
Browse files Browse the repository at this point in the history
* Fixed issue #1609 (Cell.read doesn't read LayoutMetaInfo)

This also includes some more functions:
- Layout#merge_meta_info, Layout#copy_meta_info
- Layout#clear_all_meta_info
- Cell#merge_meta_info, Cell#copy_meta_info

In addition, meta info is merged when importing a layout from
another file (Layout/Import -> Other Layouts into current).

* Meta info support in layout diff (for testing), implemented meta info merge for GDS and OASIS readers with special conflict resolution modes

* Undo support for meta info - this way we do not loose meta info when we delete a cell and undo

---------

Co-authored-by: Matthias Koefferlein <[email protected]>
  • Loading branch information
klayoutmatthias and Matthias Koefferlein authored Feb 11, 2024
1 parent 5de32c3 commit df59641
Show file tree
Hide file tree
Showing 23 changed files with 689 additions and 29 deletions.
24 changes: 17 additions & 7 deletions src/db/db/dbCommonReader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ CommonReaderBase::rename_cell (db::Layout &layout, size_t id, const std::string

// Both cells already exist and are not identical: merge ID-declared cell into the name-declared one
layout.force_update ();
merge_cell (layout, iname->second.second, iid->second.second);
merge_cell (layout, iname->second.second, iid->second.second, true);
iid->second.second = iname->second.second;

}
Expand Down Expand Up @@ -235,7 +235,7 @@ CommonReaderBase::cell_for_instance (db::Layout &layout, const std::string &cn)
}

void
CommonReaderBase::merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const
CommonReaderBase::merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta) const
{
const db::Cell &src_cell = layout.cell (src_cell_index);
db::Cell &target_cell = layout.cell (target_cell_index);
Expand All @@ -249,11 +249,11 @@ CommonReaderBase::merge_cell (db::Layout &layout, db::cell_index_type target_cel
}
}

merge_cell_without_instances (layout, target_cell_index, src_cell_index);
merge_cell_without_instances (layout, target_cell_index, src_cell_index, with_meta);
}

void
CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const
CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta) const
{
const db::Cell &src_cell = layout.cell (src_cell_index);
db::Cell &target_cell = layout.cell (target_cell_index);
Expand All @@ -268,6 +268,16 @@ CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_ind
// replace all instances of the new cell with the original one
layout.replace_instances_of (src_cell.cell_index (), target_cell.cell_index ());

// merge meta info
if (with_meta) {
auto ib = layout.begin_meta (src_cell.cell_index ());
auto ie = layout.end_meta (src_cell.cell_index ());
for (auto i = ib; i != ie; ++i) {
layout.add_meta_info (target_cell.cell_index (), i->first, i->second);
}
}
layout.clear_meta (src_cell.cell_index ());

// finally delete the new cell
layout.delete_cell (src_cell.cell_index ());
}
Expand Down Expand Up @@ -371,19 +381,19 @@ CommonReaderBase::finish (db::Layout &layout)

layout.cell (ci_org).clear_shapes ();

merge_cell (layout, ci_org, ci_new);
merge_cell (layout, ci_org, ci_new, true);

} else if (m_cc_resolution == SkipNewCell && ! layout.cell (ci_org).is_ghost_cell ()) {

layout.prune_subcells (ci_new);
layout.cell (ci_new).clear_shapes ();

// NOTE: ignore instances -> this saves us a layout update
merge_cell_without_instances (layout, ci_org, ci_new);
merge_cell_without_instances (layout, ci_org, ci_new, false);

} else {

merge_cell (layout, ci_org, ci_new);
merge_cell (layout, ci_org, ci_new, m_cc_resolution != SkipNewCell);

}

Expand Down
4 changes: 2 additions & 2 deletions src/db/db/dbCommonReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,12 @@ class DB_PUBLIC CommonReaderBase
/**
* @brief Merge (and delete) the src_cell into target_cell
*/
void merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const;
void merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta) const;

/**
* @brief Merge (and delete) the src_cell into target_cell without instances
*/
void merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const;
void merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index, bool with_meta) const;

/**
* @brief Gets the layer name map
Expand Down
178 changes: 177 additions & 1 deletion src/db/db/dbLayout.cc
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,83 @@ struct InsertRemoveLayerOp
bool m_insert;
};

struct SetLayoutMetaInfoOp
: public LayoutOp
{
SetLayoutMetaInfoOp (db::Layout::meta_info_name_id_type name_id, const db::MetaInfo *f, const db::MetaInfo *t)
: m_name_id (name_id), m_has_from (f != 0), m_has_to (t != 0)
{
if (f) {
m_from = *f;
}
if (t) {
m_to = *t;
}
}

virtual void redo (db::Layout *layout) const
{
if (! m_has_to) {
layout->remove_meta_info (m_name_id);
} else {
layout->add_meta_info (m_name_id, m_to);
}
}

virtual void undo (db::Layout *layout) const
{
if (! m_has_from) {
layout->remove_meta_info (m_name_id);
} else {
layout->add_meta_info (m_name_id, m_from);
}
}

private:
db::Layout::meta_info_name_id_type m_name_id;
bool m_has_from, m_has_to;
db::MetaInfo m_from, m_to;
};

struct SetCellMetaInfoOp
: public LayoutOp
{
SetCellMetaInfoOp (db::cell_index_type ci, db::Layout::meta_info_name_id_type name_id, const db::MetaInfo *f, const db::MetaInfo *t)
: m_ci (ci), m_name_id (name_id), m_has_from (f != 0), m_has_to (t != 0)
{
if (f) {
m_from = *f;
}
if (t) {
m_to = *t;
}
}

virtual void redo (db::Layout *layout) const
{
if (! m_has_to) {
layout->remove_meta_info (m_ci, m_name_id);
} else {
layout->add_meta_info (m_ci, m_name_id, m_to);
}
}

virtual void undo (db::Layout *layout) const
{
if (! m_has_from) {
layout->remove_meta_info (m_ci, m_name_id);
} else {
layout->add_meta_info (m_ci, m_name_id, m_from);
}
}

private:
db::cell_index_type m_ci;
db::Layout::meta_info_name_id_type m_name_id;
bool m_has_from, m_has_to;
db::MetaInfo m_from, m_to;
};

// -----------------------------------------------------------------
// Implementation of the ProxyContextInfo class

Expand Down Expand Up @@ -848,6 +925,9 @@ Layout::delete_cells (const std::set<cell_index_type> &cells_to_delete)
// cell child objects that must remain.
for (std::set<cell_index_type>::const_iterator c = cells_to_delete.begin (); c != cells_to_delete.end (); ++c) {

// supports undo
clear_meta (*c);

if (manager () && manager ()->transacting ()) {

// note the "take" method - this takes out the cell
Expand Down Expand Up @@ -917,9 +997,12 @@ Layout::delete_cell (cell_index_type id)
// a backup container for the cell. This is necessary since the ID's within manager are given to
// cell child objects that must remain.

// supports undo
clear_meta (id);

if (manager () && manager ()->transacting ()) {

// not the "take" method - this takes out the cell
// note the "take" method - this takes out the cell
std::string cn (cell_name (id));
manager ()->queue (this, new NewRemoveCellOp (id, cn, true /*remove*/, take_cell (id)));

Expand Down Expand Up @@ -1869,18 +1952,36 @@ Layout::meta_info_name_id (const std::string &name) const
void
Layout::clear_meta ()
{
if (manager () && manager ()->transacting ()) {
for (auto i = m_meta_info.begin (); i != m_meta_info.end (); ++i) {
manager ()->queue (this, new SetLayoutMetaInfoOp (i->first, &i->second, 0));
}
}

m_meta_info.clear ();
}

void
Layout::add_meta_info (meta_info_name_id_type name_id, const MetaInfo &i)
{
if (manager () && manager ()->transacting ()) {
auto e = m_meta_info.find (name_id);
manager ()->queue (this, new SetLayoutMetaInfoOp (name_id, e != m_meta_info.end () ? &e->second : 0, &i));
}

m_meta_info[name_id] = i;
}

void
Layout::remove_meta_info (meta_info_name_id_type name_id)
{
if (manager () && manager ()->transacting ()) {
auto e = m_meta_info.find (name_id);
if (e != m_meta_info.end ()) {
manager ()->queue (this, new SetLayoutMetaInfoOp (name_id, &e->second, 0));
}
}

m_meta_info.erase (name_id);
}

Expand All @@ -1901,19 +2002,60 @@ Layout::has_meta_info (meta_info_name_id_type name_id) const
void
Layout::clear_meta (db::cell_index_type ci)
{
if (manager () && manager ()->transacting ()) {
auto ib = begin_meta (ci);
auto ie = end_meta (ci);
for (auto i = ib; i != ie; ++i) {
manager ()->queue (this, new SetCellMetaInfoOp (ci, i->first, &i->second, 0));
}
}

m_meta_info_by_cell.erase (ci);
}

void
Layout::clear_all_meta ()
{
clear_meta ();
while (! m_meta_info_by_cell.empty ()) {
clear_meta (m_meta_info_by_cell.begin ()->first);
}
}

void
Layout::add_meta_info (db::cell_index_type ci, meta_info_name_id_type name_id, const MetaInfo &i)
{
if (manager () && manager ()->transacting ()) {
const MetaInfo *from = 0;
auto c = m_meta_info_by_cell.find (ci);
if (c != m_meta_info_by_cell.end ()) {
auto e = c->second.find (name_id);
if (e != c->second.end ()) {
from = &e->second;
}
}
manager ()->queue (this, new SetCellMetaInfoOp (ci, name_id, from, &i));
}

m_meta_info_by_cell[ci][name_id] = i;
}

void
Layout::remove_meta_info (db::cell_index_type ci, meta_info_name_id_type name_id)
{
auto c = m_meta_info_by_cell.find (ci);

if (manager () && manager ()->transacting ()) {
const MetaInfo *from = 0;
if (c != m_meta_info_by_cell.end ()) {
auto e = c->second.find (name_id);
if (e != c->second.end ()) {
from = &e->second;
}
}
manager ()->queue (this, new SetCellMetaInfoOp (ci, name_id, from, 0));
}

if (c != m_meta_info_by_cell.end ()) {
c->second.erase (name_id);
}
Expand Down Expand Up @@ -1945,6 +2087,40 @@ Layout::has_meta_info (db::cell_index_type ci, meta_info_name_id_type name_id) c
}
}

void
Layout::merge_meta_info (const db::Layout &other)
{
for (auto mi = other.begin_meta (); mi != other.end_meta (); ++mi) {
add_meta_info (other.meta_info_name (mi->first), mi->second);
}
}

void
Layout::merge_meta_info (db::cell_index_type into_cell, const db::Layout &other, db::cell_index_type other_cell)
{
auto mi_begin = other.begin_meta (other_cell);
auto mi_end = other.end_meta (other_cell);
for (auto mi = mi_begin; mi != mi_end; ++mi) {
add_meta_info (into_cell, other.meta_info_name (mi->first), mi->second);
}
}

void
Layout::merge_meta_info (const db::Layout &other, const db::CellMapping &cm)
{
for (auto i = cm.begin (); i != cm.end (); ++i) {
merge_meta_info (i->second, other, i->first);
}
}

void
Layout::copy_meta_info (const db::Layout &other, const db::CellMapping &cm)
{
for (auto i = cm.begin (); i != cm.end (); ++i) {
copy_meta_info (i->second, other, i->first);
}
}

void
Layout::swap_layers (unsigned int a, unsigned int b)
{
Expand Down
49 changes: 49 additions & 0 deletions src/db/db/dbLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -1993,6 +1993,11 @@ class DB_PUBLIC Layout
*/
void clear_meta (db::cell_index_type ci);

/**
* @brief Clears all meta information (cells and layout)
*/
void clear_all_meta ();

/**
* @brief Adds meta information for a given cell
* The given meta information object is to the meta information list for the given cell.
Expand Down Expand Up @@ -2021,6 +2026,50 @@ class DB_PUBLIC Layout
}
}

/**
* @brief Merges meta information from the other layout into self
* This applies to the layout-only meta information. Same keys get overwritten, new ones are added.
*/
void merge_meta_info (const db::Layout &other);

/**
* @brief Copies meta information from the other layout into self
* This applies to the layout-only meta information. All keys are replaced.
*/
void copy_meta_info (const db::Layout &other)
{
clear_meta ();
merge_meta_info (other);
}

/**
* @brief Merges meta information from the other cell into the target cell from sel.
* This applies to the cell-specific meta information. Same keys get overwritten, new ones are added.
*/
void merge_meta_info (db::cell_index_type into_cell, const db::Layout &other, db::cell_index_type other_cell);

/**
* @brief Copies meta information from the other cell into the target cell from sel.
* This applies to the cell-specific meta information. All keys are replaced.
*/
void copy_meta_info (db::cell_index_type into_cell, const db::Layout &other, db::cell_index_type other_cell)
{
clear_meta (into_cell);
merge_meta_info (into_cell, other, other_cell);
}

/**
* @brief Merges meta information from the other cell into the target cell from sel using the given cell mapping.
* The cell mapping specifies which meta information to merge from which cell into which cell.
*/
void merge_meta_info (const db::Layout &other, const db::CellMapping &cm);

/**
* @brief Copies meta information from the other cell into the target cell from sel using the given cell mapping.
* The cell mapping specifies which meta information to copy from which cell into which cell.
*/
void copy_meta_info (const db::Layout &other, const db::CellMapping &cm);

/**
* @brief Gets a value indicating whether a meta info with the given name is present for the given cell
*/
Expand Down
Loading

0 comments on commit df59641

Please sign in to comment.