mirror of https://github.com/KLayout/klayout.git
Merge pull request #2199 from KLayout/feature/issue-2195
Feature/issue 2195
This commit is contained in:
commit
ff49a81723
|
|
@ -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 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.
|
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
|
@method produce_impl
|
||||||
|
|
||||||
@brief Produces the layout
|
@brief Produces the layout
|
||||||
|
|
@ -466,6 +478,19 @@ module RBA
|
||||||
text
|
text
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# implementation of cell_name
|
||||||
|
def cell_name(parameters)
|
||||||
|
self._start
|
||||||
|
@param_values = parameters
|
||||||
|
text = ""
|
||||||
|
begin
|
||||||
|
text = cell_name_impl
|
||||||
|
ensure
|
||||||
|
self._finish
|
||||||
|
end
|
||||||
|
text
|
||||||
|
end
|
||||||
|
|
||||||
# get the parameters
|
# get the parameters
|
||||||
def get_parameters
|
def get_parameters
|
||||||
@param_decls
|
@param_decls
|
||||||
|
|
@ -568,6 +593,11 @@ module RBA
|
||||||
""
|
""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# default implementation
|
||||||
|
def cell_name_impl
|
||||||
|
self.name
|
||||||
|
end
|
||||||
|
|
||||||
# default implementation
|
# default implementation
|
||||||
def coerce_parameters_impl
|
def coerce_parameters_impl
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -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 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.
|
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
|
@method produce_impl
|
||||||
|
|
||||||
@brief Produces the layout
|
@brief Produces the layout
|
||||||
|
|
|
||||||
|
|
@ -862,6 +862,12 @@ Cell::get_basic_name () const
|
||||||
return layout ()->cell_name (cell_index ());
|
return layout ()->cell_name (cell_index ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Cell::get_variant_name () const
|
||||||
|
{
|
||||||
|
return get_basic_name ();
|
||||||
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
Cell::get_qualified_name () const
|
Cell::get_qualified_name () const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -890,7 +890,7 @@ public:
|
||||||
void set_name (const std::string &name);
|
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
|
* 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).
|
* target library (for library proxies) or the PCell name (for PCell proxies).
|
||||||
|
|
@ -898,6 +898,14 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual std::string get_basic_name () const;
|
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
|
* @brief Gets the display name
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ ColdProxy::get_basic_name () const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
ColdProxy::get_display_name () const
|
ColdProxy::get_display_name () const
|
||||||
{
|
{
|
||||||
if (! mp_context_info->lib_name.empty ()) {
|
if (! mp_context_info->lib_name.empty ()) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
pcell_variant_type *variant = header->get_variant (*this, parameters);
|
||||||
if (! variant) {
|
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 ()) {
|
if (m_cell_map.find (b.c_str ()) != m_cell_map.end ()) {
|
||||||
b = uniquify_cell_name (b.c_str ());
|
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);
|
pcell_variant_type *variant = header->get_variant (*this, parameters);
|
||||||
if (! variant) {
|
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 ()) {
|
if (m_cell_map.find (b.c_str ()) != m_cell_map.end ()) {
|
||||||
b = uniquify_cell_name (b.c_str ());
|
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);
|
const cell_type &org_cell = cell (ci);
|
||||||
|
|
||||||
// Note: convert to static cell by explicitly cloning to the db::Cell class
|
std::string vn = org_cell.get_variant_name ();
|
||||||
ret_ci = add_cell (org_cell.get_basic_name ().c_str ());
|
if (vn == std::string (cell_name (ci), vn.size ())) {
|
||||||
|
// there is a cell name conflict: give priority to the static cell, so it
|
||||||
|
// will see the variant name or at least the original disambiguated name
|
||||||
|
std::string rename_org = uniquify_cell_name (vn.c_str ());
|
||||||
|
vn = cell_name (ci);
|
||||||
|
rename_cell (ci, rename_org.c_str ());
|
||||||
|
}
|
||||||
|
|
||||||
|
ret_ci = add_cell (vn.c_str ());
|
||||||
cell_type &new_cell = cell (ret_ci);
|
cell_type &new_cell = cell (ret_ci);
|
||||||
|
// Note: we convert to static cell by explicitly converting to the db::Cell class
|
||||||
new_cell = org_cell;
|
new_cell = org_cell;
|
||||||
new_cell.set_cell_index (ret_ci);
|
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 ();
|
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
|
void
|
||||||
Layout::register_lib_proxy (db::LibraryProxy *lib_proxy)
|
Layout::register_lib_proxy (db::LibraryProxy *lib_proxy)
|
||||||
{
|
{
|
||||||
|
|
@ -3161,7 +3176,7 @@ Layout::get_lib_proxy (Library *lib, cell_index_type cell_index)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// create a new unique name
|
// 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 ()) {
|
if (m_cell_map.find (b.c_str ()) != m_cell_map.end ()) {
|
||||||
b = uniquify_cell_name (b.c_str ());
|
b = uniquify_cell_name (b.c_str ());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -675,7 +675,7 @@ public:
|
||||||
std::string display_name (cell_index_type cell_index) const;
|
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.
|
* This method is forwarded to the respective method of the cell.
|
||||||
* The basic name is the "original" cell name within the library or
|
* 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;
|
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
|
* @brief Add a cell object with the given ID and name
|
||||||
*
|
*
|
||||||
* This method is basically supposed to be used for "undo" and "redo".
|
* This method is basically supposed to be used for "undo" and "redo".
|
||||||
|
|
|
||||||
|
|
@ -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
|
LibraryProxy::get_display_name () const
|
||||||
{
|
{
|
||||||
Library *lib = LibraryManager::instance ().lib (lib_id ());
|
Library *lib = LibraryManager::instance ().lib (lib_id ());
|
||||||
|
|
|
||||||
|
|
@ -96,25 +96,28 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Gets 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
|
* This returns the basic name of the proxy target
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
virtual std::string get_basic_name () const;
|
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
|
* @brief Gets the display name
|
||||||
*
|
*
|
||||||
* The display name is some "nice" descriptive name of the cell (variant)
|
* This returns the basic name of the proxy target
|
||||||
* For normal cells this name is equivalent to the normal cell name.
|
|
||||||
*/
|
*/
|
||||||
virtual std::string get_display_name () const;
|
virtual std::string get_display_name () const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the qualified name
|
* @brief Gets the qualified name
|
||||||
*
|
*
|
||||||
* The qualified name for a library proxy is made from the library name, a
|
* Gets a combination of the library name and the target cell's qualified name
|
||||||
* dot and the cell's name.
|
|
||||||
*/
|
*/
|
||||||
virtual std::string get_qualified_name () const;
|
virtual std::string get_qualified_name () const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -673,6 +673,18 @@ public:
|
||||||
return std::string ();
|
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
|
* @brief Returns the description text of the PCell
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -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
|
PCellVariant::get_display_name () const
|
||||||
{
|
{
|
||||||
const PCellHeader *header = pcell_header ();
|
const PCellHeader *header = pcell_header ();
|
||||||
|
|
@ -172,6 +183,7 @@ PCellVariant::update (ImportLayerMapping *layer_mapping)
|
||||||
header->declaration ()->produce (*layout (), layer_ids, plist, *this);
|
header->declaration ()->produce (*layout (), layer_ids, plist, *this);
|
||||||
|
|
||||||
m_display_name = header->declaration ()->get_display_name (plist);
|
m_display_name = header->declaration ()->get_display_name (plist);
|
||||||
|
m_variant_name = header->declaration ()->get_cell_name (plist);
|
||||||
|
|
||||||
} catch (tl::Exception &ex) {
|
} catch (tl::Exception &ex) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,42 +94,37 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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).
|
|
||||||
* The actual name may be different by a extension to make it unique.
|
|
||||||
*/
|
*/
|
||||||
virtual std::string get_basic_name () const;
|
virtual std::string get_basic_name () const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the display name
|
* @brief Gets the variant name
|
||||||
*
|
*/
|
||||||
* The display name is some "nice" descriptive name of the cell (variant)
|
virtual std::string get_variant_name () const;
|
||||||
* For normal cells this name is equivalent to the normal cell name.
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the display name
|
||||||
*/
|
*/
|
||||||
virtual std::string get_display_name () const;
|
virtual std::string get_display_name () const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Unregister a cell from it's context.
|
* @brief Unregisters a cell from its context.
|
||||||
*/
|
*/
|
||||||
virtual void unregister ();
|
virtual void unregister ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reregister a cell inside it's context.
|
* @brief Re-registers a cell inside its context.
|
||||||
*/
|
*/
|
||||||
virtual void reregister ();
|
virtual void reregister ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update the layout
|
* @brief Updates the layout
|
||||||
*/
|
*/
|
||||||
virtual void update (ImportLayerMapping *layer_mapping = 0);
|
virtual void update (ImportLayerMapping *layer_mapping = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Tell, if this cell is a proxy cell
|
* @brief Gets a value indicating 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.
|
|
||||||
*/
|
*/
|
||||||
virtual bool is_proxy () const
|
virtual bool is_proxy () const
|
||||||
{
|
{
|
||||||
|
|
@ -138,7 +133,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief Get the PCell header for this variant
|
* @brief Gets the PCell header for this variant
|
||||||
*/
|
*/
|
||||||
PCellHeader *pcell_header ()
|
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
|
const PCellHeader *pcell_header () const
|
||||||
{
|
{
|
||||||
|
|
@ -156,6 +151,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
pcell_parameters_type m_parameters;
|
pcell_parameters_type m_parameters;
|
||||||
mutable std::string m_display_name;
|
mutable std::string m_display_name;
|
||||||
|
mutable std::string m_variant_name;
|
||||||
db::pcell_id_type m_pcell_id;
|
db::pcell_id_type m_pcell_id;
|
||||||
bool m_registered;
|
bool m_registered;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -368,6 +368,7 @@ Class<db::PCellDeclaration> decl_PCellDeclaration_Native ("db", "PCellDeclaratio
|
||||||
gsi::method ("via_types", &db::PCellDeclaration::via_types) +
|
gsi::method ("via_types", &db::PCellDeclaration::via_types) +
|
||||||
gsi::method ("description", &db::PCellDeclaration::get_description) +
|
gsi::method ("description", &db::PCellDeclaration::get_description) +
|
||||||
gsi::method ("display_text", &db::PCellDeclaration::get_display_name, gsi::arg ("parameters")) +
|
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,
|
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"
|
"@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."
|
"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 ¶meters) const
|
||||||
|
{
|
||||||
|
return db::PCellDeclaration::get_cell_name (parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string get_cell_name (const db::pcell_parameters_type ¶meters) 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_layer_declarations;
|
||||||
gsi::Callback cb_get_parameter_declarations;
|
gsi::Callback cb_get_parameter_declarations;
|
||||||
gsi::Callback cb_produce;
|
gsi::Callback cb_produce;
|
||||||
|
|
@ -669,6 +684,7 @@ public:
|
||||||
gsi::Callback cb_coerce_parameters;
|
gsi::Callback cb_coerce_parameters;
|
||||||
gsi::Callback cb_callback;
|
gsi::Callback cb_callback;
|
||||||
gsi::Callback cb_get_display_name;
|
gsi::Callback cb_get_display_name;
|
||||||
|
gsi::Callback cb_get_cell_name;
|
||||||
gsi::Callback cb_get_description;
|
gsi::Callback cb_get_description;
|
||||||
gsi::Callback cb_via_types;
|
gsi::Callback cb_via_types;
|
||||||
};
|
};
|
||||||
|
|
@ -682,6 +698,7 @@ Class<PCellDeclarationImpl> decl_PCellDeclaration (decl_PCellDeclaration_Native,
|
||||||
gsi::method ("parameters_from_shape", &PCellDeclarationImpl::parameters_from_shape_fb, "@hide") +
|
gsi::method ("parameters_from_shape", &PCellDeclarationImpl::parameters_from_shape_fb, "@hide") +
|
||||||
gsi::method ("transformation_from_shape", &PCellDeclarationImpl::transformation_from_shape_fb, "@hide") +
|
gsi::method ("transformation_from_shape", &PCellDeclarationImpl::transformation_from_shape_fb, "@hide") +
|
||||||
gsi::method ("display_text", &PCellDeclarationImpl::get_display_name_fb, "@hide") +
|
gsi::method ("display_text", &PCellDeclarationImpl::get_display_name_fb, "@hide") +
|
||||||
|
gsi::method ("cell_name", &PCellDeclarationImpl::get_cell_name_fb, "@hide") +
|
||||||
gsi::method ("wants_lazy_evaluation", &PCellDeclarationImpl::wants_lazy_evaluation_fb, "@hide") +
|
gsi::method ("wants_lazy_evaluation", &PCellDeclarationImpl::wants_lazy_evaluation_fb, "@hide") +
|
||||||
gsi::method ("description", &PCellDeclarationImpl::get_description_fb, "@hide") +
|
gsi::method ("description", &PCellDeclarationImpl::get_description_fb, "@hide") +
|
||||||
gsi::method ("via_types", &PCellDeclarationImpl::via_types_fb, "@hide") +
|
gsi::method ("via_types", &PCellDeclarationImpl::via_types_fb, "@hide") +
|
||||||
|
|
@ -809,6 +826,13 @@ Class<PCellDeclarationImpl> decl_PCellDeclaration (decl_PCellDeclaration_Native,
|
||||||
"@brief Returns the display text for this PCell given a certain parameter set\n"
|
"@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"
|
"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"
|
"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"
|
"@brief A PCell declaration providing the parameters and code to produce the PCell\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,13 @@ class PD
|
||||||
|
|
||||||
cell.shapes (l_metal0).insert (db::Box (0, 0, width, height));
|
cell.shapes (l_metal0).insert (db::Box (0, 0, width, height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::string get_display_name (const db::pcell_parameters_type ¶meters) const
|
||||||
|
{
|
||||||
|
db::Coord width = db::coord_traits<db::Coord>::rounded (parameters[0].to_double () * 1000.0);
|
||||||
|
db::Coord height = db::coord_traits<db::Coord>::rounded (parameters[1].to_double () * 1000.0);
|
||||||
|
return tl::sprintf ("PD(W=%d,H=%d)", width, height);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(0)
|
TEST(0)
|
||||||
|
|
@ -252,3 +259,114 @@ TEST(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PCell names, convert PCell to static
|
||||||
|
|
||||||
|
class PD2
|
||||||
|
: public PD
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual std::string get_cell_name (const db::pcell_parameters_type ¶meters) const
|
||||||
|
{
|
||||||
|
db::Coord width = db::coord_traits<db::Coord>::rounded (parameters[0].to_double () * 1000.0);
|
||||||
|
db::Coord height = db::coord_traits<db::Coord>::rounded (parameters[1].to_double () * 1000.0);
|
||||||
|
return tl::sprintf ("PD_W%d_H%d", width, height);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(2)
|
||||||
|
{
|
||||||
|
db::Manager m (true);
|
||||||
|
db::Layout layout(&m);
|
||||||
|
layout.dbu (0.001);
|
||||||
|
|
||||||
|
db::LayerProperties p;
|
||||||
|
|
||||||
|
p.layer = 23;
|
||||||
|
p.datatype = 0;
|
||||||
|
unsigned int l_cont = layout.insert_layer (p);
|
||||||
|
|
||||||
|
p.layer = 16;
|
||||||
|
p.datatype = 0;
|
||||||
|
unsigned int l_gate = layout.insert_layer (p);
|
||||||
|
|
||||||
|
db::Cell &cell_a = layout.cell (layout.add_cell ("A"));
|
||||||
|
cell_a.shapes(l_cont).insert(db::Box (50, 50, 150, 150));
|
||||||
|
cell_a.shapes(l_gate).insert(db::Box (0, 0, 200, 1000));
|
||||||
|
|
||||||
|
db::Cell &top = layout.cell (layout.add_cell ("TOP"));
|
||||||
|
|
||||||
|
db::pcell_id_type pd = layout.register_pcell ("PD", new PD2 ());
|
||||||
|
|
||||||
|
std::vector<tl::Variant> parameters;
|
||||||
|
parameters.push_back (tl::Variant ());
|
||||||
|
parameters.push_back (tl::Variant ());
|
||||||
|
parameters.push_back (tl::Variant ());
|
||||||
|
tl::Variant &width = parameters[0];
|
||||||
|
tl::Variant &height = parameters[1];
|
||||||
|
tl::Variant &orientation = parameters[2];
|
||||||
|
|
||||||
|
width = 0.5;
|
||||||
|
height = 1.0;
|
||||||
|
orientation = long (0);
|
||||||
|
|
||||||
|
db::cell_index_type pd1 = layout.get_pcell_variant (pd, parameters);
|
||||||
|
top.insert (db::CellInstArray (db::CellInst (pd1), db::Trans (db::Vector (0, 0))));
|
||||||
|
|
||||||
|
EXPECT_EQ (layout.display_name (pd1), "PD(W=500,H=1000)");
|
||||||
|
EXPECT_EQ (layout.cell_name (pd1), "PD_W500_H1000");
|
||||||
|
EXPECT_EQ (layout.variant_name (pd1), "PD_W500_H1000");
|
||||||
|
|
||||||
|
width = 0.4;
|
||||||
|
height = 0.8;
|
||||||
|
|
||||||
|
db::cell_index_type pd2 = layout.get_pcell_variant (pd, parameters);
|
||||||
|
top.insert (db::CellInstArray (db::CellInst (pd2), db::Trans (db::Vector (0, 2000))));
|
||||||
|
|
||||||
|
EXPECT_EQ (layout.display_name (pd2), "PD(W=400,H=800)");
|
||||||
|
EXPECT_EQ (layout.cell_name (pd2), "PD_W400_H800");
|
||||||
|
EXPECT_EQ (layout.variant_name (pd2), "PD_W400_H800");
|
||||||
|
|
||||||
|
EXPECT_NE (pd1, pd2);
|
||||||
|
|
||||||
|
width = 0.4;
|
||||||
|
height = 0.8;
|
||||||
|
orientation = long (1);
|
||||||
|
|
||||||
|
db::cell_index_type pd3 = layout.get_pcell_variant (pd, parameters);
|
||||||
|
auto i3 = top.insert (db::CellInstArray (db::CellInst (pd3), db::Trans (db::Vector (2000, 0))));
|
||||||
|
|
||||||
|
EXPECT_EQ (layout.display_name (pd3), "PD(W=400,H=800)");
|
||||||
|
EXPECT_EQ (layout.cell_name (pd3), "PD_W400_H800$1");
|
||||||
|
EXPECT_EQ (layout.variant_name (pd3), "PD_W400_H800");
|
||||||
|
|
||||||
|
EXPECT_NE (pd2, pd3);
|
||||||
|
|
||||||
|
auto pd3_org = pd3;
|
||||||
|
pd3 = layout.convert_cell_to_static (pd3);
|
||||||
|
EXPECT_NE (pd3, pd3_org);
|
||||||
|
|
||||||
|
auto ci3 = i3.cell_inst ();
|
||||||
|
ci3.object ().cell_index (pd3);
|
||||||
|
top.replace (i3, ci3);
|
||||||
|
|
||||||
|
EXPECT_EQ (layout.cell (pd3_org).is_proxy (), true);
|
||||||
|
EXPECT_EQ (layout.cell (pd3).is_proxy (), false);
|
||||||
|
|
||||||
|
EXPECT_EQ (layout.display_name (pd3_org), "PD(W=400,H=800)");
|
||||||
|
EXPECT_EQ (layout.cell_name (pd3_org), "PD_W400_H800$2");
|
||||||
|
EXPECT_EQ (layout.variant_name (pd3_org), "PD_W400_H800");
|
||||||
|
|
||||||
|
layout.do_cleanup (true);
|
||||||
|
layout.cleanup ();
|
||||||
|
|
||||||
|
EXPECT_EQ (layout.is_valid_cell_index (pd3_org), false);
|
||||||
|
|
||||||
|
EXPECT_EQ (layout.display_name (pd3), "PD_W400_H800$1");
|
||||||
|
EXPECT_EQ (layout.cell_name (pd3), "PD_W400_H800$1");
|
||||||
|
EXPECT_EQ (layout.variant_name (pd3), "PD_W400_H800$1");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CHECKPOINT ();
|
||||||
|
db::compare_layouts (_this, layout, tl::testdata () + "/gds/pcell_test20.gds", db::NoNormalization);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,21 @@ class _PCellDeclarationHelperMixin:
|
||||||
self._finish()
|
self._finish()
|
||||||
return text
|
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):
|
def get_parameters(self):
|
||||||
"""
|
"""
|
||||||
Reimplementation of PCellDeclaration.get_parameters
|
Reimplementation of PCellDeclaration.get_parameters
|
||||||
|
|
@ -333,6 +348,12 @@ class _PCellDeclarationHelperMixin:
|
||||||
"""
|
"""
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def cell_name_impl(self):
|
||||||
|
"""
|
||||||
|
default implementation
|
||||||
|
"""
|
||||||
|
return self.name()
|
||||||
|
|
||||||
def coerce_parameters_impl(self):
|
def coerce_parameters_impl(self):
|
||||||
"""
|
"""
|
||||||
default implementation
|
default implementation
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -27,6 +27,10 @@ class BoxPCell(pya.PCellDeclaration):
|
||||||
# provide a descriptive text for the cell
|
# provide a descriptive text for the cell
|
||||||
return "Box(L=" + str(parameters[0]) + ",W=" + ('%.3f' % parameters[1]) + ",H=" + ('%.3f' % parameters[2]) + ")"
|
return "Box(L=" + str(parameters[0]) + ",W=" + ('%.3f' % parameters[1]) + ",H=" + ('%.3f' % parameters[2]) + ")"
|
||||||
|
|
||||||
|
def cell_name(self, parameters):
|
||||||
|
# provide a descriptive text for the cell
|
||||||
|
return "Box_L" + str(parameters[0]).replace("/", "d") + "_W" + ('%.3f' % parameters[1]).replace(".", "p") + "_H" + ('%.3f' % parameters[2]).replace(".", "p")
|
||||||
|
|
||||||
def get_parameters(self):
|
def get_parameters(self):
|
||||||
|
|
||||||
# prepare a set of parameter declarations
|
# prepare a set of parameter declarations
|
||||||
|
|
@ -100,6 +104,10 @@ if "PCellDeclarationHelper" in pya.__dict__:
|
||||||
# provide a descriptive text for the cell
|
# provide a descriptive text for the cell
|
||||||
return "Box2(L=" + str(self.layer) + ",W=" + ('%.3f' % self.width) + ",H=" + ('%.3f' % self.height) + ")"
|
return "Box2(L=" + str(self.layer) + ",W=" + ('%.3f' % self.width) + ",H=" + ('%.3f' % self.height) + ")"
|
||||||
|
|
||||||
|
def cell_name_impl(self):
|
||||||
|
# provide a descriptive text for the cell
|
||||||
|
return "Box2_L" + str(self.layer).replace("/", "d") + "_W" + ('%.3f' % self.width).replace(".", "p") + "_H" + ('%.3f' % self.height).replace(".", "p")
|
||||||
|
|
||||||
def wants_lazy_evaluation(self):
|
def wants_lazy_evaluation(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
@ -260,6 +268,8 @@ class DBPCellTests(unittest.TestCase):
|
||||||
self.assertEqual(pcell_var.is_pcell_variant(), True)
|
self.assertEqual(pcell_var.is_pcell_variant(), True)
|
||||||
self.assertEqual(pcell_var.display_title(), "PCellTestLib.Box(L=1/0,W=1.000,H=1.000)")
|
self.assertEqual(pcell_var.display_title(), "PCellTestLib.Box(L=1/0,W=1.000,H=1.000)")
|
||||||
self.assertEqual(pcell_var.basic_name(), "Box")
|
self.assertEqual(pcell_var.basic_name(), "Box")
|
||||||
|
self.assertEqual(pcell_var.qname(), "PCellTestLib.Box")
|
||||||
|
self.assertEqual(pcell_var.name, "Box_L1d0_W1p000_H1p000")
|
||||||
self.assertEqual(pcell_var.pcell_declaration().wants_lazy_evaluation(), False)
|
self.assertEqual(pcell_var.pcell_declaration().wants_lazy_evaluation(), False)
|
||||||
self.assertEqual(c1.is_pcell_variant(), False)
|
self.assertEqual(c1.is_pcell_variant(), False)
|
||||||
self.assertEqual(c1.is_pcell_variant(pcell_inst), True)
|
self.assertEqual(c1.is_pcell_variant(pcell_inst), True)
|
||||||
|
|
@ -394,6 +404,8 @@ class DBPCellTests(unittest.TestCase):
|
||||||
pcell_var = ly.cell(pcell_var_id)
|
pcell_var = ly.cell(pcell_var_id)
|
||||||
pcell_inst = c1.insert(pya.CellInstArray(pcell_var_id, pya.Trans()))
|
pcell_inst = c1.insert(pya.CellInstArray(pcell_var_id, pya.Trans()))
|
||||||
self.assertEqual(pcell_var.basic_name(), "Box2")
|
self.assertEqual(pcell_var.basic_name(), "Box2")
|
||||||
|
self.assertEqual(pcell_var.name, "Box2_L1d0_W1p000_H1p000")
|
||||||
|
self.assertEqual(pcell_var.qname(), "PCellTestLib2.Box2")
|
||||||
self.assertEqual(pcell_var.pcell_parameters().__repr__(), "[<1/0>, 1.0, 1.0]")
|
self.assertEqual(pcell_var.pcell_parameters().__repr__(), "[<1/0>, 1.0, 1.0]")
|
||||||
self.assertEqual(pcell_var.display_title(), "PCellTestLib2.Box2(L=1/0,W=1.000,H=1.000)")
|
self.assertEqual(pcell_var.display_title(), "PCellTestLib2.Box2(L=1/0,W=1.000,H=1.000)")
|
||||||
self.assertEqual(nh(pcell_var.pcell_parameters_by_name()), "{'height': 1.0, 'layer': <1/0>, 'width': 1.0}")
|
self.assertEqual(nh(pcell_var.pcell_parameters_by_name()), "{'height': 1.0, 'layer': <1/0>, 'width': 1.0}")
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,11 @@ class BoxPCell < RBA::PCellDeclaration
|
||||||
# provide a descriptive text for the cell
|
# provide a descriptive text for the cell
|
||||||
return "Box(L=#{parameters[0].to_s},W=#{'%.3f' % parameters[1].to_s},H=#{'%.3f' % parameters[2].to_s})"
|
return "Box(L=#{parameters[0].to_s},W=#{'%.3f' % parameters[1].to_s},H=#{'%.3f' % parameters[2].to_s})"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cell_name(parameters)
|
||||||
|
# provide a cell name for the PCell
|
||||||
|
return "Box_L#{parameters[0].to_s.gsub('/','d')}_W#{('%.3f' % parameters[1]).gsub('.','p')}_H#{('%.3f' % parameters[2]).gsub('.','p')}"
|
||||||
|
end
|
||||||
|
|
||||||
def get_parameters
|
def get_parameters
|
||||||
|
|
||||||
|
|
@ -129,6 +134,11 @@ if RBA.constants.member?(:PCellDeclarationHelper)
|
||||||
return "Box2(L=" + layer.to_s + ",W=" + ('%.3f' % width) + ",H=" + ('%.3f' % height) + ")"
|
return "Box2(L=" + layer.to_s + ",W=" + ('%.3f' % width) + ",H=" + ('%.3f' % height) + ")"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cell_name_impl
|
||||||
|
# provide a cell name for the PCell
|
||||||
|
return "Box2_L" + layer.to_s.gsub('/', 'd') + "_W" + ('%.3f' % width).gsub('.', 'p') + "_H" + ('%.3f' % height).gsub('.', 'p')
|
||||||
|
end
|
||||||
|
|
||||||
def produce_impl
|
def produce_impl
|
||||||
|
|
||||||
# fetch the parameters
|
# fetch the parameters
|
||||||
|
|
@ -371,6 +381,9 @@ class DBPCell_TestClass < TestBase
|
||||||
param = [ RBA::LayerInfo::new(1, 0) ] # rest is filled with defaults
|
param = [ RBA::LayerInfo::new(1, 0) ] # rest is filled with defaults
|
||||||
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
|
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param)
|
||||||
pcell_var = ly.cell(pcell_var_id)
|
pcell_var = ly.cell(pcell_var_id)
|
||||||
|
assert_equal(pcell_var.name, "Box_L1d0_W1p000_H1p000")
|
||||||
|
assert_equal(pcell_var.qname, "PCellTestLib.Box")
|
||||||
|
assert_equal(pcell_var.basic_name, "Box")
|
||||||
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
|
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
|
||||||
assert_equal(pcell_var.layout.inspect, ly.inspect)
|
assert_equal(pcell_var.layout.inspect, ly.inspect)
|
||||||
assert_equal(pcell_var.library.inspect, lib.inspect)
|
assert_equal(pcell_var.library.inspect, lib.inspect)
|
||||||
|
|
@ -512,6 +525,8 @@ class DBPCell_TestClass < TestBase
|
||||||
pcell_var = ly.cell(pcell_var_id)
|
pcell_var = ly.cell(pcell_var_id)
|
||||||
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
|
pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new))
|
||||||
assert_equal(pcell_var.basic_name, "Box2")
|
assert_equal(pcell_var.basic_name, "Box2")
|
||||||
|
assert_equal(pcell_var.name, "Box2_L1d0_W1p000_H1p000")
|
||||||
|
assert_equal(pcell_var.qname, "PCellTestLib2.Box2")
|
||||||
assert_equal(pcell_var.pcell_parameters().inspect, "[<1/0>, 1.0, 1.0, 0]")
|
assert_equal(pcell_var.pcell_parameters().inspect, "[<1/0>, 1.0, 1.0, 0]")
|
||||||
assert_equal(pcell_var.display_title(), "PCellTestLib2.Box2(L=1/0,W=1.000,H=1.000)")
|
assert_equal(pcell_var.display_title(), "PCellTestLib2.Box2(L=1/0,W=1.000,H=1.000)")
|
||||||
assert_equal(norm_hash(pcell_var.pcell_parameters_by_name()), "{\"height\"=>1.0, \"layer\"=><1/0>, \"secret\"=>0, \"width\"=>1.0}")
|
assert_equal(norm_hash(pcell_var.pcell_parameters_by_name()), "{\"height\"=>1.0, \"layer\"=><1/0>, \"secret\"=>0, \"width\"=>1.0}")
|
||||||
|
|
@ -908,6 +923,37 @@ class DBPCell_TestClass < TestBase
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# convert to static cell
|
||||||
|
def test_13
|
||||||
|
|
||||||
|
if !RBA.constants.member?(:PCellDeclarationHelper)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# instantiate and register the library
|
||||||
|
tl = PCellTestLib2::new
|
||||||
|
|
||||||
|
ly = RBA::Layout::new(true)
|
||||||
|
ly.dbu = 0.01
|
||||||
|
|
||||||
|
ci1 = ly.add_cell("c1")
|
||||||
|
c1 = ly.cell(ci1)
|
||||||
|
|
||||||
|
lib = RBA::Library.library_by_name("PCellTestLib2")
|
||||||
|
assert_equal(lib != nil, true)
|
||||||
|
pcell_decl = lib.layout().pcell_declaration("Box2")
|
||||||
|
|
||||||
|
param = [ RBA::LayerInfo::new(1, 0) ] # rest is filled with defaults
|
||||||
|
pcell_var_id = ly.add_pcell_variant(lib, pcell_decl.id(), param)
|
||||||
|
static_id = ly.convert_cell_to_static(pcell_var_id)
|
||||||
|
static = ly.cell(static_id)
|
||||||
|
assert_equal(static.basic_name, "Box2_L1d0_W1p000_H1p000")
|
||||||
|
assert_equal(static.name, "Box2_L1d0_W1p000_H1p000")
|
||||||
|
assert_equal(static.qname, "Box2_L1d0_W1p000_H1p000")
|
||||||
|
assert_equal(static.is_proxy?, false)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class DBPCellParameterStates_TestClass < TestBase
|
class DBPCellParameterStates_TestClass < TestBase
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue