mirror of https://github.com/KLayout/klayout.git
Issue 1609 (#1613)
* 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 <matthias@klayout.de>
This commit is contained in:
parent
edafd01fdb
commit
5712c8a85c
|
|
@ -164,7 +164,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;
|
||||
|
||||
}
|
||||
|
|
@ -239,7 +239,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);
|
||||
|
|
@ -253,11 +253,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);
|
||||
|
|
@ -272,6 +272,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 ());
|
||||
}
|
||||
|
|
@ -375,7 +385,7 @@ 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 ()) {
|
||||
|
||||
|
|
@ -383,11 +393,11 @@ CommonReaderBase::finish (db::Layout &layout)
|
|||
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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -242,12 +242,12 @@ protected:
|
|||
/**
|
||||
* @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
|
||||
|
|
|
|||
|
|
@ -257,6 +257,83 @@ private:
|
|||
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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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)));
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -1901,12 +2002,41 @@ 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;
|
||||
}
|
||||
|
||||
|
|
@ -1914,6 +2044,18 @@ 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);
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1993,6 +1993,11 @@ public:
|
|||
*/
|
||||
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.
|
||||
|
|
@ -2021,6 +2026,50 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -702,6 +702,29 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
r.dbu_differs (a.dbu (), b.dbu ());
|
||||
}
|
||||
|
||||
if ((flags & layout_diff::f_with_meta) != 0) {
|
||||
std::map<std::string, std::pair<tl::Variant, tl::Variant> > mi;
|
||||
for (auto i = a.begin_meta (); i != a.end_meta (); ++i) {
|
||||
if (i->second.persisted) {
|
||||
mi [a.meta_info_name (i->first)].first = i->second.value;
|
||||
}
|
||||
}
|
||||
for (auto i = b.begin_meta (); i != b.end_meta (); ++i) {
|
||||
if (i->second.persisted) {
|
||||
mi [b.meta_info_name (i->first)].second = i->second.value;
|
||||
}
|
||||
}
|
||||
for (auto i = mi.begin (); i != mi.end (); ++i) {
|
||||
if (i->second.first != i->second.second) {
|
||||
differs = true;
|
||||
if (flags & layout_diff::f_silent) {
|
||||
return false;
|
||||
}
|
||||
r.layout_meta_info_differs (i->first, i->second.first, i->second.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool verbose = (flags & layout_diff::f_verbose);
|
||||
bool no_duplicates = (flags & layout_diff::f_ignore_duplicates);
|
||||
|
||||
|
|
@ -928,6 +951,33 @@ do_compare_layouts (const db::Layout &a, const db::Cell *top_a, const db::Layout
|
|||
|
||||
r.begin_cell (common_cells [cci], common_cells_a [cci], common_cells_b [cci]);
|
||||
|
||||
if ((flags & layout_diff::f_with_meta) != 0) {
|
||||
std::map<std::string, std::pair<tl::Variant, tl::Variant> > mi;
|
||||
auto ib = a.begin_meta (common_cells_a [cci]);
|
||||
auto ie = a.end_meta (common_cells_a [cci]);
|
||||
for (auto i = ib; i != ie; ++i) {
|
||||
if (i->second.persisted) {
|
||||
mi [a.meta_info_name (i->first)].first = i->second.value;
|
||||
}
|
||||
}
|
||||
ib = b.begin_meta (common_cells_b [cci]);
|
||||
ie = b.end_meta (common_cells_b [cci]);
|
||||
for (auto i = ib; i != ie; ++i) {
|
||||
if (i->second.persisted) {
|
||||
mi [b.meta_info_name (i->first)].second = i->second.value;
|
||||
}
|
||||
}
|
||||
for (auto i = mi.begin (); i != mi.end (); ++i) {
|
||||
if (i->second.first != i->second.second) {
|
||||
differs = true;
|
||||
if (flags & layout_diff::f_silent) {
|
||||
return false;
|
||||
}
|
||||
r.cell_meta_info_differs (i->first, i->second.first, i->second.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!verbose && cell_a->bbox () != cell_b->bbox ()) {
|
||||
differs = true;
|
||||
if (flags & layout_diff::f_silent) {
|
||||
|
|
@ -1215,6 +1265,7 @@ public:
|
|||
}
|
||||
|
||||
void dbu_differs (double dbu_a, double dbu_b);
|
||||
void layout_meta_info_differs (const std::string &name, const tl::Variant &a, const tl::Variant &b);
|
||||
void layer_in_a_only (const db::LayerProperties &la);
|
||||
void layer_in_b_only (const db::LayerProperties &lb);
|
||||
void layer_name_differs (const db::LayerProperties &la, const db::LayerProperties &lb);
|
||||
|
|
@ -1222,6 +1273,7 @@ public:
|
|||
void cell_in_b_only (const std::string &cellname, db::cell_index_type ci);
|
||||
void cell_name_differs (const std::string &cellname_a, db::cell_index_type cia, const std::string &cellname_b, db::cell_index_type cib);
|
||||
void begin_cell (const std::string &cellname, db::cell_index_type cia, db::cell_index_type cib);
|
||||
void cell_meta_info_differs (const std::string &name, const tl::Variant &a, const tl::Variant &b);
|
||||
void bbox_differs (const db::Box &ba, const db::Box &bb);
|
||||
void begin_inst_differences ();
|
||||
void instances_in_a (const std::vector <db::CellInstArrayWithProperties> &insts_a, const std::vector <std::string> &cell_names, const db::PropertiesRepository &props);
|
||||
|
|
@ -1384,6 +1436,16 @@ PrintingDifferenceReceiver::dbu_differs (double dbu_a, double dbu_b)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
PrintingDifferenceReceiver::layout_meta_info_differs (const std::string &name, const tl::Variant &a, const tl::Variant &b)
|
||||
{
|
||||
try {
|
||||
enough (tl::error) << "Global meta info differs - [" << name << "]: " << a << " vs. " << b;
|
||||
} catch (tl::CancelException &) {
|
||||
// ignore cancel exceptions
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PrintingDifferenceReceiver::layer_in_a_only (const db::LayerProperties &la)
|
||||
{
|
||||
|
|
@ -1461,6 +1523,16 @@ PrintingDifferenceReceiver::begin_cell (const std::string &cellname, db::cell_in
|
|||
m_cellname = cellname;
|
||||
}
|
||||
|
||||
void
|
||||
PrintingDifferenceReceiver::cell_meta_info_differs (const std::string &name, const tl::Variant &a, const tl::Variant &b)
|
||||
{
|
||||
try {
|
||||
enough (tl::error) << "Meta info differs in cell " << m_cellname << " - [" << name << "]: " << a << " vs. " << b;
|
||||
} catch (tl::CancelException &) {
|
||||
// ignore cancel exceptions
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PrintingDifferenceReceiver::begin_inst_differences ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ const unsigned int f_no_text_orientation = 0x02;
|
|||
// Ignore properties
|
||||
const unsigned int f_no_properties = 0x04;
|
||||
|
||||
// With meta info
|
||||
const unsigned int f_with_meta = 0x08;
|
||||
|
||||
// Do not compare layer names
|
||||
const unsigned int f_no_layer_names = 0x10;
|
||||
|
||||
|
|
@ -94,6 +97,7 @@ public:
|
|||
virtual ~DifferenceReceiver () { }
|
||||
|
||||
virtual void dbu_differs (double /*dbu_a*/, double /*dbu_b*/) { }
|
||||
virtual void layout_meta_info_differs (const std::string & /*name*/, const tl::Variant & /*value_a*/, const tl::Variant & /*value_b*/) { }
|
||||
virtual void layer_in_a_only (const db::LayerProperties & /*la*/) { }
|
||||
virtual void layer_in_b_only (const db::LayerProperties & /*lb*/) { }
|
||||
virtual void layer_name_differs (const db::LayerProperties & /*la*/, const db::LayerProperties & /*lb*/) { }
|
||||
|
|
@ -102,6 +106,7 @@ public:
|
|||
virtual void cell_in_b_only (const std::string & /*cellname*/, db::cell_index_type /*ci*/) { }
|
||||
virtual void bbox_differs (const db::Box & /*ba*/, const db::Box & /*bb*/) { }
|
||||
virtual void begin_cell (const std::string & /*cellname*/, db::cell_index_type /*cia*/, db::cell_index_type /*cib*/) { }
|
||||
virtual void cell_meta_info_differs (const std::string & /*name*/, const tl::Variant & /*value_a*/, const tl::Variant & /*value_b*/) { }
|
||||
virtual void begin_inst_differences () { }
|
||||
virtual void instances_in_a (const std::vector <db::CellInstArrayWithProperties> & /*insts_a*/, const std::vector <std::string> & /*cell_names*/, const db::PropertiesRepository & /*props*/) { }
|
||||
virtual void instances_in_b (const std::vector <db::CellInstArrayWithProperties> & /*insts_b*/, const std::vector <std::string> & /*cell_names*/, const db::PropertiesRepository & /*props*/) { }
|
||||
|
|
|
|||
|
|
@ -252,6 +252,9 @@ merge_layouts (db::Layout &target,
|
|||
const db::Cell &source_cell = source.cell (*c);
|
||||
db::Cell &target_cell = target.cell (target_cell_index);
|
||||
|
||||
// merge meta info
|
||||
target.merge_meta_info (target_cell_index, source, *c);
|
||||
|
||||
// NOTE: this implementation employs the safe but cumbersome "local transformation" feature.
|
||||
// This means, all cells are transformed according to the given transformation and their
|
||||
// references are transformed to account for that effect. This will lead to somewhat strange
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ void compare_layouts (tl::TestBase *_this, const db::Layout &layout, const std::
|
|||
(n > 0 ? db::layout_diff::f_silent : db::layout_diff::f_verbose)
|
||||
| ((norm & AsPolygons) != 0 ? db::layout_diff::f_boxes_as_polygons + db::layout_diff::f_paths_as_polygons : 0)
|
||||
| ((norm & WithArrays) != 0 ? 0 : db::layout_diff::f_flatten_array_insts)
|
||||
| ((norm & WithMeta) == 0 ? 0 : db::layout_diff::f_with_meta)
|
||||
/*| db::layout_diff::f_no_text_details | db::layout_diff::f_no_text_orientation*/
|
||||
, tolerance, 100 /*max diff lines*/);
|
||||
if (equal && n > 0) {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ enum NormalizationMode
|
|||
NormFileMask = 7, // bits the extract for file mode
|
||||
NoContext = 8, // write tmp file without context
|
||||
AsPolygons = 16, // paths and boxes are treated as polygons
|
||||
WithArrays = 32 // do not flatten arrays
|
||||
WithArrays = 32, // do not flatten arrays
|
||||
WithMeta = 64 // with meta info
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1004,6 +1004,22 @@ static void cell_add_meta_info (db::Cell *cell, const MetaInfo &mi)
|
|||
}
|
||||
}
|
||||
|
||||
static void cell_merge_meta_info (db::Cell *cell, const db::Cell *source)
|
||||
{
|
||||
if (! source || ! cell->layout () || ! source->layout ()) {
|
||||
return;
|
||||
}
|
||||
cell->layout ()->merge_meta_info (cell->cell_index (), *source->layout (), source->cell_index ());
|
||||
}
|
||||
|
||||
static void cell_copy_meta_info (db::Cell *cell, const db::Cell *source)
|
||||
{
|
||||
if (! source || ! cell->layout () || ! source->layout ()) {
|
||||
return;
|
||||
}
|
||||
cell->layout ()->copy_meta_info (cell->cell_index (), *source->layout (), source->cell_index ());
|
||||
}
|
||||
|
||||
static const tl::Variant &cell_meta_info_value (db::Cell *cell, const std::string &name)
|
||||
{
|
||||
if (! cell->layout ()) {
|
||||
|
|
@ -1755,6 +1771,7 @@ read_options (db::Cell *cell, const std::string &path, const db::LoadLayoutOptio
|
|||
db::CellMapping cm;
|
||||
std::vector<db::cell_index_type> new_cells = cm.create_single_mapping_full (*cell->layout (), cell->cell_index (), tmp, *tmp.begin_top_down ());
|
||||
cell->move_tree_shapes (tmp.cell (*tmp.begin_top_down ()), cm);
|
||||
cell->layout ()->merge_meta_info (tmp, cm);
|
||||
|
||||
return new_cells;
|
||||
}
|
||||
|
|
@ -1834,6 +1851,21 @@ Class<db::Cell> decl_Cell ("db", "Cell",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.28.8."
|
||||
) +
|
||||
gsi::method_ext ("merge_meta_info", &cell_merge_meta_info, gsi::arg ("other"),
|
||||
"@brief Merges the meta information from the other cell into this cell\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
"Existing keys in this cell will be overwritten by the respective values from the other cell.\n"
|
||||
"New keys will be added.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method_ext ("copy_meta_info", &cell_copy_meta_info, gsi::arg ("other"),
|
||||
"@brief Copies the meta information from the other cell into this cell\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
"The meta information from this cell will be replaced by the meta information from the other cell.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method_ext ("clear_meta_info", &cell_clear_meta_info,
|
||||
"@brief Clears the meta information of the cell\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
|
|
|
|||
|
|
@ -1105,12 +1105,54 @@ Class<db::Layout> decl_Layout ("db", "Layout",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.25."
|
||||
) +
|
||||
gsi::method ("merge_meta_info", static_cast<void (db::Layout::*) (const db::Layout &)> (&db::Layout::merge_meta_info), gsi::arg ("other"),
|
||||
"@brief Merges the meta information from the other layout into this layout\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
"Existing keys in this layout will be overwritten by the respective values from the other layout.\n"
|
||||
"New keys will be added.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method ("merge_meta_info", static_cast<void (db::Layout::*) (const db::Layout &, const db::CellMapping &cm)> (&db::Layout::merge_meta_info), gsi::arg ("other"), gsi::arg ("cm"),
|
||||
"@brief Merges the meta information from the other layout into this layout for the cells given by the cell mapping\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
"This method will use the source/target cell pairs from the cell mapping object and merge the meta information "
|
||||
"from each source cell from the 'other' layout into the mapped cell inside self.\n"
|
||||
"This method can be used with '\\copy_tree_shapes' and similar to copy meta information in addition to the shapes.\n"
|
||||
"Existing cell-specific keys in this layout will be overwritten by the respective values from the other layout.\n"
|
||||
"New keys will be added.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method ("copy_meta_info", static_cast<void (db::Layout::*) (const db::Layout &)> (&db::Layout::copy_meta_info), gsi::arg ("other"),
|
||||
"@brief Copies the meta information from the other layout into this layout\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
"The meta information from this layout will be replaced by the meta information from the other layout.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method ("copy_meta_info", static_cast<void (db::Layout::*) (const db::Layout &, const db::CellMapping &cm)> (&db::Layout::copy_meta_info), gsi::arg ("other"), gsi::arg ("cm"),
|
||||
"@brief Copies the meta information from the other layout into this layout for the cells given by the cell mapping\n"
|
||||
"See \\LayoutMetaInfo for details about cells and meta information.\n"
|
||||
"This method will use the source/target cell pairs from the cell mapping object and merge the meta information "
|
||||
"from each source cell from the 'other' layout into the mapped cell inside self.\n"
|
||||
"This method can be used with '\\copy_tree_shapes' and similar to copy meta information in addition to the shapes.\n"
|
||||
"All cell-specific keys in this layout will be replaced by the respective values from the other layout.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method ("clear_meta_info", static_cast<void (db::Layout::*) ()> (&db::Layout::clear_meta),
|
||||
"@brief Clears the meta information of the layout\n"
|
||||
"See \\LayoutMetaInfo for details about layouts and meta information."
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.8."
|
||||
) +
|
||||
gsi::method ("clear_all_meta_info", static_cast<void (db::Layout::*) ()> (&db::Layout::clear_all_meta),
|
||||
"@brief Clears all meta information of the layout (cell specific and global)\n"
|
||||
"See \\LayoutMetaInfo for details about layouts and meta information."
|
||||
"\n"
|
||||
"This method has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::method ("remove_meta_info", static_cast<void (db::Layout::*) (const std::string &name)> (&db::Layout::remove_meta_info), gsi::arg ("name"),
|
||||
"@brief Removes meta information from the layout\n"
|
||||
"See \\LayoutMetaInfo for details about layouts and meta information."
|
||||
|
|
|
|||
|
|
@ -90,6 +90,11 @@ public:
|
|||
dbu_differs_event (dbu_a, dbu_b);
|
||||
}
|
||||
|
||||
virtual void layout_meta_info_differs (const std::string &name, const tl::Variant &value_a, const tl::Variant &value_b)
|
||||
{
|
||||
layout_meta_info_differs_event (name, value_a, value_b);
|
||||
}
|
||||
|
||||
virtual void layer_in_a_only (const db::LayerProperties &la)
|
||||
{
|
||||
layer_in_a_only_event (la);
|
||||
|
|
@ -132,6 +137,11 @@ public:
|
|||
begin_cell_event (mp_cell_a, mp_cell_b);
|
||||
}
|
||||
|
||||
virtual void cell_meta_info_differs (const std::string &name, const tl::Variant &value_a, const tl::Variant &value_b)
|
||||
{
|
||||
cell_meta_info_differs_event (name, value_a, value_b);
|
||||
}
|
||||
|
||||
virtual void begin_inst_differences ()
|
||||
{
|
||||
begin_inst_differences_event ();
|
||||
|
|
@ -343,6 +353,7 @@ public:
|
|||
}
|
||||
|
||||
tl::event<double /*dbu_a*/, double /*dbu_a*/> dbu_differs_event;
|
||||
tl::event<const std::string & /*name*/, const tl::Variant & /*value_a*/, const tl::Variant & /*value_b*/> layout_meta_info_differs_event;
|
||||
tl::event<const db::LayerProperties & /*a*/> layer_in_a_only_event;
|
||||
tl::event<const db::LayerProperties & /*b*/> layer_in_b_only_event;
|
||||
tl::event<const db::LayerProperties & /*a*/, const db::LayerProperties & /*b*/> layer_name_differs_event;
|
||||
|
|
@ -351,6 +362,7 @@ public:
|
|||
tl::event<const db::Cell * /*c*/> cell_in_b_only_event;
|
||||
tl::event<const db::Box & /*ba*/, const db::Box & /*bb*/> bbox_differs_event;
|
||||
tl::event<const db::Cell * /*ca*/, const db::Cell * /*cb*/> begin_cell_event;
|
||||
tl::event<const std::string & /*name*/, const tl::Variant & /*value_a*/, const tl::Variant & /*value_b*/> cell_meta_info_differs_event;
|
||||
tl::Event begin_inst_differences_event;
|
||||
tl::event<const db::CellInstArray & /*anotb*/, db::properties_id_type /*prop_id*/> instance_in_a_only_event;
|
||||
tl::event<const db::CellInstArray & /*bnota*/, db::properties_id_type /*prop_id*/> instance_in_b_only_event;
|
||||
|
|
@ -409,6 +421,10 @@ static unsigned int f_no_properties () {
|
|||
return db::layout_diff::f_no_properties;
|
||||
}
|
||||
|
||||
static unsigned int f_with_meta () {
|
||||
return db::layout_diff::f_with_meta;
|
||||
}
|
||||
|
||||
static unsigned int f_no_layer_names () {
|
||||
return db::layout_diff::f_no_layer_names;
|
||||
}
|
||||
|
|
@ -450,7 +466,7 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
"full compare.\n"
|
||||
"\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("IgnoreDuplicates", &f_ignore_duplicates,
|
||||
"@brief Ignore duplicate instances or shapes\n"
|
||||
|
|
@ -462,17 +478,25 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
gsi::constant ("NoTextOrientation", &f_no_text_orientation,
|
||||
"@brief Ignore text orientation\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("NoProperties", &f_no_properties,
|
||||
"@brief Ignore properties\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("WithMetaInfo", &f_with_meta,
|
||||
"@brief Ignore meta info\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"combined with other constants to form a flag set. If present, this option tells the compare algorithm "
|
||||
"to include persisted meta info in the compare.\n"
|
||||
"\n"
|
||||
"This flag has been introduced in version 0.28.16."
|
||||
) +
|
||||
gsi::constant ("NoLayerNames", &f_no_layer_names,
|
||||
"@brief Do not compare layer names\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("Verbose", &f_verbose,
|
||||
"@brief Enables verbose mode (gives details about the differences)\n"
|
||||
|
|
@ -480,22 +504,22 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
"See the event descriptions for details about the differences in verbose and non-verbose mode.\n"
|
||||
"\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("BoxesAsPolygons", &f_boxes_as_polygons,
|
||||
"@brief Compare boxes to polygons\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("FlattenArrayInsts", &f_flatten_array_insts,
|
||||
"@brief Compare array instances instance by instance\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("PathsAsPolygons", &f_paths_as_polygons,
|
||||
"@brief Compare paths to polygons\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("SmartCellMapping", &f_smart_cell_mapping,
|
||||
"@brief Derive smart cell mapping instead of name mapping (available only if top cells are specified)\n"
|
||||
|
|
@ -503,7 +527,7 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
"cells are compared (with \\LayoutDiff#compare with cells instead of layout objects).\n"
|
||||
"\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set.\n"
|
||||
"combined with other constants to form a flag set.\n"
|
||||
) +
|
||||
gsi::constant ("DontSummarizeMissingLayers", &f_dont_summarize_missing_layers,
|
||||
"@brief Don't summarize missing layers\n"
|
||||
|
|
@ -511,12 +535,12 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
"layer will be reported as difference.\n"
|
||||
"\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::constant ("NoTextDetails", &f_no_text_details,
|
||||
"@brief Ignore text details (font, size, presentation)\n"
|
||||
"This constant can be used for the flags parameter of \\compare_layouts and \\compare_cells. It can be "
|
||||
"compared with other constants to form a flag set."
|
||||
"combined with other constants to form a flag set."
|
||||
) +
|
||||
gsi::method ("compare", &LayoutDiff::compare_layouts,
|
||||
gsi::arg("a"),
|
||||
|
|
@ -593,6 +617,14 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
gsi::event ("on_dbu_differs", &LayoutDiff::dbu_differs_event, gsi::arg ("dbu_a"), gsi::arg ("dbu_b"),
|
||||
"@brief This signal indicates a difference in the database units of the layouts\n"
|
||||
) +
|
||||
gsi::event ("on_layout_meta_info_differs", &LayoutDiff::layout_meta_info_differs_event, gsi::arg ("name"), gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief This signal indicates that global meta info differs\n"
|
||||
"Meta information is only compared when \\WithMetaInfo is added to the compare flags.\n"
|
||||
"'a' and 'b' are the values for the first and second layout. 'nil' is passed to these values to indicate "
|
||||
"missing meta information on one side.\n"
|
||||
"\n"
|
||||
"This event has been added in version 0.28.16."
|
||||
) +
|
||||
gsi::event ("on_layer_in_a_only", &LayoutDiff::layer_in_a_only_event, gsi::arg ("a"),
|
||||
"@brief This signal indicates a layer that is present only in the first layout\n"
|
||||
) +
|
||||
|
|
@ -619,9 +651,17 @@ gsi::Class<LayoutDiff> decl_LayoutDiff ("db", "LayoutDiff",
|
|||
"In verbose mode detailed events will be issued indicating the differences.\n"
|
||||
) +
|
||||
gsi::event ("on_begin_cell", &LayoutDiff::begin_cell_event, gsi::arg ("ca"), gsi::arg ("cb"),
|
||||
"@brief This signal initiates the sequence of events for a cell pair\n"
|
||||
"@brief This signal indicates the sequence of events for a cell pair\n"
|
||||
"All cell specific events happen between \\begin_cell_event and \\end_cell_event signals."
|
||||
) +
|
||||
gsi::event ("on_cell_meta_info_differs", &LayoutDiff::cell_meta_info_differs_event, gsi::arg ("name"), gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief This signal indicates that meta info between the current cells differs\n"
|
||||
"Meta information is only compared when \\WithMetaInfo is added to the compare flags.\n"
|
||||
"'a' and 'b' are the values for the first and second layout. 'nil' is passed to these values to indicate "
|
||||
"missing meta information on one side.\n"
|
||||
"\n"
|
||||
"This event has been added in version 0.28.16."
|
||||
) +
|
||||
gsi::event ("on_begin_inst_differences", &LayoutDiff::begin_inst_differences_event,
|
||||
"@brief This signal indicates differences in the cell instances\n"
|
||||
"In verbose mode (see \\Verbose) more events will follow that indicate the instances that are present only "
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ public:
|
|||
std::string text () const { return m_os.str (); }
|
||||
void clear () { m_os.str (std::string ()); }
|
||||
void dbu_differs (double dbu_a, double dbu_b);
|
||||
void layout_meta_info_differs (const std::string &, const tl::Variant &, const tl::Variant &);
|
||||
void layer_in_a_only (const db::LayerProperties &la);
|
||||
void layer_in_b_only (const db::LayerProperties &lb);
|
||||
void layer_name_differs (const db::LayerProperties &la, const db::LayerProperties &lb);
|
||||
|
|
@ -45,6 +46,7 @@ public:
|
|||
void cell_in_b_only (const std::string &cellname, db::cell_index_type ci);
|
||||
void cell_name_differs (const std::string &cellname_a, db::cell_index_type cia, const std::string &cellname_b, db::cell_index_type cib);
|
||||
void begin_cell (const std::string &cellname, db::cell_index_type cia, db::cell_index_type cib);
|
||||
void cell_meta_info_differs (const std::string &, const tl::Variant &, const tl::Variant &);
|
||||
void bbox_differs (const db::Box &ba, const db::Box &bb);
|
||||
void begin_inst_differences ();
|
||||
void instances_in_a (const std::vector <db::CellInstArrayWithProperties> &insts_a, const std::vector <std::string> &cell_names, const db::PropertiesRepository &props);
|
||||
|
|
@ -155,6 +157,12 @@ TestDifferenceReceiver::dbu_differs (double dbu_a, double dbu_b)
|
|||
m_os << "layout_diff: database units differ " << dbu_a << " vs. " << dbu_b << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
TestDifferenceReceiver::layout_meta_info_differs (const std::string &name, const tl::Variant &va, const tl::Variant &vb)
|
||||
{
|
||||
m_os << "layout_diff: global meta info differs " << name << ": " << va.to_string () << " vs. " << vb.to_string () << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
TestDifferenceReceiver::layer_in_a_only (const db::LayerProperties &la)
|
||||
{
|
||||
|
|
@ -204,6 +212,12 @@ TestDifferenceReceiver::begin_cell (const std::string &cellname, db::cell_index_
|
|||
m_cellname = cellname;
|
||||
}
|
||||
|
||||
void
|
||||
TestDifferenceReceiver::cell_meta_info_differs (const std::string &name, const tl::Variant &va, const tl::Variant &vb)
|
||||
{
|
||||
m_os << "layout_diff: cell meta info differs for cell " << m_cellname << " - " << name << ": " << va.to_string () << " vs. " << vb.to_string () << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
TestDifferenceReceiver::begin_inst_differences ()
|
||||
{
|
||||
|
|
@ -1704,4 +1718,46 @@ TEST(8)
|
|||
);
|
||||
}
|
||||
|
||||
// meta info
|
||||
TEST(9)
|
||||
{
|
||||
db::Layout a;
|
||||
db::cell_index_type caa = a.add_cell ("A");
|
||||
db::cell_index_type cab = a.add_cell ("B");
|
||||
|
||||
db::Layout b;
|
||||
db::cell_index_type cba = b.add_cell ("A");
|
||||
db::cell_index_type cbb = b.add_cell ("B");
|
||||
|
||||
a.add_meta_info ("x", db::MetaInfo ("", 17.0, true));
|
||||
a.add_meta_info ("y", db::MetaInfo ("", -1.0, false)); // not persisted
|
||||
a.add_meta_info ("z", db::MetaInfo ("", -1.0, true));
|
||||
a.add_meta_info (caa, "a1", db::MetaInfo ("", "a", true));
|
||||
a.add_meta_info (caa, "a2", db::MetaInfo ("", 42, false)); // not persisted
|
||||
a.add_meta_info (caa, "a3", db::MetaInfo ("", 41, true));
|
||||
a.add_meta_info (cab, "b1", db::MetaInfo ("", "b", true));
|
||||
a.add_meta_info (cab, "b2", db::MetaInfo ("", 3, false)); // not persisted
|
||||
a.add_meta_info (cab, "b3", db::MetaInfo ("", "q", true));
|
||||
|
||||
b.add_meta_info ("x", db::MetaInfo ("", 21.0, true));
|
||||
b.add_meta_info ("y", db::MetaInfo ("", -1.0, true));
|
||||
b.add_meta_info (cba, "a1", db::MetaInfo ("", "aa", true));
|
||||
b.add_meta_info (cba, "a2", db::MetaInfo ("", 42, true));
|
||||
b.add_meta_info (cbb, "b1", db::MetaInfo ("", "bb", true));
|
||||
b.add_meta_info (cbb, "b2", db::MetaInfo ("", 3, true));
|
||||
|
||||
TestDifferenceReceiver r;
|
||||
bool eq = db::compare_layouts (a, b, db::layout_diff::f_verbose | db::layout_diff::f_with_meta, 0, r);
|
||||
EXPECT_EQ (eq, false);
|
||||
EXPECT_EQ (r.text (),
|
||||
"layout_diff: global meta info differs x: 17 vs. 21\n"
|
||||
"layout_diff: global meta info differs y: nil vs. -1\n"
|
||||
"layout_diff: global meta info differs z: -1 vs. nil\n"
|
||||
"layout_diff: cell meta info differs for cell A - a1: a vs. aa\n"
|
||||
"layout_diff: cell meta info differs for cell A - a2: nil vs. 42\n"
|
||||
"layout_diff: cell meta info differs for cell A - a3: 41 vs. nil\n"
|
||||
"layout_diff: cell meta info differs for cell B - b1: b vs. bb\n"
|
||||
"layout_diff: cell meta info differs for cell B - b2: nil vs. 3\n"
|
||||
"layout_diff: cell meta info differs for cell B - b3: q vs. nil\n"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ TEST(4_CollectModeRename)
|
|||
}
|
||||
|
||||
std::string fn_au (tl::testdata () + "/gds/collect_rename_au.gds");
|
||||
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
|
||||
db::compare_layouts (_this, layout, fn_au, db::NormalizationMode (db::WriteGDS2 | db::WithMeta), 1);
|
||||
}
|
||||
|
||||
TEST(4_CollectModeRenameWithGhost)
|
||||
|
|
@ -634,7 +634,7 @@ TEST(4_CollectModeOverwrite)
|
|||
}
|
||||
|
||||
std::string fn_au (tl::testdata () + "/gds/collect_overwrite_au.gds");
|
||||
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
|
||||
db::compare_layouts (_this, layout, fn_au, db::NormalizationMode (db::WriteGDS2 | db::WithMeta), 1);
|
||||
}
|
||||
|
||||
TEST(4_CollectModeSkip)
|
||||
|
|
@ -658,7 +658,7 @@ TEST(4_CollectModeSkip)
|
|||
}
|
||||
|
||||
std::string fn_au (tl::testdata () + "/gds/collect_skip_au.gds");
|
||||
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
|
||||
db::compare_layouts (_this, layout, fn_au, db::NormalizationMode (db::WriteGDS2 | db::WithMeta), 1);
|
||||
}
|
||||
|
||||
TEST(4_CollectModeAdd)
|
||||
|
|
@ -682,7 +682,7 @@ TEST(4_CollectModeAdd)
|
|||
}
|
||||
|
||||
std::string fn_au (tl::testdata () + "/gds/collect_add_au.gds");
|
||||
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
|
||||
db::compare_layouts (_this, layout, fn_au, db::NormalizationMode (db::WriteGDS2 | db::WithMeta), 1);
|
||||
}
|
||||
|
||||
// border case with multiple padding 0 for SNAME and STRING records
|
||||
|
|
@ -6,8 +6,8 @@ TARGET = gds2_tests
|
|||
include($$PWD/../../../../lib_ut.pri)
|
||||
|
||||
SOURCES = \
|
||||
dbGDS2Reader.cc \
|
||||
dbGDS2Writer.cc \
|
||||
dbGDS2ReaderTests.cc \
|
||||
dbGDS2WriterTests.cc
|
||||
|
||||
INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
|
||||
DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -23,6 +23,10 @@ end
|
|||
|
||||
load("test_prologue.rb")
|
||||
|
||||
def mi2s(obj)
|
||||
obj.each_meta_info.collect { |mi| mi.name + ":" + mi.value.to_s }.sort.join(";")
|
||||
end
|
||||
|
||||
class DBLayoutTests2_TestClass < TestBase
|
||||
|
||||
# LayerInfo
|
||||
|
|
@ -1253,6 +1257,175 @@ class DBLayoutTests2_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
# Cell#read and meta info (issue #1609)
|
||||
def test_16
|
||||
|
||||
tmp = File::join($ut_testtmp, "test16.gds")
|
||||
|
||||
ly1 = RBA::Layout::new
|
||||
a = ly1.create_cell("A")
|
||||
b = ly1.create_cell("B")
|
||||
a.insert(RBA::DCellInstArray::new(b, RBA::Trans::new))
|
||||
|
||||
a.add_meta_info(RBA::LayoutMetaInfo::new("am1", 42.0, "", true))
|
||||
a.add_meta_info(RBA::LayoutMetaInfo::new("am2", "u", "", true))
|
||||
assert_equal(mi2s(a), "am1:42.0;am2:u")
|
||||
|
||||
b.add_meta_info(RBA::LayoutMetaInfo::new("bm1", 17, "", true))
|
||||
assert_equal(mi2s(b), "bm1:17")
|
||||
|
||||
ly1.add_meta_info(RBA::LayoutMetaInfo::new("lm1", -2.0, "", true))
|
||||
ly1.add_meta_info(RBA::LayoutMetaInfo::new("lm2", "v", "", true))
|
||||
assert_equal(mi2s(ly1), "lm1:-2.0;lm2:v")
|
||||
|
||||
ly1.write(tmp)
|
||||
|
||||
ly2 = RBA::Layout::new
|
||||
top = ly2.create_cell("TOP")
|
||||
a = ly2.create_cell("A")
|
||||
c = ly2.create_cell("C")
|
||||
top.insert(RBA::DCellInstArray::new(a, RBA::Trans::new))
|
||||
a.insert(RBA::DCellInstArray::new(c, RBA::Trans::new))
|
||||
|
||||
top.add_meta_info(RBA::LayoutMetaInfo::new("topm1", "abc"))
|
||||
assert_equal(mi2s(top), "topm1:abc")
|
||||
a.add_meta_info(RBA::LayoutMetaInfo::new("am1", "a number"))
|
||||
a.add_meta_info(RBA::LayoutMetaInfo::new("am3", 0))
|
||||
assert_equal(mi2s(a), "am1:a number;am3:0")
|
||||
c.add_meta_info(RBA::LayoutMetaInfo::new("cm1", 3))
|
||||
assert_equal(mi2s(c), "cm1:3")
|
||||
|
||||
ly2.add_meta_info(RBA::LayoutMetaInfo::new("lm1", 5))
|
||||
assert_equal(mi2s(ly2), "lm1:5")
|
||||
|
||||
a.read(tmp)
|
||||
# not modified
|
||||
assert_equal(mi2s(ly2), "lm1:5")
|
||||
# merged
|
||||
assert_equal(mi2s(a), "am1:42.0;am2:u;am3:0")
|
||||
# not modified
|
||||
assert_equal(mi2s(c), "cm1:3")
|
||||
|
||||
b2 = ly2.cell("B")
|
||||
# imported
|
||||
assert_equal(mi2s(b2), "bm1:17")
|
||||
|
||||
puts "done."
|
||||
|
||||
end
|
||||
|
||||
# Layout, meta info diverse
|
||||
def test_17
|
||||
|
||||
manager = RBA::Manager::new
|
||||
|
||||
ly = RBA::Layout::new(manager)
|
||||
a = ly.create_cell("A")
|
||||
|
||||
manager.transaction("trans")
|
||||
ly.add_meta_info(RBA::LayoutMetaInfo::new("lm1", 17))
|
||||
a.add_meta_info(RBA::LayoutMetaInfo::new("am1", "u"))
|
||||
manager.commit
|
||||
|
||||
assert_equal(mi2s(ly), "lm1:17")
|
||||
assert_equal(mi2s(a), "am1:u")
|
||||
|
||||
manager.undo
|
||||
assert_equal(mi2s(ly), "")
|
||||
assert_equal(mi2s(a), "")
|
||||
|
||||
manager.redo
|
||||
assert_equal(mi2s(ly), "lm1:17")
|
||||
assert_equal(mi2s(a), "am1:u")
|
||||
|
||||
manager.transaction("trans")
|
||||
ly.add_meta_info(RBA::LayoutMetaInfo::new("lm1", 117))
|
||||
a.add_meta_info(RBA::LayoutMetaInfo::new("am1", "v"))
|
||||
manager.commit
|
||||
|
||||
assert_equal(mi2s(ly), "lm1:117")
|
||||
assert_equal(mi2s(a), "am1:v")
|
||||
|
||||
manager.undo
|
||||
assert_equal(mi2s(ly), "lm1:17")
|
||||
assert_equal(mi2s(a), "am1:u")
|
||||
|
||||
manager.redo
|
||||
assert_equal(mi2s(ly), "lm1:117")
|
||||
assert_equal(mi2s(a), "am1:v")
|
||||
|
||||
manager.undo
|
||||
assert_equal(mi2s(ly), "lm1:17")
|
||||
assert_equal(mi2s(a), "am1:u")
|
||||
|
||||
manager.transaction("trans")
|
||||
ly.remove_meta_info("lm1")
|
||||
a.remove_meta_info("am1")
|
||||
a.remove_meta_info("doesnotexist")
|
||||
manager.commit
|
||||
|
||||
assert_equal(mi2s(ly), "")
|
||||
assert_equal(mi2s(a), "")
|
||||
|
||||
manager.undo
|
||||
assert_equal(mi2s(ly), "lm1:17")
|
||||
assert_equal(mi2s(a), "am1:u")
|
||||
|
||||
manager.transaction("trans")
|
||||
ly.clear_all_meta_info
|
||||
manager.commit
|
||||
|
||||
assert_equal(mi2s(ly), "")
|
||||
assert_equal(mi2s(a), "")
|
||||
|
||||
manager.undo
|
||||
assert_equal(mi2s(ly), "lm1:17")
|
||||
assert_equal(mi2s(a), "am1:u")
|
||||
|
||||
manager.redo
|
||||
assert_equal(mi2s(ly), "")
|
||||
assert_equal(mi2s(a), "")
|
||||
|
||||
ly2 = RBA::Layout::new
|
||||
ly.add_meta_info(RBA::LayoutMetaInfo::new("lm1", 17))
|
||||
ly2.add_meta_info(RBA::LayoutMetaInfo::new("lm2", 42))
|
||||
assert_equal(mi2s(ly), "lm1:17")
|
||||
ly.merge_meta_info(ly2)
|
||||
assert_equal(mi2s(ly), "lm1:17;lm2:42")
|
||||
ly.copy_meta_info(ly2)
|
||||
assert_equal(mi2s(ly), "lm2:42")
|
||||
|
||||
a = ly.create_cell("A")
|
||||
a.add_meta_info(RBA::LayoutMetaInfo::new("am1", "u"))
|
||||
b = ly2.create_cell("B")
|
||||
b.add_meta_info(RBA::LayoutMetaInfo::new("bm1", "v"))
|
||||
|
||||
assert_equal(mi2s(a), "am1:u")
|
||||
a.merge_meta_info(b)
|
||||
assert_equal(mi2s(a), "am1:u;bm1:v")
|
||||
a.copy_meta_info(b)
|
||||
assert_equal(mi2s(a), "bm1:v")
|
||||
|
||||
ly = RBA::Layout::new
|
||||
ly2 = RBA::Layout::new
|
||||
|
||||
a = ly.create_cell("A")
|
||||
a.add_meta_info(RBA::LayoutMetaInfo::new("am1", "u"))
|
||||
ly2.create_cell("X")
|
||||
b = ly2.create_cell("B")
|
||||
b.add_meta_info(RBA::LayoutMetaInfo::new("bm1", "v"))
|
||||
|
||||
cm = RBA::CellMapping::new
|
||||
cm.map(b.cell_index, a.cell_index)
|
||||
|
||||
assert_equal(mi2s(a), "am1:u")
|
||||
ly.merge_meta_info(ly2, cm)
|
||||
assert_equal(mi2s(a), "am1:u;bm1:v")
|
||||
ly.copy_meta_info(ly2, cm)
|
||||
assert_equal(mi2s(a), "bm1:v")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue