Implementing variant reporting

Instead of reporting working layout cell names, the
original cell names plus a variant indicator is reported.
Also, the variant information from the RDB is filled now.

Also, the marker browser now shows the qname of the cells
instead of the name alone.
This commit is contained in:
Matthias Koefferlein 2024-04-28 15:30:29 +02:00
parent aacdc1a4b7
commit 6e3eb568c3
8 changed files with 149 additions and 15 deletions

View File

@ -288,6 +288,7 @@ VariantsCollectorBase::separate_variants (std::map<db::cell_index_type, std::map
if (! var_table) {
var_table = &var_table_intern;
}
tl_assert (var_table->empty ());
for (db::Layout::bottom_up_const_iterator c = mp_layout->begin_bottom_up (); c != mp_layout->end_bottom_up (); ++c) {
@ -311,6 +312,9 @@ VariantsCollectorBase::separate_variants (std::map<db::cell_index_type, std::map
cell.clear_insts ();
bool original_cell_is_variant = false;
db::ICplxTrans original_cell_variant;
int index = 0;
for (auto v = vc->second.begin (); v != vc->second.end (); ++v, ++index) {
@ -333,6 +337,8 @@ VariantsCollectorBase::separate_variants (std::map<db::cell_index_type, std::map
} else {
ci_var = *c;
original_cell_is_variant = true;
original_cell_variant = *v;
}
vt.insert (std::make_pair (*v, ci_var));
@ -341,12 +347,14 @@ VariantsCollectorBase::separate_variants (std::map<db::cell_index_type, std::map
}
// correct the first (remaining) entry
if (! vt.begin ()->first.is_unity ()) {
std::set<db::ICplxTrans> &tv = m_variants [*c];
tv.clear ();
tv.insert (vt.begin ()->first);
} else {
m_variants.erase (*c);
if (original_cell_is_variant) {
if (! original_cell_variant.is_unity ()) {
std::set<db::ICplxTrans> &tv = m_variants [*c];
tv.clear ();
tv.insert (original_cell_variant);
} else {
m_variants.erase (*c);
}
}
} else {

View File

@ -298,28 +298,57 @@ struct DeepShapeStore::LayoutHolder
{
public:
VariantsCreatedListener (DeepShapeStore::LayoutHolder *lh, db::Layout *ly)
: mp_lh (lh)
: mp_lh (lh), m_dbu (ly->dbu ())
{
ly->variants_created_event.add (this, &VariantsCreatedListener::variants_created);
}
private:
std::string var_desc (const db::ICplxTrans &t)
{
std::string s;
if (t.is_mirror ()) {
s += "m";
s += tl::to_string (t.angle () * 0.5);
} else {
s += "r";
s += tl::to_string (t.angle ());
}
if (t.is_mag ()) {
s += tl::sprintf ("*%.9g", t.mag ());
}
if (t.disp () != db::Vector ()) {
s += tl::sprintf ("(%.12g,%.12g)", t.disp ().x () * m_dbu, t.disp ().y () * m_dbu);
}
return s;
}
void variants_created (const std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > *var_map)
{
for (std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> >::const_iterator i = var_map->begin (); i != var_map->end (); ++i) {
for (std::map<db::ICplxTrans, db::cell_index_type>::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
mp_lh->builder.register_variant (i->first, j->second);
if (i->first != j->second) {
mp_lh->builder.register_variant (i->first, j->second, var_desc (j->first));
}
}
// NOTE: variant conversion events are registered after variant formation events, so we can
// base the formed variants (first pass) on the originals.
for (std::map<db::ICplxTrans, db::cell_index_type>::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
if (i->first == j->second) {
mp_lh->builder.register_variant (i->first, j->second, var_desc (j->first));
}
}
}
}
DeepShapeStore::LayoutHolder *mp_lh;
double m_dbu;
};
LayoutHolder (const db::ICplxTrans &trans)
: refs (0), layout (false), builder (&layout, trans), variants_created (this, &layout)
{
// .. nothing yet ..
layout.set_hierarchy_builder (&builder);
}
void add_layer_ref (unsigned int layer)

View File

@ -182,14 +182,24 @@ HierarchyBuilder::reset ()
m_cells_to_be_filled.clear ();
m_cell_map.clear ();
m_variants_of_sources_map.clear ();
m_cells_seen.clear ();
m_cell_stack.clear ();
m_cm_entry = null_iterator;
m_cm_new_entry = false;
}
const std::pair<db::cell_index_type, std::string> &
HierarchyBuilder::variant_of_source (db::cell_index_type target) const
{
static std::pair<db::cell_index_type, std::string> def (std::numeric_limits<db::cell_index_type>::max (), std::string ());
auto vs = m_variants_of_sources_map.find (target);
return vs != m_variants_of_sources_map.end () ? vs->second : def;
}
void
HierarchyBuilder::register_variant (db::cell_index_type non_var, db::cell_index_type var)
HierarchyBuilder::register_variant (db::cell_index_type non_var, db::cell_index_type var, const std::string &description)
{
// non_var (despite its name) may be a variant created previously.
variant_to_original_target_map_type::const_iterator v = m_variants_to_original_target_map.find (non_var);
@ -199,11 +209,23 @@ HierarchyBuilder::register_variant (db::cell_index_type non_var, db::cell_index_
m_original_targets_to_variants_map [non_var].push_back (var);
m_variants_to_original_target_map.insert (std::make_pair (var, non_var));
auto vs = m_variants_of_sources_map.find (non_var);
if (vs != m_variants_of_sources_map.end ()) {
std::string new_description = vs->second.second;
if (! new_description.empty ()) {
new_description += ";";
}
new_description += description;
m_variants_of_sources_map [var] = std::make_pair (vs->second.first, new_description);
}
}
void
HierarchyBuilder::unregister_variant (db::cell_index_type var)
{
m_variants_of_sources_map.erase (var);
variant_to_original_target_map_type::iterator v = m_variants_to_original_target_map.find (var);
if (v == m_variants_to_original_target_map.end ()) {
return;
@ -257,6 +279,7 @@ HierarchyBuilder::begin (const RecursiveShapeIterator *iter)
if (m_cm_entry == m_cell_map.end ()) {
db::cell_index_type new_top_index = mp_target->add_cell (iter->layout ()->cell_name (key.original_cell));
m_cm_entry = m_cell_map.insert (std::make_pair (key, new_top_index)).first;
m_variants_of_sources_map.insert (std::make_pair (new_top_index, std::make_pair (key.original_cell, std::string ())));
}
db::Cell &new_top = mp_target->cell (m_cm_entry->second);
@ -324,17 +347,34 @@ HierarchyBuilder::make_cell_variant (const HierarchyBuilder::CellMapKey &key, co
if (m_cm_entry == m_cell_map.end ()) {
std::string cn = cell_name;
std::string description;
if (! key.clip_region.empty ()) {
cn += "$CLIP_VAR";
description += "CLIP";
}
if (key.inactive) {
cn += "$DIS";
if (! description.empty ()) {
description += "/";
}
description += "DISABLED";
}
new_cell = mp_target->add_cell (cn.c_str ());
std::string new_name = mp_target->cell_name (new_cell);
if (new_name.size () > cn.size ()) {
// use cell name extension to uniquify the description
description += new_name.c_str () + cn.size ();
}
m_cm_entry = m_cell_map.insert (std::make_pair (key, new_cell)).first;
m_cm_new_entry = true;
m_cells_to_be_filled.insert (new_cell);
m_variants_of_sources_map.insert (std::make_pair (new_cell, std::make_pair (key.original_cell, description)));
} else {
new_cell = m_cm_entry->second;
}

View File

@ -389,7 +389,7 @@ public:
* The first cell is either the original, non-variant target cell or itself a variant.
* The second cell will be registered as a variant of the first one.
*/
void register_variant (db::cell_index_type non_var, db::cell_index_type var);
void register_variant (db::cell_index_type non_var, db::cell_index_type var, const std::string &description);
/**
* @brief Unregisters a cell as a variant
@ -404,8 +404,23 @@ public:
return m_variants_to_original_target_map.find (ci) != m_variants_to_original_target_map.end ();
}
/**
* @brief Gets the information about the target/source + variant relationship
*
* For a target cell, returns a pointer to a pair with the cell index of the source cell and
* a string describing the variant this cell forms of the source cell.
*
* The description string is empty if the cell is not a variant.
*/
const std::pair<db::cell_index_type, std::string> &variant_of_source (db::cell_index_type target) const;
/**
* @brief Gets the original target for a variant cell
*
* The original cell is the first-generation target-space cell that variants have been created for.
* This still can mean that the original cell is a clip variant of a source cell.
*
* Target-to-source variants can be derived with "variant_of_source".
*/
db::cell_index_type original_target_for_variant (db::cell_index_type ci) const;
@ -419,6 +434,7 @@ private:
cell_map_type m_cell_map;
original_target_to_variants_map_type m_original_targets_to_variants_map;
variant_to_original_target_map_type m_variants_to_original_target_map;
std::map<db::cell_index_type, std::pair<db::cell_index_type, std::string> > m_variants_of_sources_map;
std::set<cell_map_type::key_type> m_cells_seen;
std::set<db::cell_index_type> m_cells_to_be_filled;

View File

@ -439,6 +439,7 @@ LayoutOrCellContextInfo::has_meta_info () const
Layout::Layout (db::Manager *manager)
: db::Object (manager),
mp_library (0),
mp_builder (0),
m_cells_size (0),
m_invalid (0),
m_top_cells (0),
@ -454,6 +455,7 @@ Layout::Layout (db::Manager *manager)
Layout::Layout (bool editable, db::Manager *manager)
: db::Object (manager),
mp_library (0),
mp_builder (0),
m_cells_size (0),
m_invalid (0),
m_top_cells (0),
@ -473,6 +475,7 @@ Layout::Layout (const db::Layout &layout)
tl::Object (),
tl::UniqueId (),
mp_library (0),
mp_builder (0),
m_cells_size (0),
m_invalid (0),
m_top_cells (0),

View File

@ -72,6 +72,7 @@ class Technology;
class CellMapping;
class LayerMapping;
class VariantsCollectorBase;
class HierarchyBuilder;
template <class Coord> class generic_repository;
typedef generic_repository<db::Coord> GenericRepository;
@ -2113,6 +2114,24 @@ public:
*/
const MetaInfo &meta_info (db::cell_index_type ci, meta_info_name_id_type name_id) const;
/**
* @brief Sets the hierarchy builder reference
* Used internally
*/
void set_hierarchy_builder (db::HierarchyBuilder *builder)
{
mp_builder = builder;
}
/**
* @brief Gets the hierarchy builder
* Used internally
*/
db::HierarchyBuilder *builder () const
{
return mp_builder;
}
/**
* @brief This event is triggered when the technology changes
*/
@ -2138,6 +2157,7 @@ protected:
private:
db::Library *mp_library;
db::HierarchyBuilder *mp_builder;
cell_list m_cells;
size_t m_cells_size;
cell_ptr_vector m_cell_ptrs;

View File

@ -287,7 +287,7 @@ SortByKeyCompareFunc::operator() (MarkerBrowserTreeViewModelCacheEntry *a, Marke
const rdb::Cell *ca = mp_rdb->cell_by_id (a->id ());
const rdb::Cell *cb = mp_rdb->cell_by_id (b->id ());
if (ca && cb) {
return m_ascending ? ca->name () < cb->name () : cb->name () < ca->name ();
return m_ascending ? ca->qname () < cb->qname () : cb->qname () < ca->qname ();
}
const rdb::Category *xa = mp_rdb->category_by_id (a->id ());
@ -582,7 +582,7 @@ public:
if (cell->name ().empty ()) {
return QObject::tr ("All Cells");
} else {
return QVariant (QString::fromUtf8 ("[") + tl::to_qstring (cell->name ()) + QString::fromUtf8 ("]"));
return QVariant (QString::fromUtf8 ("[") + tl::to_qstring (cell->qname ()) + QString::fromUtf8 ("]"));
}
}

View File

@ -174,10 +174,28 @@ public:
const rdb::Cell *cell_for_id (const db::Layout *layout, db::cell_index_type ci)
{
tl_assert (layout != 0);
std::string cn = layout->cell_name (ci);
const rdb::Cell *rdb_cell = mp_rdb->cell_by_qname (cn);
std::string layout_cn = cn;
std::string qname = cn;
std::string var;
// resolve references to original cells in deep mode and determine variant
if (layout->builder ()) {
const db::Layout *source = layout->builder ()->source ().layout ();
if (source) {
const std::pair<db::cell_index_type, std::string> &vs = layout->builder ()->variant_of_source (ci);
if (! vs.second.empty () && source->is_valid_cell_index (vs.first)) {
var = vs.second;
cn = source->cell_name (vs.first);
qname = cn + ":" + var;
}
}
}
const rdb::Cell *rdb_cell = mp_rdb->cell_by_qname (qname);
if (! rdb_cell) {
return mp_rdb->create_cell (cn);
return mp_rdb->create_cell (cn, var, layout_cn);
} else {
return rdb_cell;
}