First implementation of issue-1075 fix: when editing a layer spec, the PCell parameters are analyzed and PCells are rewritten accordingly. (#1088)

This commit is contained in:
Matthias Köfferlein 2022-05-31 00:22:32 +02:00 committed by GitHub
parent 6bcb7d0aa6
commit 4cbd28fd23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 25 deletions

View File

@ -266,16 +266,7 @@ CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_ind
}
// replace all instances of the new cell with the original one
std::vector<std::pair<db::cell_index_type, db::Instance> > parents;
for (db::Cell::parent_inst_iterator pi = src_cell.begin_parent_insts (); ! pi.at_end (); ++pi) {
parents.push_back (std::make_pair (pi->parent_cell_index (), pi->child_inst ()));
}
for (std::vector<std::pair<db::cell_index_type, db::Instance> >::const_iterator p = parents.begin (); p != parents.end (); ++p) {
db::CellInstArray ia = p->second.cell_inst ();
ia.object ().cell_index (target_cell.cell_index ());
layout.cell (p->first).replace (p->second, ia);
}
layout.replace_instances_of (src_cell.cell_index (), target_cell.cell_index ());
// finally delete the new cell
layout.delete_cell (src_cell.cell_index ());

View File

@ -2133,6 +2133,22 @@ Layout::replace_cell (cell_index_type target_cell_index, db::Cell *new_cell, boo
}
}
void
Layout::replace_instances_of (cell_index_type src_cell_index, cell_index_type target_cell_index)
{
// replace all instances of the new cell with the original one
std::vector<std::pair<db::cell_index_type, db::Instance> > parents;
for (db::Cell::parent_inst_iterator pi = cell (src_cell_index).begin_parent_insts (); ! pi.at_end (); ++pi) {
parents.push_back (std::make_pair (pi->parent_cell_index (), pi->child_inst ()));
}
for (std::vector<std::pair<db::cell_index_type, db::Instance> >::const_iterator p = parents.begin (); p != parents.end (); ++p) {
db::CellInstArray ia = p->second.cell_inst ();
ia.object ().cell_index (target_cell_index);
cell (p->first).replace (p->second, ia);
}
}
void
Layout::get_pcell_variant_as (pcell_id_type pcell_id, const std::vector<tl::Variant> &p, cell_index_type target_cell_index, ImportLayerMapping *layer_mapping, bool retain_layout)
{

View File

@ -1131,6 +1131,11 @@ public:
*/
void replace_cell (cell_index_type target_cell_index, db::Cell *new_cell, bool retain_layout);
/**
* @brief Replaces all instances of src_cell_index by target_cell_index
*/
void replace_instances_of (cell_index_type src_cell_index, cell_index_type target_cell_index);
/**
* @brief Delete a cell plus the subcells not used otherwise
*

View File

@ -37,6 +37,7 @@
#include "dbClipboard.h"
#include "dbRecursiveShapeIterator.h"
#include "dbLayoutUtils.h"
#include "dbPCellDeclaration.h"
#include <QMessageBox>
#include <QInputDialog>
@ -485,18 +486,8 @@ LayoutViewFunctions::cm_cell_replace ()
// replace instances of the target cell with the new cell
db::Cell &target_cell = layout.cell (paths.front ().back ());
std::vector<std::pair<db::cell_index_type, db::Instance> > parents;
for (db::Cell::parent_inst_iterator pi = target_cell.begin_parent_insts (); ! pi.at_end (); ++pi) {
parents.push_back (std::make_pair (pi->parent_cell_index (), pi->child_inst ()));
}
for (std::vector<std::pair<db::cell_index_type, db::Instance> >::const_iterator p = parents.begin (); p != parents.end (); ++p) {
db::CellInstArray ia = p->second.cell_inst ();
ia.object ().cell_index (with_cell);
layout.cell (p->first).replace (p->second, ia);
}
db::cell_index_type target_cell_index = paths.front ().back ();
layout.replace_instances_of (target_cell_index, with_cell);
std::set<db::cell_index_type> cells_to_delete;
for (std::vector<lay::LayoutViewBase::cell_path_type>::const_iterator p = paths.begin (); p != paths.end (); ++p) {
@ -1881,14 +1872,16 @@ LayoutViewFunctions::cm_edit_layer ()
}
const lay::CellView &cv = view ()->cellview (index);
db::Layout &layout = cv->layout ();
db::LayerProperties layer_props = cv->layout ().get_properties ((unsigned int) sel->layer_index ());
db::LayerProperties layer_props = layout.get_properties ((unsigned int) sel->layer_index ());
db::LayerProperties old_props = layer_props;
lay::NewLayerPropertiesDialog prop_dia (view ()->widget ());
if (prop_dia.exec_dialog (cv, layer_props)) {
for (unsigned int l = 0; l < cv->layout ().layers (); ++l) {
if (cv->layout ().is_valid_layer (l) && int (l) != sel->layer_index () && cv->layout ().get_properties (l).log_equal (layer_props)) {
for (unsigned int l = 0; l < layout.layers (); ++l) {
if (cv->layout ().is_valid_layer (l) && int (l) != sel->layer_index () && layout.get_properties (l).log_equal (layer_props)) {
throw tl::Exception (tl::to_string (tr ("A layer with that signature already exists: ")) + layer_props.to_string ());
}
}
@ -1897,6 +1890,56 @@ LayoutViewFunctions::cm_edit_layer ()
cv->layout ().set_properties (sel->layer_index (), layer_props);
// Update all layer parameters for PCells inside the layout
// collect PCell variants first
std::vector<std::pair<db::cell_index_type, const db::PCellDeclaration *> > pcell_variants;
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
const db::PCellDeclaration *pcell_decl = layout.pcell_declaration_for_pcell_variant (c->cell_index ());
if (pcell_decl) {
pcell_variants.push_back (std::make_pair (c->cell_index (), pcell_decl));
}
}
// translate parameters if required
std::map<db::cell_index_type, db::cell_index_type> cell_map;
for (auto c = pcell_variants.begin (); c != pcell_variants.end (); ++c) {
const std::vector<tl::Variant> &old_param = layout.get_pcell_parameters (c->first);
std::vector<tl::Variant> new_param;
const std::vector<db::PCellParameterDeclaration> &pd = c->second->parameter_declarations ();
auto v = old_param.begin ();
auto p = pd.begin ();
while (v != old_param.end () && p != pd.end ()) {
if (p->get_type () == db::PCellParameterDeclaration::t_layer && v->to_user<db::LayerProperties> ().log_equal (old_props)) {
if (new_param.empty ()) {
new_param = old_param;
}
new_param [v - old_param.begin ()] = tl::Variant (layer_props);
}
++v, ++p;
}
if (! new_param.empty ()) {
db::cell_index_type new_cell = layout.get_pcell_variant_cell (c->first, new_param);
cell_map[c->first] = new_cell;
}
}
// change instances
{
db::LayoutLocker locker (&layout);
for (auto c = cell_map.begin (); c != cell_map.end (); ++c) {
layout.replace_instances_of (c->first, c->second);
}
}
layout.cleanup ();
// Adjust view
lay::LayerProperties lp (*sel);
lay::ParsedLayerSource s = lp.source (false);
s.layer (layer_props.layer);