Merge pull request #1663 from KLayout/issue-1638

Issue 1638
This commit is contained in:
Matthias Köfferlein 2024-03-29 08:58:17 +01:00 committed by GitHub
commit 4c5aeff1b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 253 additions and 176 deletions

View File

@ -30,6 +30,42 @@
namespace db
{
// ------------------------------------------------------------------
// Implementation of StreamFormatDeclaration
std::string StreamFormatDeclaration::all_formats_string ()
{
std::string fmts = tl::to_string (tr ("All layout files ("));
for (tl::Registrar<db::StreamFormatDeclaration>::iterator rdr = tl::Registrar<db::StreamFormatDeclaration>::begin (); rdr != tl::Registrar<db::StreamFormatDeclaration>::end (); ++rdr) {
if (rdr != tl::Registrar<db::StreamFormatDeclaration>::begin ()) {
fmts += " ";
}
std::string f = rdr->file_format ();
if (!f.empty ()) {
const char *fp = f.c_str ();
while (*fp && *fp != '(') {
++fp;
}
if (*fp) {
++fp;
}
while (*fp && *fp != ')') {
fmts += *fp++;
}
}
}
fmts += ")";
for (tl::Registrar<db::StreamFormatDeclaration>::iterator rdr = tl::Registrar<db::StreamFormatDeclaration>::begin (); rdr != tl::Registrar<db::StreamFormatDeclaration>::end (); ++rdr) {
if (!rdr->file_format ().empty ()) {
fmts += ";;";
fmts += rdr->file_format ();
}
}
return fmts;
}
// ------------------------------------------------------------------
// Implementation of load_options_xml_element_list

View File

@ -136,6 +136,11 @@ public:
{
return 0;
}
/**
* @brief Returns a string for the file dialogs that describes all formats
*/
static std::string all_formats_string ();
};
/**

View File

@ -498,34 +498,9 @@ MainWindow::~MainWindow ()
std::string
MainWindow::all_layout_file_formats () const
{
std::string fmts = tl::to_string (QObject::tr ("All layout files ("));
for (tl::Registrar<db::StreamFormatDeclaration>::iterator rdr = tl::Registrar<db::StreamFormatDeclaration>::begin (); rdr != tl::Registrar<db::StreamFormatDeclaration>::end (); ++rdr) {
if (rdr != tl::Registrar<db::StreamFormatDeclaration>::begin ()) {
fmts += " ";
}
std::string f = rdr->file_format ();
if (!f.empty ()) {
const char *fp = f.c_str ();
while (*fp && *fp != '(') {
++fp;
}
if (*fp) {
++fp;
}
while (*fp && *fp != ')') {
fmts += *fp++;
}
}
}
fmts += ");;";
for (tl::Registrar<db::StreamFormatDeclaration>::iterator rdr = tl::Registrar<db::StreamFormatDeclaration>::begin (); rdr != tl::Registrar<db::StreamFormatDeclaration>::end (); ++rdr) {
if (!rdr->file_format ().empty ()) {
fmts += rdr->file_format ();
fmts += ";;";
}
}
fmts += tl::to_string (QObject::tr ("All files (*)"));
std::string fmts = db::StreamFormatDeclaration::all_formats_string ();
fmts += ";;";
fmts += tl::to_string (tr ("All files (*)"));
return fmts;
}

View File

@ -35,6 +35,7 @@
#include "layConfigurationDialog.h"
#include "dbLayoutUtils.h"
#include "dbRecursiveShapeIterator.h"
#include "dbStream.h"
#include "ui_MarkerBrowserDialog.h"
@ -420,11 +421,17 @@ BEGIN_PROTECTED
// collect the formats available ...
std::string fmts = tl::to_string (QObject::tr ("All files (*)"));
for (tl::Registrar<rdb::FormatDeclaration>::iterator rdr = tl::Registrar<rdb::FormatDeclaration>::begin (); rdr != tl::Registrar<rdb::FormatDeclaration>::end (); ++rdr) {
fmts += ";;" + rdr->file_format ();
fmts += ";;";
fmts += rdr->file_format ();
}
// also provide the stream formats
fmts += ";;";
fmts += db::StreamFormatDeclaration::all_formats_string ();
// prepare and open the file dialog
lay::FileDialog open_dialog (this, tl::to_string (QObject::tr ("Load Marker Database File")), fmts);
if (open_dialog.get_open (m_open_filename)) {
std::unique_ptr <rdb::Database> db (new rdb::Database ());
@ -731,111 +738,17 @@ MarkerBrowserDialog::deactivated ()
void
MarkerBrowserDialog::scan_layer ()
{
std::vector<lay::LayerPropertiesConstIterator> layers = view ()->selected_layers ();
if (layers.empty ()) {
throw tl::Exception (tl::to_string (QObject::tr ("No layer selected to get shapes from")));
}
int cv_index = -1;
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
if (!(*l)->has_children ()) {
if (cv_index < 0) {
cv_index = (*l)->cellview_index ();
} else if ((*l)->cellview_index () >= 0) {
if (cv_index != (*l)->cellview_index ()) {
throw tl::Exception (tl::to_string (QObject::tr ("All layers must originate from the same layout")));
}
}
}
}
if (cv_index < 0) {
throw tl::Exception (tl::to_string (QObject::tr ("No valid layer selected")));
}
tl::AbsoluteProgress progress (tl::to_string (QObject::tr ("Shapes To Markers")), 10000);
progress.set_format (tl::to_string (QObject::tr ("%.0f0000 markers")));
progress.set_unit (10000);
const lay::CellView &cv = view ()->cellview (cv_index);
const db::Layout &layout = cv->layout ();
std::unique_ptr<rdb::Database> rdb (new rdb::Database ());
rdb->set_name ("Shapes");
rdb->set_top_cell_name (layout.cell_name (cv.cell_index ()));
rdb::Cell *rdb_top_cell = rdb->create_cell (rdb->top_cell_name ());
std::string desc;
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) {
if (! desc.empty ()) {
desc += ", ";
}
desc += layout.get_properties ((*l)->layer_index ()).to_string ();
}
}
desc = tl::to_string (tr ("Hierarchical shapes of layer(s) ")) + desc;
desc += " ";
desc += tl::to_string (tr ("from cell "));
desc += cv->layout ().cell_name (cv.cell_index ());
rdb->set_description (desc);
std::set<db::cell_index_type> called_cells;
called_cells.insert (cv.cell_index ());
cv->layout ().cell (cv.cell_index ()).collect_called_cells (called_cells);
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) {
rdb::Category *cat = rdb->create_category (layout.get_properties ((*l)->layer_index ()).to_string ());
for (db::Layout::const_iterator cid = layout.begin (); cid != layout.end (); ++cid) {
if (called_cells.find (cid->cell_index ()) == called_cells.end ()) {
continue;
}
const db::Cell &cell = *cid;
if (cell.shapes ((*l)->layer_index ()).size () > 0) {
std::string cn = layout.cell_name (cell.cell_index ());
const rdb::Cell *rdb_cell = rdb->cell_by_qname (cn);
if (! rdb_cell) {
rdb::Cell *rdb_cell_nc = rdb->create_cell (cn);
rdb_cell = rdb_cell_nc;
std::pair<bool, db::ICplxTrans> ctx = db::find_layout_context (layout, cell.cell_index (), cv.cell_index ());
if (ctx.first) {
db::DCplxTrans t = db::DCplxTrans (layout.dbu ()) * db::DCplxTrans (ctx.second) * db::DCplxTrans (1.0 / layout.dbu ());
rdb_cell_nc->references ().insert (Reference (t, rdb_top_cell->id ()));
}
}
for (db::ShapeIterator shape = cell.shapes ((*l)->layer_index ()).begin (db::ShapeIterator::All); ! shape.at_end (); ++shape) {
rdb::create_item_from_shape (rdb.get (), rdb_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()), *shape);
++progress;
}
}
}
}
}
unsigned int rdb_index = view ()->add_rdb (rdb.release ());
view ()->open_rdb_browser (rdb_index, cv_index);
scan_layer_flat_or_hierarchical (false);
}
void
void
MarkerBrowserDialog::scan_layer_flat ()
{
scan_layer_flat_or_hierarchical (true);
}
void
MarkerBrowserDialog::scan_layer_flat_or_hierarchical (bool flat)
{
std::vector<lay::LayerPropertiesConstIterator> layers = view ()->selected_layers ();
if (layers.empty ()) {
@ -859,52 +772,19 @@ MarkerBrowserDialog::scan_layer_flat ()
throw tl::Exception (tl::to_string (QObject::tr ("No valid layer selected")));
}
tl::AbsoluteProgress progress (tl::to_string (QObject::tr ("Shapes To Markers")), 10000);
progress.set_format (tl::to_string (QObject::tr ("%.0f0000 markers")));
progress.set_unit (10000);
const lay::CellView &cv = view ()->cellview (cv_index);
const db::Layout &layout = cv->layout ();
std::vector<std::pair <unsigned int, std::string> > layer_indexes;
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) {
layer_indexes.push_back (std::make_pair ((*l)->layer_index (), (*l)->name ()));
}
}
std::unique_ptr<rdb::Database> rdb (new rdb::Database ());
rdb->set_name ("Shapes");
rdb->set_top_cell_name (layout.cell_name (cv.cell_index ()));
rdb::Cell *rdb_top_cell = rdb->create_cell (rdb->top_cell_name ());
std::string desc;
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) {
if (! desc.empty ()) {
desc += ", ";
}
desc += layout.get_properties ((*l)->layer_index ()).to_string ();
}
}
desc = tl::to_string (tr ("Flat shapes of layer(s) ")) + desc;
desc += " ";
desc += tl::to_string (tr ("from cell "));
desc += cv->layout ().cell_name (cv.cell_index ());
rdb->set_description (desc);
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) {
rdb::Category *cat = rdb->create_category (layout.get_properties ((*l)->layer_index ()).to_string ());
db::RecursiveShapeIterator shape (layout, *cv.cell (), (*l)->layer_index ());
while (! shape.at_end ()) {
rdb::create_item_from_shape (rdb.get (), rdb_top_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()) * shape.trans (), *shape);
++progress;
++shape;
}
}
}
rdb->scan_layout (layout, cv.cell_index (), layer_indexes, flat);
unsigned int rdb_index = view ()->add_rdb (rdb.release ());
view ()->open_rdb_browser (rdb_index, cv_index);

View File

@ -36,9 +36,16 @@ namespace Ui
class MarkerBrowserDialog;
}
namespace db
{
class Layout;
}
namespace rdb
{
class Database;
class LAYUI_PUBLIC MarkerBrowserDialog
: public lay::Browser
{
@ -101,6 +108,7 @@ private:
void update_content ();
void scan_layer ();
void scan_layer_flat ();
void scan_layer_flat_or_hierarchical (bool flat);
};
}

View File

@ -23,11 +23,13 @@
#include "rdb.h"
#include "rdbReader.h"
#include "rdbUtils.h"
#include "tlString.h"
#include "tlAssert.h"
#include "tlStream.h"
#include "tlLog.h"
#include "tlBase64.h"
#include "tlProgress.h"
#include "dbPolygon.h"
#include "dbBox.h"
#include "dbEdge.h"
@ -35,6 +37,10 @@
#include "dbPath.h"
#include "dbText.h"
#include "dbShape.h"
#include "dbLayout.h"
#include "dbLayoutUtils.h"
#include "dbReader.h"
#include "dbRecursiveShapeIterator.h"
#if defined(HAVE_QT)
# include <QByteArray>
@ -1599,16 +1605,49 @@ Database::clear ()
mp_categories->set_database (this);
}
static void
read_db_from_layout (rdb::Database *db, tl::InputStream &is)
{
// try reading a layout file
db::Layout layout;
db::Reader reader (is);
reader.read (layout);
std::vector<std::pair<unsigned int, std::string> > layers;
for (auto l = layout.begin_layers (); l != layout.end_layers (); ++l) {
layers.push_back (std::make_pair ((*l).first, std::string ()));
}
if (layout.begin_top_down () != layout.end_top_down ()) {
db->scan_layout (layout, *layout.begin_top_down (), layers, false /*hierarchical*/);
}
}
void
Database::load (const std::string &fn)
{
tl::log << "Loading RDB from " << fn;
tl::InputStream stream (fn);
rdb::Reader reader (stream);
clear ();
reader.read (*this);
tl::InputStream stream (fn);
bool ok = false;
try {
// try reading a stream file
read_db_from_layout (this, stream);
ok = true;
} catch (tl::Exception &) {
stream.reset ();
}
if (! ok) {
// try reading a DB file
clear ();
rdb::Reader reader (stream);
reader.read (*this);
}
set_filename (stream.absolute_path ());
set_name (stream.filename ());
@ -1620,5 +1659,128 @@ Database::load (const std::string &fn)
}
}
void
Database::scan_layout (const db::Layout &layout, db::cell_index_type cell_index, const std::vector<std::pair<unsigned int, std::string> > &layers_and_descriptions, bool flat)
{
tl::AbsoluteProgress progress (tl::to_string (tr ("Shapes To Markers")), 10000);
progress.set_format (tl::to_string (tr ("%.0f0000 markers")));
progress.set_unit (10000);
set_name ("Shapes");
set_top_cell_name (layout.cell_name (cell_index));
rdb::Cell *rdb_top_cell = create_cell (top_cell_name ());
std::string desc;
if (layers_and_descriptions.size () == 1) {
if (flat) {
desc = tl::to_string (tr ("Flat shapes of layer "));
} else {
desc = tl::to_string (tr ("Hierarchical shapes of layer "));
}
desc += layout.get_properties (layers_and_descriptions.front ().first).to_string ();
} else if (layers_and_descriptions.size () < 4 && layers_and_descriptions.size () > 0) {
if (flat) {
desc = tl::to_string (tr ("Flat shapes of layers "));
} else {
desc = tl::to_string (tr ("Hierarchical shapes of layers "));
}
for (auto l = layers_and_descriptions.begin (); l != layers_and_descriptions.end (); ++l) {
if (l != layers_and_descriptions.begin ()) {
desc += ",";
}
desc += layout.get_properties (l->first).to_string ();
}
} else {
if (flat) {
desc = tl::sprintf (tl::to_string (tr ("Flat shapes of %d layers")), int (layers_and_descriptions.size ()));
} else {
desc = tl::sprintf (tl::to_string (tr ("Hierarchical shapes of %d layers")), int (layers_and_descriptions.size ()));
}
}
desc += " ";
desc += tl::to_string (tr ("from cell "));
desc += layout.cell_name (cell_index);
set_description (desc);
if (flat) {
for (auto l = layers_and_descriptions.begin (); l != layers_and_descriptions.end (); ++l) {
rdb::Category *cat = create_category (l->second.empty () ? layout.get_properties (l->first).to_string () : l->second);
db::RecursiveShapeIterator shape (layout, layout.cell (cell_index), l->first);
while (! shape.at_end ()) {
rdb::create_item_from_shape (this, rdb_top_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()) * shape.trans (), *shape);
++progress;
++shape;
}
}
} else {
std::set<db::cell_index_type> called_cells;
called_cells.insert (cell_index);
layout.cell (cell_index).collect_called_cells (called_cells);
for (auto l = layers_and_descriptions.begin (); l != layers_and_descriptions.end (); ++l) {
rdb::Category *cat = create_category (l->second.empty () ? layout.get_properties (l->first).to_string () : l->second);
for (db::Layout::const_iterator cid = layout.begin (); cid != layout.end (); ++cid) {
if (called_cells.find (cid->cell_index ()) == called_cells.end ()) {
continue;
}
const db::Cell &cell = *cid;
if (! cell.shapes (l->first).empty ()) {
std::string cn = layout.cell_name (cell.cell_index ());
const rdb::Cell *rdb_cell = cell_by_qname (cn);
if (! rdb_cell) {
rdb::Cell *rdb_cell_nc = create_cell (cn);
rdb_cell = rdb_cell_nc;
std::pair<bool, db::ICplxTrans> ctx = db::find_layout_context (layout, cell.cell_index (), cell_index);
if (ctx.first) {
db::DCplxTrans t = db::DCplxTrans (layout.dbu ()) * db::DCplxTrans (ctx.second) * db::DCplxTrans (1.0 / layout.dbu ());
rdb_cell_nc->references ().insert (Reference (t, rdb_top_cell->id ()));
}
}
for (db::ShapeIterator shape = cell.shapes (l->first).begin (db::ShapeIterator::All); ! shape.at_end (); ++shape) {
rdb::create_item_from_shape (this, rdb_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()), *shape);
++progress;
}
}
}
}
}
}
} // namespace rdb

View File

@ -50,6 +50,7 @@ namespace tl
namespace db
{
class Shape;
class Layout;
}
namespace rdb
@ -2384,6 +2385,16 @@ public:
*/
void load (const std::string &filename);
/**
* @brief Scans a layout into this RDB
*
* @param layout The layout to scan
* @param cell_index The top cell to scan
* @param layers_and_descriptions The layers and (optional) descriptions/names of the layer to scan
* @param flat True, to perform a flat scan
*/
void scan_layout (const db::Layout &layout, db::cell_index_type cell_index, const std::vector<std::pair<unsigned int, std::string> > &layers_and_descriptions, bool flat);
private:
std::string m_generator;
std::string m_filename;