Implemented a solution for #2195

A new PCell method cell_name/cell_name_impl that
delivers a cell name, which is used for "convert to
static cell" and as cell name in general.

Needs testing.
This commit is contained in:
Matthias Koefferlein 2025-10-25 00:21:04 +02:00
parent 564111af77
commit e8e2858af3
14 changed files with 199 additions and 36 deletions

View File

@ -149,6 +149,18 @@ created as well.
This method must be reimplemented in a PCell class to identify the PCell in human-readable form.
This text is shown in the cell tree for the PCell for example.
@method cell_name_impl
@brief Delivers the cell name to be used for the PCell variant
A PCell variant is represented in the cell tree by a placeholder cell. By
default, the name of this cell is the PCell name. Since multiple variants
may exist, usually a disambiguator is added to the name (e.g. "..$1").
This method allows encoding the PCell parameters into that cell name,
so the PCell variant is easier to identify in the cell tree - for example
in the GDS file - instead of the unspecific disambiguator.
@method produce_impl
@brief Produces the layout
@ -466,6 +478,19 @@ module RBA
text
end
# implementation of display_text
def cell_name(parameters)
self._start
@param_values = parameters
text = ""
begin
text = cell_name_impl
ensure
self._finish
end
text
end
# get the parameters
def get_parameters
@param_decls
@ -568,6 +593,11 @@ module RBA
""
end
# default implementation
def cell_name_impl
self.name
end
# default implementation
def coerce_parameters_impl
end

View File

@ -158,6 +158,18 @@ created as well.
This method must be reimplemented in a PCell class to identify the PCell in human-readable form.
This text is shown in the cell tree for the PCell for example.
@method cell_name_impl
@brief Delivers the cell name to be used for the PCell variant
A PCell variant is represented in the cell tree by a placeholder cell. By
default, the name of this cell is the PCell name. Since multiple variants
may exist, usually a disambiguator is added to the name (e.g. "..$1").
This method allows encoding the PCell parameters into that cell name,
so the PCell variant is easier to identify in the cell tree - for example
in the GDS file - instead of the unspecific disambiguator.
@method produce_impl
@brief Produces the layout

View File

@ -862,6 +862,12 @@ Cell::get_basic_name () const
return layout ()->cell_name (cell_index ());
}
std::string
Cell::get_variant_name () const
{
return get_basic_name ();
}
std::string
Cell::get_qualified_name () const
{

View File

@ -890,7 +890,7 @@ public:
void set_name (const std::string &name);
/**
* @brief Get the basic name
* @brief Gets the basic name
*
* The basic name of the cell is either the cell name or the cell name in the
* target library (for library proxies) or the PCell name (for PCell proxies).
@ -898,6 +898,14 @@ public:
*/
virtual std::string get_basic_name () const;
/**
* @brief Gets the variant name
*
* The variant name is the PCell's "cell_name" - which may encode the PCell parameters
* into a formal name. Usually that is identical to the PCell name.
*/
virtual std::string get_variant_name () const;
/**
* @brief Gets the display name
*

View File

@ -89,7 +89,7 @@ ColdProxy::get_basic_name () const
}
}
std::string
std::string
ColdProxy::get_display_name () const
{
if (! mp_context_info->lib_name.empty ()) {

View File

@ -2462,7 +2462,7 @@ Layout::get_pcell_variant_dict (pcell_id_type pcell_id, const std::map<std::stri
pcell_variant_type *variant = header->get_variant (*this, parameters);
if (! variant) {
std::string b (header->get_name ());
std::string b (header->declaration ()->get_cell_name (parameters));
if (m_cell_map.find (b.c_str ()) != m_cell_map.end ()) {
b = uniquify_cell_name (b.c_str ());
}
@ -2501,7 +2501,7 @@ Layout::get_pcell_variant (pcell_id_type pcell_id, const std::vector<tl::Variant
pcell_variant_type *variant = header->get_variant (*this, parameters);
if (! variant) {
std::string b (header->get_name ());
std::string b (header->declaration ()->get_cell_name (parameters));
if (m_cell_map.find (b.c_str ()) != m_cell_map.end ()) {
b = uniquify_cell_name (b.c_str ());
}
@ -2627,9 +2627,18 @@ Layout::convert_cell_to_static (db::cell_index_type ci)
const cell_type &org_cell = cell (ci);
// Note: convert to static cell by explicitly cloning to the db::Cell class
ret_ci = add_cell (org_cell.get_basic_name ().c_str ());
std::string vn = org_cell.get_variant_name ();
if (vn == cell_name (ci)) {
// there is a cell name conflict: give priority to the static cell, so it
// will see the variant name
std::string rename_org = uniquify_cell_name (cell_name (ci));
rename_cell (ci, rename_org.c_str ());
}
ret_ci = add_cell (vn.c_str ());
cell_type &new_cell = cell (ret_ci);
// Note: we convert to static cell by explicitly cloning to the db::Cell class
new_cell = org_cell;
new_cell.set_cell_index (ret_ci);
@ -3126,6 +3135,12 @@ Layout::basic_name (cell_index_type cell_index) const
return cell (cell_index).get_basic_name ();
}
std::string
Layout::variant_name (cell_index_type cell_index) const
{
return cell (cell_index).get_variant_name ();
}
void
Layout::register_lib_proxy (db::LibraryProxy *lib_proxy)
{
@ -3161,7 +3176,7 @@ Layout::get_lib_proxy (Library *lib, cell_index_type cell_index)
} else {
// create a new unique name
std::string b (lib->layout ().basic_name (cell_index));
std::string b (lib->layout ().variant_name (cell_index));
if (m_cell_map.find (b.c_str ()) != m_cell_map.end ()) {
b = uniquify_cell_name (b.c_str ());
}

View File

@ -675,7 +675,7 @@ public:
std::string display_name (cell_index_type cell_index) const;
/**
* @brief Return the basic name for the given cell
* @brief Returns the basic name for the given cell
*
* This method is forwarded to the respective method of the cell.
* The basic name is the "original" cell name within the library or
@ -684,7 +684,16 @@ public:
*/
std::string basic_name (cell_index_type cell_index) const;
/**
/**
* @brief Returns the variant name for the given cell
*
* The variant name usually is the basic name. For PCells, this name
* can encode PCell parameters, depending on the definition of the
* PCell.
*/
std::string variant_name (cell_index_type cell_index) const;
/**
* @brief Add a cell object with the given ID and name
*
* This method is basically supposed to be used for "undo" and "redo".

View File

@ -257,7 +257,23 @@ LibraryProxy::get_basic_name () const
}
}
std::string
std::string
LibraryProxy::get_variant_name () const
{
Library *lib = LibraryManager::instance ().lib (lib_id ());
if (lib) {
if (! lib->layout ().is_valid_cell_index (library_cell_index ())) {
return "<defunct>";
} else {
const db::Cell &lib_cell = lib->layout ().cell (library_cell_index ());
return lib_cell.get_variant_name ();
}
} else {
return Cell::get_variant_name ();
}
}
std::string
LibraryProxy::get_display_name () const
{
Library *lib = LibraryManager::instance ().lib (lib_id ());

View File

@ -96,25 +96,28 @@ public:
/**
* @brief Gets the basic name
*
* The basic name of the cell is either the cell name or the cell name in the
* target library (for library proxies) or the PCell name (for PCell proxies).
* The actual name may be different by a extension to make it unique.
* This returns the basic name of the proxy target
*/
virtual std::string get_basic_name () const;
/**
* @brief Gets the variant name
*
* This returns the basic name of the proxy target
*/
virtual std::string get_variant_name () const;
/**
* @brief Gets the display name
*
* The display name is some "nice" descriptive name of the cell (variant)
* For normal cells this name is equivalent to the normal cell name.
* This returns the basic name of the proxy target
*/
virtual std::string get_display_name () const;
/**
* @brief Gets the qualified name
*
* The qualified name for a library proxy is made from the library name, a
* dot and the cell's name.
* Gets a combination of the library name and the target cell's qualified name
*/
virtual std::string get_qualified_name () const;

View File

@ -673,6 +673,18 @@ public:
return std::string ();
}
/**
* @brief Gets a cell name for the PCell, which can depend on the parameters
*
* The actual cell name in the layout may differ by disambiguation. This method
* delivers a proposal for a cell name.
* By default, the PCell name is returned.
*/
virtual std::string get_cell_name (const pcell_parameters_type &) const
{
return m_name;
}
/**
* @brief Returns the description text of the PCell
*

View File

@ -86,7 +86,18 @@ PCellVariant::get_basic_name () const
}
}
std::string
std::string
PCellVariant::get_variant_name () const
{
const PCellHeader *header = pcell_header ();
if (header) {
return m_variant_name;
} else {
return Cell::get_basic_name ();
}
}
std::string
PCellVariant::get_display_name () const
{
const PCellHeader *header = pcell_header ();
@ -172,6 +183,7 @@ PCellVariant::update (ImportLayerMapping *layer_mapping)
header->declaration ()->produce (*layout (), layer_ids, plist, *this);
m_display_name = header->declaration ()->get_display_name (plist);
m_variant_name = header->declaration ()->get_cell_name (plist);
} catch (tl::Exception &ex) {

View File

@ -94,42 +94,37 @@ public:
}
/**
* @brief Get the basic name
*
* The basic name of the cell is either the cell name or the cell name in the
* target library (for library proxies) or the PCell name (for PCell proxies).
* The actual name may be different by a extension to make it unique.
* @brief Gets the basic name
*/
virtual std::string get_basic_name () const;
/**
* @brief Get the display name
*
* The display name is some "nice" descriptive name of the cell (variant)
* For normal cells this name is equivalent to the normal cell name.
* @brief Gets the variant name
*/
virtual std::string get_variant_name () const;
/**
* @brief Gets the display name
*/
virtual std::string get_display_name () const;
/**
* @brief Unregister a cell from it's context.
* @brief Unregisters a cell from it's context.
*/
virtual void unregister ();
/**
* @brief Reregister a cell inside it's context.
* @brief Re-registers a cell inside it's context.
*/
virtual void reregister ();
/**
* @brief Update the layout
* @brief Updates the layout
*/
virtual void update (ImportLayerMapping *layer_mapping = 0);
/**
* @brief Tell, if this cell is a proxy cell
*
* Proxy cells are such whose layout represents a snapshot of another entity.
* Such cells can be PCell variants or library references for example.
* @brief Gets a value indicating if this cell is a proxy cell
*/
virtual bool is_proxy () const
{
@ -138,7 +133,7 @@ public:
protected:
/**
* @brief Get the PCell header for this variant
* @brief Gets the PCell header for this variant
*/
PCellHeader *pcell_header ()
{
@ -146,7 +141,7 @@ protected:
}
/**
* @brief Get the PCell header for this variant
* @brief Gets the PCell header for this variant
*/
const PCellHeader *pcell_header () const
{
@ -156,6 +151,7 @@ protected:
private:
pcell_parameters_type m_parameters;
mutable std::string m_display_name;
mutable std::string m_variant_name;
db::pcell_id_type m_pcell_id;
bool m_registered;
};

View File

@ -368,6 +368,7 @@ Class<db::PCellDeclaration> decl_PCellDeclaration_Native ("db", "PCellDeclaratio
gsi::method ("via_types", &db::PCellDeclaration::via_types) +
gsi::method ("description", &db::PCellDeclaration::get_description) +
gsi::method ("display_text", &db::PCellDeclaration::get_display_name, gsi::arg ("parameters")) +
gsi::method ("cell_name", &db::PCellDeclaration::get_cell_name, gsi::arg ("parameters")) +
gsi::method ("layout", &db::PCellDeclaration::layout,
"@brief Gets the Layout object the PCell is registered in or nil if it is not registered yet.\n"
"This attribute has been added in version 0.27.5."
@ -659,6 +660,20 @@ public:
}
}
std::string get_cell_name_fb (const db::pcell_parameters_type &parameters) const
{
return db::PCellDeclaration::get_cell_name (parameters);
}
virtual std::string get_cell_name (const db::pcell_parameters_type &parameters) const
{
if (cb_get_cell_name.can_issue ()) {
return cb_get_cell_name.issue<db::PCellDeclaration, std::string, const db::pcell_parameters_type &> (&db::PCellDeclaration::get_cell_name, parameters);
} else {
return db::PCellDeclaration::get_cell_name (parameters);
}
}
gsi::Callback cb_get_layer_declarations;
gsi::Callback cb_get_parameter_declarations;
gsi::Callback cb_produce;
@ -669,6 +684,7 @@ public:
gsi::Callback cb_coerce_parameters;
gsi::Callback cb_callback;
gsi::Callback cb_get_display_name;
gsi::Callback cb_get_cell_name;
gsi::Callback cb_get_description;
gsi::Callback cb_via_types;
};
@ -809,6 +825,13 @@ Class<PCellDeclarationImpl> decl_PCellDeclaration (decl_PCellDeclaration_Native,
"@brief Returns the display text for this PCell given a certain parameter set\n"
"Reimplement this method to create a distinct display text for a PCell variant with \n"
"the given parameter set. If this method is not implemented, a default text is created. \n"
) +
gsi::callback ("cell_name", &PCellDeclarationImpl::get_cell_name, &PCellDeclarationImpl::cb_get_cell_name, gsi::arg ("parameters"),
"@brief Returns a cell name used for the PCell variant\n"
"Reimplement this method to create a cell name the system uses for the PCell variant. By default that is the PCell name.\n"
"This feature allows encoding the PCell parameters into the cell name for easier identification of the PCell variant in a cell tree.\n"
"\n"
"This feature has been added in version 0.30.5.\n"
),
"@brief A PCell declaration providing the parameters and code to produce the PCell\n"
"\n"

View File

@ -138,6 +138,21 @@ class _PCellDeclarationHelperMixin:
self._finish()
return text
def cell_name(self, parameters):
"""
Reimplementation of PCellDeclaration.cell_name
This function delegates the implementation to self.cell_name_impl
after configuring the PCellDeclaration object.
"""
self._start()
self._param_values = parameters
try:
text = self.cell_name_impl()
finally:
self._finish()
return text
def get_parameters(self):
"""
Reimplementation of PCellDeclaration.get_parameters
@ -333,6 +348,12 @@ class _PCellDeclarationHelperMixin:
"""
return ""
def cell_name_impl(self):
"""
default implementation
"""
return self.name()
def coerce_parameters_impl(self):
"""
default implementation