From 3a2d44bd12a2e9d50ec36ee8cc689c6fb38c5301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6fferlein?= Date: Thu, 19 May 2022 22:14:07 +0200 Subject: [PATCH 1/5] Fixed #1081 (#1084) --- src/lay/lay/layMainWindow.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index e1690b121..f6dc15a82 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -2046,6 +2046,10 @@ MainWindow::cm_load_layer_props () void MainWindow::load_layer_props_from_file (const std::string &fn) { + if (! current_view ()) { + throw tl::Exception (tl::to_string (QObject::tr ("No view open to load the layer properties for"))); + } + int target_cv_index = -2; if (current_view ()->cellviews () > 1 && is_single_cv_layer_properties_file (fn)) { From 49e5dffa9938ebd92cc8df9572973abb3dee0ec2 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 22 May 2022 22:39:56 +0200 Subject: [PATCH 2/5] Backward compatibility of build.sh call - qt5 and qt4 options are accepted but ingored --- build.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 97ef2b73a..daafa8c93 100755 --- a/build.sh +++ b/build.sh @@ -205,6 +205,12 @@ while [ "$*" != "" ]; do -libexpat) HAVE_EXPAT=1 ;; + -qt5) + echo "*** WARNING: -qt5 option is ignored - Qt version is auto-detected now." + ;; + -qt4) + echo "*** WARNING: -qt4 option is ignored - Qt version is auto-detected now." + ;; -option) MAKE_OPT="$MAKE_OPT $1" shift @@ -243,8 +249,6 @@ while [ "$*" != "" ]; do echo "" echo "Special options (usually auto-selected from ruby/python/Qt installation):" echo "" - echo " -qt4|-qt5 Use Qt4 or Qt5 API [default: auto detect]" - echo "" echo " -rblib Location of the .so/.dll to link for Ruby support" echo " -rbinc Location of the Ruby headers (in particular 'ruby.h')" echo " -rbinc and -rblib must be set to enable Ruby support" From 0398beffaecdb69d2ded087f6d5dce8cb510fe4c Mon Sep 17 00:00:00 2001 From: Kazunari Sekigawa Date: Tue, 24 May 2022 03:36:48 +0900 Subject: [PATCH 3/5] To make 'build.sh' detect the Qt type automatically. (#1086) --- macbuild/build4mac.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/macbuild/build4mac.py b/macbuild/build4mac.py index 9774583d2..66aca6e56 100755 --- a/macbuild/build4mac.py +++ b/macbuild/build4mac.py @@ -889,8 +889,8 @@ def Run_Build_Command(parameters): # (C) Target directories and files MacBuildDirQAT = parameters['build'] + ".macQAT" - # (D) Qt5 - cmd_args += " \\\n -qt5" + # (D) Qt5 | Qt6 (Homebrew) + #cmd_args += " \\\n -qt5" # make 'build.sh' detect the Qt type automatically cmd_args += " \\\n -qmake %s" % parameters['qmake'] cmd_args += " \\\n -bin %s" % parameters['bin'] cmd_args += " \\\n -build %s" % parameters['build'] From b84ec19da183f6a7e4a5448a2ea78968f8e233eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6fferlein?= Date: Mon, 23 May 2022 20:37:26 +0200 Subject: [PATCH 4/5] Issue 1071 (GDS2Text format options issues) (#1085) * Fixed first issue (UI problem with GDS2Text options) * Fixed problem with 'save' when the file extension does not indicate one of the known formats In this case, and when plain 'save' is used, the original format is delivered. The session files also store the original format now. The statistics page will now indicate the format of the file that was loaded. --- src/db/db/dbStream.cc | 1 + src/lay/lay/layMainWindow.cc | 10 ++-- src/laybasic/laybasic/layCellView.cc | 8 +++- .../laybasic/layLayoutStatisticsForm.cc | 9 +++- .../laybasic/laySaveLayoutOptionsDialog.cc | 47 +++++++++++++++---- src/laybasic/laybasic/layStream.h | 8 ++++ .../gds2/lay_plugin/layGDS2WriterPlugin.cc | 40 +++++++++++++--- 7 files changed, 103 insertions(+), 20 deletions(-) diff --git a/src/db/db/dbStream.cc b/src/db/db/dbStream.cc index 347e95f63..4b0a0adef 100644 --- a/src/db/db/dbStream.cc +++ b/src/db/db/dbStream.cc @@ -51,6 +51,7 @@ tl::XMLElementList load_options_xml_element_list () tl::XMLElementList save_options_xml_element_list () { tl::XMLElementList elements; + elements.append (tl::make_member (&db::SaveLayoutOptions::format, &db::SaveLayoutOptions::set_format, "format")); for (tl::Registrar::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) { const StreamFormatDeclaration *decl = dynamic_cast (&*cls); diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index f6dc15a82..77455f3b2 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -2298,12 +2298,14 @@ MainWindow::do_save (bool as) db::SaveLayoutOptions options = cv->save_options (); if (!cv->save_options_valid () && cv->technology ()) { options = cv->technology ()->save_layout_options (); + options.set_format (cv->save_options ().format ()); } options.set_dbu (cv->layout ().dbu ()); - options.set_format_from_filename (fn); - cv->update_save_options (options); + if (as || options.format ().empty ()) { + options.set_format_from_filename (fn); + } tl::OutputStream::OutputStreamMode om = tl::OutputStream::OM_Auto; @@ -2340,7 +2342,9 @@ MainWindow::cm_save_all () db::SaveLayoutOptions options (cv->save_options ()); options.set_dbu (cv->layout ().dbu ()); - options.set_format_from_filename (fn); + if (options.format ().empty ()) { + options.set_format_from_filename (fn); + } tl::OutputStream::OutputStreamMode om = tl::OutputStream::OM_Auto; diff --git a/src/laybasic/laybasic/layCellView.cc b/src/laybasic/laybasic/layCellView.cc index 476b6867e..08f187383 100644 --- a/src/laybasic/laybasic/layCellView.cc +++ b/src/laybasic/laybasic/layCellView.cc @@ -277,7 +277,7 @@ LayoutHandle::update_save_options (db::SaveLayoutOptions &options) for (tl::Registrar::iterator cls = tl::Registrar::begin (); cls != tl::Registrar::end (); ++cls) { const lay::StreamWriterPluginDeclaration *decl = dynamic_cast (&*cls); - if (! decl) { + if (! decl || decl->options_alias ()) { continue; } @@ -350,6 +350,8 @@ db::LayerMap LayoutHandle::load (const db::LoadLayoutOptions &options, const std::string &technology) { m_load_options = options; + m_save_options = db::SaveLayoutOptions (); + m_save_options_valid = false; set_tech_name (technology); @@ -369,6 +371,7 @@ LayoutHandle::load (const db::LoadLayoutOptions &options, const std::string &tec file_watcher ().remove_file (filename ()); file_watcher ().add_file (filename ()); + m_save_options.set_format (reader.format ()); m_dirty = false; return new_lmap; } @@ -377,6 +380,8 @@ db::LayerMap LayoutHandle::load () { m_load_options = db::LoadLayoutOptions (); + m_save_options = db::SaveLayoutOptions (); + m_save_options_valid = false; set_tech_name (std::string ()); @@ -394,6 +399,7 @@ LayoutHandle::load () file_watcher ().remove_file (filename ()); file_watcher ().add_file (filename ()); + m_save_options.set_format (reader.format ()); m_dirty = false; return new_lmap; } diff --git a/src/laybasic/laybasic/layLayoutStatisticsForm.cc b/src/laybasic/laybasic/layLayoutStatisticsForm.cc index e671fa0e5..a2e9db0b9 100644 --- a/src/laybasic/laybasic/layLayoutStatisticsForm.cc +++ b/src/laybasic/laybasic/layLayoutStatisticsForm.cc @@ -682,8 +682,13 @@ StatisticsSource::get (const std::string &url) << "" << std::endl << "" << "" - << "" << std::endl - << "" + << "" << std::endl; + if (! m_h->save_options ().format ().empty ()) { + os << "" + << "" + << "" << std::endl; + } + os << "" << "" << "" << std::endl << "" diff --git a/src/laybasic/laybasic/laySaveLayoutOptionsDialog.cc b/src/laybasic/laybasic/laySaveLayoutOptionsDialog.cc index c1fc62cb4..675373333 100644 --- a/src/laybasic/laybasic/laySaveLayoutOptionsDialog.cc +++ b/src/laybasic/laybasic/laySaveLayoutOptionsDialog.cc @@ -338,16 +338,47 @@ SaveLayoutAsOptionsDialog::SaveLayoutAsOptionsDialog (QWidget *parent, const std fmt_cbx->addItem (tl::to_qstring (fmt->format_title ())); - StreamWriterOptionsPage *page = 0; - // obtain the config page from the plugin which we identify by format name const StreamWriterPluginDeclaration *decl = plugin_for_format (fmt->format_name ()); - if (decl) { - page = decl->format_specific_options_page (options_stack); - } - m_pages.push_back (std::make_pair (page, fmt->format_name ())); - m_tab_positions.push_back (page ? options_stack->addWidget (page) : empty_widget_index); + if (decl) { + + const char *alias = decl->options_alias (); + if (alias) { + + // alias needs to come before + int index = -1; + int n = 0; + for (tl::Registrar::iterator i = tl::Registrar::begin (); i != tl::Registrar::end (); ++i) { + if (i->format_name () == alias) { + index = n; + } + ++n; + } + + if (index >= 0 && index < int (m_tab_positions.size ())) { + m_pages.push_back (std::make_pair (m_pages [index].first, fmt->format_name ())); + m_tab_positions.push_back (m_tab_positions[index]); + } else { + m_pages.push_back (std::make_pair ((StreamWriterOptionsPage *) 0, fmt->format_name ())); + m_tab_positions.push_back (empty_widget_index); + } + + } else { + + StreamWriterOptionsPage *page = decl->format_specific_options_page (options_stack); + + m_pages.push_back (std::make_pair (page, fmt->format_name ())); + m_tab_positions.push_back (page ? options_stack->addWidget (page) : empty_widget_index); + + } + + } else { + + m_pages.push_back (std::make_pair ((StreamWriterOptionsPage *) 0, fmt->format_name ())); + m_tab_positions.push_back (empty_widget_index); + + } } @@ -440,7 +471,7 @@ SaveLayoutAsOptionsDialog::get_options (lay::LayoutView *view, unsigned int cv_i for (std::vector< std::pair >::iterator page = m_pages.begin (); page != m_pages.end (); ++page) { const StreamWriterPluginDeclaration *decl = plugin_for_format (page->second); - if (decl) { + if (decl && ! decl->options_alias ()) { std::unique_ptr specific_options; if (options.get_options (page->second)) { diff --git a/src/laybasic/laybasic/layStream.h b/src/laybasic/laybasic/layStream.h index 333e86331..6d3facfd3 100644 --- a/src/laybasic/laybasic/layStream.h +++ b/src/laybasic/laybasic/layStream.h @@ -229,6 +229,14 @@ public: */ static const StreamWriterPluginDeclaration *plugin_for_format (const std::string &format_name); + /** + * @brief If the options are shared with another declaration, returns this name of this declaration here + */ + virtual const char *options_alias () const + { + return 0; + } + /** * @brief Create a format specific options page */ diff --git a/src/plugins/streamers/gds2/lay_plugin/layGDS2WriterPlugin.cc b/src/plugins/streamers/gds2/lay_plugin/layGDS2WriterPlugin.cc index 9a3c03b31..41738a15f 100644 --- a/src/plugins/streamers/gds2/lay_plugin/layGDS2WriterPlugin.cc +++ b/src/plugins/streamers/gds2/lay_plugin/layGDS2WriterPlugin.cc @@ -118,12 +118,14 @@ GDS2WriterOptionPage::multi_xy_clicked () // --------------------------------------------------------------- // GDS2WriterPluginDeclaration definition and implementation -class GDS2WriterPluginDeclaration +namespace { + +class GDS2WriterPluginDeclarationBase : public StreamWriterPluginDeclaration { public: - GDS2WriterPluginDeclaration () - : StreamWriterPluginDeclaration (db::GDS2WriterOptions ().format_name ()) + GDS2WriterPluginDeclarationBase (const std::string &name) + : StreamWriterPluginDeclaration (name) { // .. nothing yet .. } @@ -152,21 +154,47 @@ public: } }; +} + /** - * @brief A dummy plugin for GDS2Text + * @brief A plugin for GDS2 + */ +class GDS2WriterPluginDeclaration + : public GDS2WriterPluginDeclarationBase +{ +public: + GDS2WriterPluginDeclaration () + : GDS2WriterPluginDeclarationBase (db::GDS2WriterOptions ().format_name ()) + { + // .. nothing yet .. + } +}; + +/** + * @brief A plugin for GDS2Text * * GDS2Text shares the options with GDS2, although some limitations do not exist. * There is not specific option set for GDS2Text. The writer will take the options from GDS2. */ class GDS2TextWriterPluginDeclaration - : public StreamWriterPluginDeclaration + : public GDS2WriterPluginDeclarationBase { public: GDS2TextWriterPluginDeclaration () - : StreamWriterPluginDeclaration ("GDS2Text") + : GDS2WriterPluginDeclarationBase ("GDS2Text") { // .. nothing yet .. } + + virtual const char *options_alias () const + { + return db::GDS2WriterOptions ().format_name ().c_str (); + } + + StreamWriterOptionsPage *format_specific_options_page (QWidget *) const + { + return 0; + } }; static tl::RegisteredClass plugin_decl1 (new lay::GDS2WriterPluginDeclaration (), 10000, "GDS2Writer"); From a03464d441451aa9da15820246e63232463b424e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6fferlein?= Date: Mon, 23 May 2022 20:38:10 +0200 Subject: [PATCH 5/5] Issue 1079 (#1083) * WIP: some convenience (self.param=() for Ruby PCell impl), a bug fix (crash on call of pcell_parameter on wrong cell), update of tests * Implemented solution for #1079 (refresh calls coerce_parameters) * Basic.CIRCLE modified such that coerce_parameters_impl also catches the case of a programmatic change of actual_radius and this function will update radius and the handle accordingly * Modified Basic PCells such that they work with coerce_parameters also if generated programmatically * Added tests --- .../pcell_declaration_helper.lym | 1 + src/db/db/dbLayout.cc | 6 +- src/db/db/dbLibrary.cc | 16 +- src/db/db/dbPCellVariant.cc | 24 +- src/db/db/dbPCellVariant.h | 7 +- src/lib/lib/libBasicArc.cc | 132 +-- src/lib/lib/libBasicCircle.cc | 31 +- src/lib/lib/libBasicDonut.cc | 50 +- src/lib/lib/libBasicEllipse.cc | 52 +- src/lib/lib/libBasicPie.cc | 113 +-- src/lib/unit_tests/libBasicTests.cc | 763 +++++++++++++++++- testdata/gds/basic_instances.gds | Bin 0 -> 10170 bytes testdata/gds/basic_instances_au.gds | Bin 0 -> 10410 bytes testdata/ruby/dbPCells.rb | 539 ++++++------- 14 files changed, 1262 insertions(+), 472 deletions(-) create mode 100644 testdata/gds/basic_instances.gds create mode 100644 testdata/gds/basic_instances_au.gds diff --git a/src/db/db/built-in-macros/pcell_declaration_helper.lym b/src/db/db/built-in-macros/pcell_declaration_helper.lym index 8689a942c..115f3fdee 100644 --- a/src/db/db/built-in-macros/pcell_declaration_helper.lym +++ b/src/db/db/built-in-macros/pcell_declaration_helper.lym @@ -272,6 +272,7 @@ module RBA param_index = @param_decls.length self.instance_eval("def #{name.to_s}; @param_values[#{param_index}]; end") self.instance_eval("def set_#{name.to_s}(v); @param_values[#{param_index}] = v; end") + self.instance_eval("def #{name.to_s}=(v); @param_values[#{param_index}] = v; end") if type == TypeLayer self.instance_eval("def #{name.to_s}_layer; @layers[#{@layer_param_index.length}]; end") @layer_param_index.push(param_index) diff --git a/src/db/db/dbLayout.cc b/src/db/db/dbLayout.cc index 4c629a94d..e5b300d51 100644 --- a/src/db/db/dbLayout.cc +++ b/src/db/db/dbLayout.cc @@ -2423,8 +2423,7 @@ Layout::get_pcell_parameter (cell_index_type cell_index, const std::string &name if (pcell_variant) { return pcell_variant->parameter_by_name (name); } else { - static std::map empty; - return empty; + return tl::Variant (); } } @@ -2444,8 +2443,7 @@ Layout::get_named_pcell_parameters (cell_index_type cell_index) const if (pcell_variant) { return pcell_variant->parameters_by_name (); } else { - static std::map empty; - return empty; + return std::map (); } } diff --git a/src/db/db/dbLibrary.cc b/src/db/db/dbLibrary.cc index 4fa34f794..9ea099487 100644 --- a/src/db/db/dbLibrary.cc +++ b/src/db/db/dbLibrary.cc @@ -222,9 +222,19 @@ Library::remap_to (db::Library *other) } else { - // map pcell parameters by name - std::map param_by_name = lib_pcell->parameters_by_name (); - lp->first->remap (other->get_id (), other->layout ().get_pcell_variant (pn.second, new_pcell_decl->map_parameters (param_by_name))); + db::pcell_parameters_type new_parameters = new_pcell_decl->map_parameters (lib_pcell->parameters_by_name ()); + + // coerce the new parameters if requested + try { + db::pcell_parameters_type plist = new_parameters; + new_pcell_decl->coerce_parameters (other->layout (), plist); + plist.swap (new_parameters); + } catch (tl::Exception &ex) { + // ignore exception - we will do that again on update() to establish an error message + tl::error << ex.msg (); + } + + lp->first->remap (other->get_id (), other->layout ().get_pcell_variant (pn.second, new_parameters)); } diff --git a/src/db/db/dbPCellVariant.cc b/src/db/db/dbPCellVariant.cc index 3f8f7bdee..b8a5454ff 100644 --- a/src/db/db/dbPCellVariant.cc +++ b/src/db/db/dbPCellVariant.cc @@ -122,13 +122,19 @@ PCellVariant::parameter_by_name (const std::string &name) const std::map PCellVariant::parameters_by_name () const +{ + return parameters_by_name_from_list (parameters ()); +} + +std::map +PCellVariant::parameters_by_name_from_list (const db::pcell_parameters_type &list) const { std::map param_by_name; const PCellHeader *header = pcell_header (); if (header && header->declaration ()) { - db::pcell_parameters_type::const_iterator pp = parameters ().begin (); + db::pcell_parameters_type::const_iterator pp = list.begin (); const std::vector &pcp = header->declaration ()->parameter_declarations (); for (std::vector::const_iterator pd = pcp.begin (); pd != pcp.end () && pp != parameters ().end (); ++pd, ++pp) { param_by_name.insert (std::make_pair (pd->get_name (), *pp)); @@ -155,13 +161,25 @@ PCellVariant::update (ImportLayerMapping *layer_mapping) std::vector layer_ids; try { + layer_ids = header->get_layer_indices (*layout (), m_parameters, layer_mapping); - header->declaration ()->produce (*layout (), layer_ids, m_parameters, *this); - m_display_name = header->declaration ()->get_display_name (m_parameters); + + // call coerce prior to produce to make sure we have a validated parameter set + // (note that we cannot persist parameters from here) + db::pcell_parameters_type plist = m_parameters; + header->declaration ()->coerce_parameters (*layout (), plist); + + header->declaration ()->produce (*layout (), layer_ids, plist, *this); + + m_display_name = header->declaration ()->get_display_name (plist); + } catch (tl::Exception &ex) { + tl::error << ex.msg (); + // put error messages into layout as text objects on error layer shapes (layout ()->error_layer ()).insert (db::Text (ex.msg (), db::Trans ())); + } // produce the shape parameters on the guiding shape layer so they can be edited diff --git a/src/db/db/dbPCellVariant.h b/src/db/db/dbPCellVariant.h index d2f6de959..ae76c23f9 100644 --- a/src/db/db/dbPCellVariant.h +++ b/src/db/db/dbPCellVariant.h @@ -62,7 +62,12 @@ public: virtual Cell *clone (Layout &layout) const; /** - * @brief Get the parameter name map for this variant + * @brief Gets the parameter name map for a parameter list + */ + std::map parameters_by_name_from_list (const pcell_parameters_type &list) const; + + /** + * @brief Gets the parameter name map for this variant */ std::map parameters_by_name () const; diff --git a/src/lib/lib/libBasicArc.cc b/src/lib/lib/libBasicArc.cc index 732a71c70..d10f1c1b0 100644 --- a/src/lib/lib/libBasicArc.cc +++ b/src/lib/lib/libBasicArc.cc @@ -72,40 +72,40 @@ BasicArc::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parameters return; } - double ru1 = parameters [p_actual_radius1].to_double (); - double r1 = parameters [p_radius1].to_double (); + double ru1 = parameters [p_radius1].to_double (); + double r1 = parameters [p_actual_radius1].to_double (); double rs1 = ru1; - if (parameters [p_handle1].is_user ()) { - rs1 = parameters [p_handle1].to_user ().distance (); + if (parameters [p_actual_handle1].is_user ()) { + rs1 = parameters [p_actual_handle1].to_user ().distance (); } - double ru2 = parameters [p_actual_radius2].to_double (); - double r2 = parameters [p_radius2].to_double (); + double ru2 = parameters [p_radius2].to_double (); + double r2 = parameters [p_actual_radius2].to_double (); double rs2 = ru2; - if (parameters [p_handle2].is_user ()) { - rs2 = parameters [p_handle2].to_user ().distance (); + if (parameters [p_actual_handle2].is_user ()) { + rs2 = parameters [p_actual_handle2].to_user ().distance (); } - double a1u = parameters [p_actual_start_angle].to_double (); - double a1 = parameters [p_start_angle].to_double (); + double a1u = parameters [p_start_angle].to_double (); + double a1 = parameters [p_actual_start_angle].to_double (); db::DPoint h1u; - if (parameters [p_actual_handle1].is_user ()) { - h1u = parameters [p_actual_handle1].to_user (); + if (parameters [p_handle1].is_user ()) { + h1u = parameters [p_handle1].to_user (); } db::DPoint h1; - if (parameters [p_handle1].is_user ()) { - h1 = parameters [p_handle1].to_user (); + if (parameters [p_actual_handle1].is_user ()) { + h1 = parameters [p_actual_handle1].to_user (); } - double a2u = parameters [p_actual_end_angle].to_double (); - double a2 = parameters [p_end_angle].to_double (); + double a2u = parameters [p_end_angle].to_double (); + double a2 = parameters [p_actual_end_angle].to_double (); db::DPoint h2u; - if (parameters [p_actual_handle2].is_user ()) { - h2u = parameters [p_actual_handle2].to_user (); + if (parameters [p_handle2].is_user ()) { + h2u = parameters [p_handle2].to_user (); } db::DPoint h2; - if (parameters [p_handle2].is_user ()) { - h2 = parameters [p_handle2].to_user (); + if (parameters [p_actual_handle2].is_user ()) { + h2 = parameters [p_actual_handle2].to_user (); } if (fabs (ru1 - r1) > 1e-6 || fabs (ru2 - r2) > 1e-6 || fabs (a1u - a1) > 1e-6 || fabs (a2u - a2) > 1e-6) { @@ -118,8 +118,8 @@ BasicArc::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parameters h1u = db::DPoint (r1 * cos (a1 / 180.0 * M_PI), r1 * sin (a1 / 180.0 * M_PI)); h2u = db::DPoint (r2 * cos (a2 / 180.0 * M_PI), r2 * sin (a2 / 180.0 * M_PI)); - parameters [p_handle1] = h1u; - parameters [p_handle2] = h2u; + parameters [p_actual_handle1] = h1u; + parameters [p_actual_handle2] = h2u; } else if (h1u.distance (h1) > 1e-6 || h2u.distance (h2) > 1e-6) { @@ -135,20 +135,20 @@ BasicArc::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parameters h1u = h1; h2u = h2; - parameters [p_radius1] = ru1; - parameters [p_radius2] = ru2; - parameters [p_start_angle] = a1u; - parameters [p_end_angle] = a2u; + parameters [p_actual_radius1] = ru1; + parameters [p_actual_radius2] = ru2; + parameters [p_actual_start_angle] = a1u; + parameters [p_actual_end_angle] = a2u; } // set the hidden used radius parameter - parameters [p_actual_radius1] = ru1; - parameters [p_actual_radius2] = ru2; - parameters [p_actual_start_angle] = a1u; - parameters [p_actual_end_angle] = a2u; - parameters [p_actual_handle1] = h1u; - parameters [p_actual_handle2] = h2u; + parameters [p_radius1] = ru1; + parameters [p_radius2] = ru2; + parameters [p_start_angle] = a1u; + parameters [p_end_angle] = a2u; + parameters [p_handle1] = h1u; + parameters [p_handle2] = h2u; } void @@ -158,10 +158,10 @@ BasicArc::produce (const db::Layout &layout, const std::vector &la return; } - double r1 = parameters [p_actual_radius1].to_double () / layout.dbu (); - double r2 = parameters [p_actual_radius2].to_double () / layout.dbu (); - double a1 = parameters [p_actual_start_angle].to_double (); - double a2 = parameters [p_actual_end_angle].to_double (); + double r1 = parameters [p_radius1].to_double () / layout.dbu (); + double r2 = parameters [p_radius2].to_double () / layout.dbu (); + double a1 = parameters [p_start_angle].to_double (); + double a2 = parameters [p_end_angle].to_double (); if (a2 < a1 - 1e-6) { a2 += 360 * ceil ((a1 - a2) / 360.0 + 1e-6); } @@ -205,8 +205,8 @@ std::string BasicArc::get_display_name (const db::pcell_parameters_type ¶meters) const { return "ARC(l=" + std::string (parameters [p_layer].to_string ()) + - ",r=" + tl::to_string (parameters [p_actual_radius1].to_double ()) + - ".." + tl::to_string (parameters [p_actual_radius2].to_double ()) + + ",r=" + tl::to_string (parameters [p_radius1].to_double ()) + + ".." + tl::to_string (parameters [p_radius2].to_double ()) + ",a=" + tl::to_string (parameters [p_start_angle].to_double (), 6) + ".." + tl::to_string (parameters [p_end_angle].to_double (), 6) + ",n=" + tl::to_string (parameters [p_npoints].to_int ()) + @@ -224,51 +224,49 @@ BasicArc::get_parameter_declarations () const parameters.back ().set_type (db::PCellParameterDeclaration::t_layer); parameters.back ().set_description (tl::to_string (tr ("Layer"))); - // parameter #1: radius + // parameter #1: radius + // This is a shadow parameter to receive the used radius1 tl_assert (parameters.size () == p_radius1); parameters.push_back (db::PCellParameterDeclaration ("radius1")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_description (tl::to_string (tr ("Radius 1"))); - parameters.back ().set_default (0.1); - parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_hidden (true); // parameter #2: radius + // This is a shadow parameter to receive the used radius2 tl_assert (parameters.size () == p_radius2); parameters.push_back (db::PCellParameterDeclaration ("radius2")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_description (tl::to_string (tr ("Radius 2"))); - parameters.back ().set_default (0.2); - parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_hidden (true); // parameter #3: start angle + // This is a shadow parameter to receive the used start angle tl_assert (parameters.size () == p_start_angle); parameters.push_back (db::PCellParameterDeclaration ("a1")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_description (tl::to_string (tr ("Start angle"))); - parameters.back ().set_default (0); - parameters.back ().set_unit (tl::to_string (tr ("degree"))); + parameters.back ().set_hidden (true); // parameter #4: end angle + // This is a shadow parameter to receive the used end angle tl_assert (parameters.size () == p_end_angle); parameters.push_back (db::PCellParameterDeclaration ("a2")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_description (tl::to_string (tr ("End angle"))); - parameters.back ().set_default (90); - parameters.back ().set_unit (tl::to_string (tr ("degree"))); + parameters.back ().set_hidden (true); // parameter #5: handle 1 + // This is a shadow parameter to keep the current handle position and to determine + // whether the handle changed tl_assert (parameters.size () == p_handle1); parameters.push_back (db::PCellParameterDeclaration ("handle1")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_default (db::DPoint (0.1, 0)); - parameters.back ().set_description (tl::to_string (tr ("S"))); + parameters.back ().set_hidden (true); // parameter #6: handle 1 + // This is a shadow parameter to keep the current handle position and to determine + // whether the handle changed tl_assert (parameters.size () == p_handle2); parameters.push_back (db::PCellParameterDeclaration ("handle2")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_default (db::DPoint (0, 0.1)); - parameters.back ().set_description (tl::to_string (tr ("E"))); + parameters.back ().set_hidden (true); // parameter #7: number of points tl_assert (parameters.size () == p_npoints); @@ -281,41 +279,47 @@ BasicArc::get_parameter_declarations () const tl_assert (parameters.size () == p_actual_radius1); parameters.push_back (db::PCellParameterDeclaration ("actual_radius1")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_default (0.0); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("Radius 1"))); + parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_default (0.5); // parameter #9: used radius 2 tl_assert (parameters.size () == p_actual_radius2); parameters.push_back (db::PCellParameterDeclaration ("actual_radius2")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_default (0.0); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("Radius 2"))); + parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_default (1.0); // parameter #10: used start angle tl_assert (parameters.size () == p_actual_start_angle); parameters.push_back (db::PCellParameterDeclaration ("actual_start_angle")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); + parameters.back ().set_description (tl::to_string (tr ("Start angle"))); + parameters.back ().set_unit (tl::to_string (tr ("degree"))); parameters.back ().set_default (0.0); - parameters.back ().set_hidden (true); // parameter #11: used end angle tl_assert (parameters.size () == p_actual_end_angle); parameters.push_back (db::PCellParameterDeclaration ("actual_end_angle")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_default (0.0); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("End angle"))); + parameters.back ().set_unit (tl::to_string (tr ("degree"))); + parameters.back ().set_default (90.0); // parameter #12: used handle 1 tl_assert (parameters.size () == p_actual_handle1); parameters.push_back (db::PCellParameterDeclaration ("actual_handle1")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("S"))); + parameters.back ().set_default (db::DPoint (0.5, 0.0)); // parameter #13: used handle 2 tl_assert (parameters.size () == p_actual_handle2); parameters.push_back (db::PCellParameterDeclaration ("actual_handle2")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("E"))); + parameters.back ().set_default (db::DPoint (0.0, 1.0)); tl_assert (parameters.size () == p_total); return parameters; diff --git a/src/lib/lib/libBasicCircle.cc b/src/lib/lib/libBasicCircle.cc index 9de697b71..6054f5dd3 100644 --- a/src/lib/lib/libBasicCircle.cc +++ b/src/lib/lib/libBasicCircle.cc @@ -64,7 +64,7 @@ BasicCircle::parameters_from_shape (const db::Layout &layout, const db::Shape &s // use map_parameters to create defaults for the other parameters std::map nm; nm.insert (std::make_pair (p_layer, tl::Variant (layout.get_properties (layer)))); - nm.insert (std::make_pair (p_radius, tl::Variant (0.5 * std::min (dbox.width (), dbox.height ())))); + nm.insert (std::make_pair (p_actual_radius, tl::Variant (0.5 * std::min (dbox.width (), dbox.height ())))); return map_parameters (nm); } @@ -88,8 +88,8 @@ BasicCircle::coerce_parameters (const db::Layout & /*layout*/, db::pcell_paramet return; } - double ru = parameters [p_actual_radius].to_double (); - double r = parameters [p_radius].to_double (); + double ru = parameters [p_radius].to_double (); + double r = parameters [p_actual_radius].to_double (); double rs = ru; if (parameters [p_handle].is_user ()) { @@ -104,11 +104,11 @@ BasicCircle::coerce_parameters (const db::Layout & /*layout*/, db::pcell_paramet // the handle has changed: use this ru = rs; r = rs; - parameters [p_radius] = r; + parameters [p_actual_radius] = r; } // set the hidden used radius parameter - parameters [p_actual_radius] = ru; + parameters [p_radius] = ru; } void @@ -118,7 +118,7 @@ BasicCircle::produce (const db::Layout &layout, const std::vector return; } - double r = parameters [p_actual_radius].to_double () / layout.dbu (); + double r = parameters [p_radius].to_double () / layout.dbu (); int n = std::max (3, parameters [p_npoints].to_int ()); std::vector points; @@ -143,7 +143,7 @@ std::string BasicCircle::get_display_name (const db::pcell_parameters_type ¶meters) const { return "CIRCLE(l=" + std::string (parameters [p_layer].to_string ()) + - ",r=" + tl::to_string (parameters [p_actual_radius].to_double ()) + + ",r=" + tl::to_string (parameters [p_radius].to_double ()) + ",n=" + tl::to_string (parameters [p_npoints].to_int ()) + ")"; } @@ -159,19 +159,19 @@ BasicCircle::get_parameter_declarations () const parameters.back ().set_type (db::PCellParameterDeclaration::t_layer); parameters.back ().set_description (tl::to_string (tr ("Layer"))); - // parameter #1: radius + // parameter #1: radius (shadow, hidden) + // This parameter is updated by "coerce_parameters" from "actual_radius" or "handle", + // whichever changed. tl_assert (parameters.size () == p_radius); parameters.push_back (db::PCellParameterDeclaration ("radius")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_description (tl::to_string (tr ("Radius"))); - parameters.back ().set_default (0.1); - parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_hidden (true); // parameter #2: handle tl_assert (parameters.size () == p_handle); parameters.push_back (db::PCellParameterDeclaration ("handle")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_default (db::DPoint (-0.1, 0)); + parameters.back ().set_default (db::DPoint (-1.0, 0)); parameters.back ().set_description (tl::to_string (tr ("R"))); // parameter #3: number of points @@ -181,12 +181,13 @@ BasicCircle::get_parameter_declarations () const parameters.back ().set_description (tl::to_string (tr ("Number of points"))); parameters.back ().set_default (64); - // parameter #4: used radius + // parameter #4: radius (entry field) tl_assert (parameters.size () == p_actual_radius); parameters.push_back (db::PCellParameterDeclaration ("actual_radius")); + parameters.back ().set_description (tl::to_string (tr ("Radius"))); + parameters.back ().set_unit (tl::to_string (tr ("micron"))); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_default (0.0); - parameters.back ().set_hidden (true); + parameters.back ().set_default (1.0); return parameters; } diff --git a/src/lib/lib/libBasicDonut.cc b/src/lib/lib/libBasicDonut.cc index 385425b85..2594fa52e 100644 --- a/src/lib/lib/libBasicDonut.cc +++ b/src/lib/lib/libBasicDonut.cc @@ -67,8 +67,8 @@ BasicDonut::parameters_from_shape (const db::Layout &layout, const db::Shape &sh // use map_parameters to create defaults for the other parameters std::map nm; nm.insert (std::make_pair (p_layer, tl::Variant (layout.get_properties (layer)))); - nm.insert (std::make_pair (p_radius1, tl::Variant (0.5 * std::min (dbox.width (), dbox.height ())))); - nm.insert (std::make_pair (p_radius2, tl::Variant (0.25 * std::min (dbox.width (), dbox.height ())))); + nm.insert (std::make_pair (p_actual_radius1, tl::Variant (0.5 * std::min (dbox.width (), dbox.height ())))); + nm.insert (std::make_pair (p_actual_radius2, tl::Variant (0.25 * std::min (dbox.width (), dbox.height ())))); return map_parameters (nm); } @@ -92,15 +92,15 @@ BasicDonut::coerce_parameters (const db::Layout & /*layout*/, db::pcell_paramete return; } - double ru1 = parameters [p_actual_radius1].to_double (); - double r1 = parameters [p_radius1].to_double (); + double ru1 = parameters [p_radius1].to_double (); + double r1 = parameters [p_actual_radius1].to_double (); double rs1 = ru1; if (parameters [p_handle1].is_user ()) { rs1 = parameters [p_handle1].to_user ().distance (); } - double ru2 = parameters [p_actual_radius2].to_double (); - double r2 = parameters [p_radius2].to_double (); + double ru2 = parameters [p_radius2].to_double (); + double r2 = parameters [p_actual_radius2].to_double (); double rs2 = ru2; if (parameters [p_handle2].is_user ()) { rs2 = parameters [p_handle2].to_user ().distance (); @@ -118,13 +118,13 @@ BasicDonut::coerce_parameters (const db::Layout & /*layout*/, db::pcell_paramete r1 = rs1; ru2 = rs2; r2 = rs2; - parameters [p_radius1] = r1; - parameters [p_radius2] = r2; + parameters [p_actual_radius1] = r1; + parameters [p_actual_radius2] = r2; } // set the hidden used radius parameter - parameters [p_actual_radius1] = ru1; - parameters [p_actual_radius2] = ru2; + parameters [p_radius1] = ru1; + parameters [p_radius2] = ru2; } void @@ -134,8 +134,8 @@ BasicDonut::produce (const db::Layout &layout, const std::vector & return; } - double r1 = parameters [p_actual_radius1].to_double () / layout.dbu (); - double r2 = parameters [p_actual_radius2].to_double () / layout.dbu (); + double r1 = parameters [p_radius1].to_double () / layout.dbu (); + double r2 = parameters [p_radius2].to_double () / layout.dbu (); int n = std::max (3, parameters [p_npoints].to_int ()); std::vector points; @@ -170,8 +170,8 @@ std::string BasicDonut::get_display_name (const db::pcell_parameters_type ¶meters) const { return "DONUT(l=" + std::string (parameters [p_layer].to_string ()) + - ",r=" + tl::to_string (parameters [p_actual_radius1].to_double ()) + - ".." + tl::to_string (parameters [p_actual_radius2].to_double ()) + + ",r=" + tl::to_string (parameters [p_radius1].to_double ()) + + ".." + tl::to_string (parameters [p_radius2].to_double ()) + ",n=" + tl::to_string (parameters [p_npoints].to_int ()) + ")"; } @@ -188,33 +188,29 @@ BasicDonut::get_parameter_declarations () const parameters.back ().set_description (tl::to_string (tr ("Layer"))); // parameter #1: radius1 + // This is a shadow parameter to receive the used first radius tl_assert (parameters.size () == p_radius1); parameters.push_back (db::PCellParameterDeclaration ("radius1")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_description (tl::to_string (tr ("Radius 1"))); - parameters.back ().set_default (0.1); - parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_hidden (true); // parameter #2: radius2 + // This is a shadow parameter to receive the used second radius tl_assert (parameters.size () == p_radius2); parameters.push_back (db::PCellParameterDeclaration ("radius2")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_description (tl::to_string (tr ("Radius 2"))); - parameters.back ().set_default (0.2); - parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_hidden (true); // parameter #3: handle 1 tl_assert (parameters.size () == p_handle1); parameters.push_back (db::PCellParameterDeclaration ("handle1")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_default (db::DPoint (-0.1, 0)); parameters.back ().set_description (tl::to_string (tr ("R1"))); // parameter #4: handle 2 tl_assert (parameters.size () == p_handle2); parameters.push_back (db::PCellParameterDeclaration ("handle2")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_default (db::DPoint (-0.2, 0)); parameters.back ().set_description (tl::to_string (tr ("R2"))); // parameter #5: number of points @@ -228,15 +224,17 @@ BasicDonut::get_parameter_declarations () const tl_assert (parameters.size () == p_actual_radius1); parameters.push_back (db::PCellParameterDeclaration ("actual_radius1")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_default (0.0); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("Radius 1"))); + parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_default (0.5); // parameter #7: used radius 2 tl_assert (parameters.size () == p_actual_radius2); parameters.push_back (db::PCellParameterDeclaration ("actual_radius2")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_default (0.0); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("Radius 2"))); + parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_default (1.0); return parameters; } diff --git a/src/lib/lib/libBasicEllipse.cc b/src/lib/lib/libBasicEllipse.cc index e6faa3004..2484ffda9 100644 --- a/src/lib/lib/libBasicEllipse.cc +++ b/src/lib/lib/libBasicEllipse.cc @@ -67,8 +67,8 @@ BasicEllipse::parameters_from_shape (const db::Layout &layout, const db::Shape & // use map_parameters to create defaults for the other parameters std::map nm; nm.insert (std::make_pair (p_layer, tl::Variant (layout.get_properties (layer)))); - nm.insert (std::make_pair (p_radius_x, tl::Variant (0.5 * dbox.width ()))); - nm.insert (std::make_pair (p_radius_y, tl::Variant (0.5 * dbox.height ()))); + nm.insert (std::make_pair (p_actual_radius_x, tl::Variant (0.5 * dbox.width ()))); + nm.insert (std::make_pair (p_actual_radius_y, tl::Variant (0.5 * dbox.height ()))); return map_parameters (nm); } @@ -92,8 +92,8 @@ BasicEllipse::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parame return; } - double ru_x = parameters [p_actual_radius_x].to_double (); - double r_x = parameters [p_radius_x].to_double (); + double ru_x = parameters [p_radius_x].to_double (); + double r_x = parameters [p_actual_radius_x].to_double (); double rs_x = ru_x; if (parameters [p_handle_x].is_user ()) { @@ -108,16 +108,16 @@ BasicEllipse::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parame // the handle has changed: use this ru_x = rs_x; r_x = rs_x; - parameters [p_radius_x] = r_x; + parameters [p_actual_radius_x] = r_x; parameters [p_handle_x] = db::DPoint (-r_x, 0); } // set the hidden used radius parameter - parameters [p_actual_radius_x] = ru_x; + parameters [p_radius_x] = ru_x; // do the same for the y radius - double ru_y = parameters [p_actual_radius_y].to_double (); - double r_y = parameters [p_radius_y].to_double (); + double ru_y = parameters [p_radius_y].to_double (); + double r_y = parameters [p_actual_radius_y].to_double (); double rs_y = ru_y; if (parameters [p_handle_y].is_user ()) { @@ -132,12 +132,12 @@ BasicEllipse::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parame // the handle has changed: use this ru_y = rs_y; r_y = rs_y; - parameters [p_radius_y] = r_y; + parameters [p_actual_radius_y] = r_y; parameters [p_handle_y] = db::DPoint (0, r_y); } // set the hidden used radius parameter - parameters [p_actual_radius_y] = ru_y; + parameters [p_radius_y] = ru_y; } void @@ -147,8 +147,8 @@ BasicEllipse::produce (const db::Layout &layout, const std::vector return; } - double r_x = parameters [p_actual_radius_x].to_double () / layout.dbu (); - double r_y = parameters [p_actual_radius_y].to_double () / layout.dbu (); + double r_x = parameters [p_radius_x].to_double () / layout.dbu (); + double r_y = parameters [p_radius_y].to_double () / layout.dbu (); int n = std::max (3, parameters [p_npoints].to_int ()); std::vector points; @@ -174,8 +174,8 @@ std::string BasicEllipse::get_display_name (const db::pcell_parameters_type ¶meters) const { return "ELLIPSE(l=" + std::string (parameters [p_layer].to_string ()) + - ",rx=" + tl::to_string (parameters [p_actual_radius_x].to_double ()) + - ",ry=" + tl::to_string (parameters [p_actual_radius_y].to_double ()) + + ",rx=" + tl::to_string (parameters [p_radius_x].to_double ()) + + ",ry=" + tl::to_string (parameters [p_radius_y].to_double ()) + ",n=" + tl::to_string (parameters [p_npoints].to_int ()) + ")"; } @@ -195,30 +195,28 @@ BasicEllipse::get_parameter_declarations () const tl_assert (parameters.size () == p_radius_x); parameters.push_back (db::PCellParameterDeclaration ("radius_x")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_description (tl::to_string (tr ("Radius (x)"))); - parameters.back ().set_default (0.1); - parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_hidden (true); // parameter #2: y radius + // This is a shadow parameter to receive the used y radius tl_assert (parameters.size () == p_radius_y); parameters.push_back (db::PCellParameterDeclaration ("radius_y")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_description (tl::to_string (tr ("Radius (y)"))); - parameters.back ().set_default (0.1); - parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_hidden (true); // parameter #3: x handle + // This is a shadow parameter to receive the used x radius tl_assert (parameters.size () == p_handle_x); parameters.push_back (db::PCellParameterDeclaration ("handle_x")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_default (db::DPoint (-0.2, 0)); + parameters.back ().set_default (db::DPoint (-1.0, 0)); parameters.back ().set_description (tl::to_string (tr ("Rx"))); // parameter #4: x handle tl_assert (parameters.size () == p_handle_y); parameters.push_back (db::PCellParameterDeclaration ("handle_y")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_default (db::DPoint (-0.1, 0)); + parameters.back ().set_default (db::DPoint (0, 0.5)); parameters.back ().set_description (tl::to_string (tr ("Ry"))); // parameter #5: number of points @@ -232,15 +230,17 @@ BasicEllipse::get_parameter_declarations () const tl_assert (parameters.size () == p_actual_radius_x); parameters.push_back (db::PCellParameterDeclaration ("actual_radius_x")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_default (0.0); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("Radius (x)"))); + parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_default (1.0); // parameter #6: used y radius tl_assert (parameters.size () == p_actual_radius_y); parameters.push_back (db::PCellParameterDeclaration ("actual_radius_y")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_default (0.0); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("Radius (y)"))); + parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_default (0.5); return parameters; } diff --git a/src/lib/lib/libBasicPie.cc b/src/lib/lib/libBasicPie.cc index 14b51bb91..d57a780be 100644 --- a/src/lib/lib/libBasicPie.cc +++ b/src/lib/lib/libBasicPie.cc @@ -70,38 +70,38 @@ BasicPie::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parameters return; } - double ru = parameters [p_actual_radius].to_double (); - double r = parameters [p_radius].to_double (); + double ru = parameters [p_radius].to_double (); + double r = parameters [p_actual_radius].to_double (); double rs = ru; - if (parameters [p_handle1].is_user ()) { - rs = parameters [p_handle1].to_user ().distance (); - if (parameters [p_handle2].is_user ()) { - rs = std::max (rs, parameters [p_handle2].to_user ().distance ()); + if (parameters [p_actual_handle1].is_user ()) { + rs = parameters [p_actual_handle1].to_user ().distance (); + if (parameters [p_actual_handle2].is_user ()) { + rs = std::max (rs, parameters [p_actual_handle2].to_user ().distance ()); } - } else if (parameters [p_handle2].is_user ()) { - rs = parameters [p_handle2].to_user ().distance (); + } else if (parameters [p_actual_handle2].is_user ()) { + rs = parameters [p_actual_handle2].to_user ().distance (); } - double a1u = parameters [p_actual_start_angle].to_double (); - double a1 = parameters [p_start_angle].to_double (); + double a1u = parameters [p_start_angle].to_double (); + double a1 = parameters [p_actual_start_angle].to_double (); db::DPoint h1u; - if (parameters [p_actual_handle1].is_user ()) { - h1u = parameters [p_actual_handle1].to_user (); + if (parameters [p_handle1].is_user ()) { + h1u = parameters [p_handle1].to_user (); } db::DPoint h1; - if (parameters [p_handle1].is_user ()) { - h1 = parameters [p_handle1].to_user (); + if (parameters [p_actual_handle1].is_user ()) { + h1 = parameters [p_actual_handle1].to_user (); } - double a2u = parameters [p_actual_end_angle].to_double (); - double a2 = parameters [p_end_angle].to_double (); + double a2u = parameters [p_end_angle].to_double (); + double a2 = parameters [p_actual_end_angle].to_double (); db::DPoint h2u; - if (parameters [p_actual_handle2].is_user ()) { - h2u = parameters [p_actual_handle2].to_user (); + if (parameters [p_handle2].is_user ()) { + h2u = parameters [p_handle2].to_user (); } db::DPoint h2; - if (parameters [p_handle2].is_user ()) { - h2 = parameters [p_handle2].to_user (); + if (parameters [p_actual_handle2].is_user ()) { + h2 = parameters [p_actual_handle2].to_user (); } if (fabs (ru - r) > 1e-6 || fabs (a1u - a1) > 1e-6 || fabs (a2u - a2) > 1e-6) { @@ -113,8 +113,8 @@ BasicPie::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parameters h1u = db::DPoint (r * cos (a1 / 180.0 * M_PI), r * sin (a1 / 180.0 * M_PI)); h2u = db::DPoint (r * cos (a2 / 180.0 * M_PI), r * sin (a2 / 180.0 * M_PI)); - parameters [p_handle1] = h1u; - parameters [p_handle2] = h2u; + parameters [p_actual_handle1] = h1u; + parameters [p_actual_handle2] = h2u; } else if (h1u.distance (h1) > 1e-6 || h2u.distance (h2) > 1e-6) { @@ -129,18 +129,18 @@ BasicPie::coerce_parameters (const db::Layout & /*layout*/, db::pcell_parameters h1u = h1; h2u = h2; - parameters [p_radius] = ru; - parameters [p_start_angle] = a1u; - parameters [p_end_angle] = a2u; + parameters [p_actual_radius] = ru; + parameters [p_actual_start_angle] = a1u; + parameters [p_actual_end_angle] = a2u; } // set the hidden used radius parameter - parameters [p_actual_radius] = ru; - parameters [p_actual_start_angle] = a1u; - parameters [p_actual_end_angle] = a2u; - parameters [p_actual_handle1] = h1u; - parameters [p_actual_handle2] = h2u; + parameters [p_radius] = ru; + parameters [p_start_angle] = a1u; + parameters [p_end_angle] = a2u; + parameters [p_handle1] = h1u; + parameters [p_handle2] = h2u; } void @@ -150,9 +150,9 @@ BasicPie::produce (const db::Layout &layout, const std::vector &la return; } - double r = parameters [p_actual_radius].to_double () / layout.dbu (); - double a1 = parameters [p_actual_start_angle].to_double (); - double a2 = parameters [p_actual_end_angle].to_double (); + double r = parameters [p_radius].to_double () / layout.dbu (); + double a1 = parameters [p_start_angle].to_double (); + double a2 = parameters [p_end_angle].to_double (); if (a2 < a1 - 1e-6) { a2 += 360 * ceil ((a1 - a2) / 360.0 + 1e-6); } @@ -187,7 +187,7 @@ std::string BasicPie::get_display_name (const db::pcell_parameters_type ¶meters) const { return "PIE(l=" + std::string (parameters [p_layer].to_string ()) + - ",r=" + tl::to_string (parameters [p_actual_radius].to_double ()) + + ",r=" + tl::to_string (parameters [p_radius].to_double ()) + ",a=" + tl::to_string (parameters [p_start_angle].to_double (), 6) + ".." + tl::to_string (parameters [p_end_angle].to_double (), 6) + ",n=" + tl::to_string (parameters [p_npoints].to_int ()) + @@ -206,42 +206,42 @@ BasicPie::get_parameter_declarations () const parameters.back ().set_description (tl::to_string (tr ("Layer"))); // parameter #1: radius + // This parameter is updated by "coerce_parameters" from "actual_radius" or the handles, + // whichever changed. tl_assert (parameters.size () == p_radius); parameters.push_back (db::PCellParameterDeclaration ("radius")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_description (tl::to_string (tr ("Radius"))); - parameters.back ().set_default (0.1); - parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_hidden (true); // parameter #2: start angle + // This is a shadow parameter to keep the final start angle tl_assert (parameters.size () == p_start_angle); parameters.push_back (db::PCellParameterDeclaration ("a1")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_description (tl::to_string (tr ("Start angle"))); - parameters.back ().set_default (0); - parameters.back ().set_unit (tl::to_string (tr ("degree"))); + parameters.back ().set_hidden (true); // parameter #3: end angle + // This is a shadow parameter to keep the final end angle tl_assert (parameters.size () == p_end_angle); parameters.push_back (db::PCellParameterDeclaration ("a2")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_description (tl::to_string (tr ("End angle"))); - parameters.back ().set_default (90); - parameters.back ().set_unit (tl::to_string (tr ("degree"))); + parameters.back ().set_hidden (true); // parameter #4: handle 1 tl_assert (parameters.size () == p_handle1); + // This is a shadow parameter to keep the current handle position and to determine + // whether the handle changed parameters.push_back (db::PCellParameterDeclaration ("handle1")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_default (db::DPoint (0.1, 0)); - parameters.back ().set_description (tl::to_string (tr ("S"))); + parameters.back ().set_hidden (true); // parameter #5: handle 1 + // This is a shadow parameter to keep the current handle position and to determine + // whether the handle changed tl_assert (parameters.size () == p_handle2); parameters.push_back (db::PCellParameterDeclaration ("handle2")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_default (db::DPoint (0, 0.1)); - parameters.back ().set_description (tl::to_string (tr ("E"))); + parameters.back ().set_hidden (true); // parameter #6: number of points tl_assert (parameters.size () == p_npoints); @@ -254,34 +254,39 @@ BasicPie::get_parameter_declarations () const tl_assert (parameters.size () == p_actual_radius); parameters.push_back (db::PCellParameterDeclaration ("actual_radius")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_default (0.0); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("Radius"))); + parameters.back ().set_unit (tl::to_string (tr ("micron"))); + parameters.back ().set_default (1.0); // parameter #8: used start angle tl_assert (parameters.size () == p_actual_start_angle); parameters.push_back (db::PCellParameterDeclaration ("actual_start_angle")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); + parameters.back ().set_description (tl::to_string (tr ("Start angle"))); + parameters.back ().set_unit (tl::to_string (tr ("degree"))); parameters.back ().set_default (0.0); - parameters.back ().set_hidden (true); // parameter #9: used end angle tl_assert (parameters.size () == p_actual_end_angle); parameters.push_back (db::PCellParameterDeclaration ("actual_end_angle")); parameters.back ().set_type (db::PCellParameterDeclaration::t_double); - parameters.back ().set_default (0.0); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("End angle"))); + parameters.back ().set_unit (tl::to_string (tr ("degree"))); + parameters.back ().set_default (90.0); // parameter #10: used handle 1 tl_assert (parameters.size () == p_actual_handle1); parameters.push_back (db::PCellParameterDeclaration ("actual_handle1")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("S"))); + parameters.back ().set_default (db::DPoint (-1.0, 0.0)); // parameter #11: used handle 2 tl_assert (parameters.size () == p_actual_handle2); parameters.push_back (db::PCellParameterDeclaration ("actual_handle2")); parameters.back ().set_type (db::PCellParameterDeclaration::t_shape); - parameters.back ().set_hidden (true); + parameters.back ().set_description (tl::to_string (tr ("E"))); + parameters.back ().set_default (db::DPoint (0.0, 1.0)); tl_assert (parameters.size () == p_total); return parameters; diff --git a/src/lib/unit_tests/libBasicTests.cc b/src/lib/unit_tests/libBasicTests.cc index 6e3348849..ffda9420d 100644 --- a/src/lib/unit_tests/libBasicTests.cc +++ b/src/lib/unit_tests/libBasicTests.cc @@ -23,11 +23,764 @@ #include "tlUnitTest.h" -TEST(1) -{ - EXPECT_EQ (1, 1); // avoids a compiler warning because of unreferenced _this +#include "dbLibrary.h" +#include "dbLibraryManager.h" +#include "dbReader.h" +#include "dbTestSupport.h" - // TODO: add tests for lib specific things - throw tl::CancelException (); // skip this test to indicate that there is nothing yet +#include "libBasicCircle.h" + +TEST(1_Circle) +{ + const size_t p_layer = 0; + const size_t p_radius = 1; + const size_t p_handle = 2; + const size_t p_npoints = 3; + const size_t p_actual_radius = 4; + const size_t p_total = 5; + + db::Library *lib_basic = db::LibraryManager::instance ().lib_ptr_by_name ("Basic"); + tl_assert (lib_basic); + + db::Layout ly; + + std::pair pc = lib_basic->layout ().pcell_by_name ("CIRCLE"); + tl_assert (pc.first); + + std::map params; + params["layer"] = db::LayerProperties (1, 0); + params["actual_radius"] = 10.0; + + db::cell_index_type lib_cell; + db::Cell *circle; + std::vector plist; + + lib_cell = lib_basic->layout ().get_pcell_variant_dict (pc.second, params); + circle = &ly.cell (ly.get_lib_proxy (lib_basic, lib_cell)); + + // change radius explicitly + + // has radius 10um + EXPECT_EQ (circle->bbox ().to_string (), "(-10000,-10000;10000,10000)"); + EXPECT_EQ (circle->get_display_name (), "Basic.CIRCLE(l=1/0,r=10,n=64)"); + + // only after Library::refresh the parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_radius].to_double (), 0.0); + + lib_basic->refresh (); + EXPECT_EQ (circle->bbox ().to_string (), "(-10000,-10000;10000,10000)"); + EXPECT_EQ (circle->get_display_name (), "Basic.CIRCLE(l=1/0,r=10,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_radius].to_double (), 10.0); + EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_actual_radius].to_double (), 10.0); + + // change radius explicitly + + plist = ly.get_pcell_parameters (circle->cell_index ()); + plist[p_actual_radius] = 9.0; + circle = &ly.cell (ly.get_pcell_variant_cell (circle->cell_index (), plist)); + + // as the radius is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_radius].to_double (), 10.0); + + lib_basic->refresh (); + EXPECT_EQ (circle->bbox ().to_string (), "(-9000,-9000;9000,9000)"); + EXPECT_EQ (circle->get_display_name (), "Basic.CIRCLE(l=1/0,r=9,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_radius].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_actual_radius].to_double (), 9.0); + + // change handle explicitly + + plist = ly.get_pcell_parameters (circle->cell_index ()); + plist[p_handle] = db::DPoint (0.0, 8.0); + circle = &ly.cell (ly.get_pcell_variant_cell (circle->cell_index (), plist)); + + // as the handle is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_actual_radius].to_double (), 9.0); + + lib_basic->refresh (); + EXPECT_EQ (circle->bbox ().to_string (), "(-8000,-8000;8000,8000)"); + EXPECT_EQ (circle->get_display_name (), "Basic.CIRCLE(l=1/0,r=8,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_radius].to_double (), 8.0); + EXPECT_EQ (ly.get_pcell_parameters (circle->cell_index ()) [p_actual_radius].to_double (), 8.0); + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + + db::Shapes shapes; + db::Shape s = shapes.insert (db::Box (1000, 2000, 4000, 5000)); + EXPECT_EQ (lib_basic->layout ().pcell_declaration (pc.second)->can_create_from_shape (ly, s, l1), true); + EXPECT_EQ (lib_basic->layout ().pcell_declaration (pc.second)->transformation_from_shape (ly, s, l1).to_string (), "r0 2500,3500"); + plist = lib_basic->layout ().pcell_declaration (pc.second)->parameters_from_shape (ly, s, l1); + EXPECT_EQ (plist [p_layer].to_string (), "1/0"); + EXPECT_EQ (plist [p_actual_radius].to_string (), "1.5"); } +TEST(2_Pie) +{ + static size_t p_layer = 0; + static size_t p_radius = 1; + static size_t p_start_angle = 2; + static size_t p_end_angle = 3; + static size_t p_handle1 = 4; + static size_t p_handle2 = 5; + static size_t p_npoints = 6; + static size_t p_actual_radius = 7; + static size_t p_actual_start_angle = 8; + static size_t p_actual_end_angle = 9; + static size_t p_actual_handle1 = 10; + static size_t p_actual_handle2 = 11; + static size_t p_total = 12; + + db::Library *lib_basic = db::LibraryManager::instance ().lib_ptr_by_name ("Basic"); + tl_assert (lib_basic); + + db::Layout ly; + + std::pair pc = lib_basic->layout ().pcell_by_name ("PIE"); + tl_assert (pc.first); + + std::map params; + params["layer"] = db::LayerProperties (1, 0); + params["actual_radius"] = 10.0; + params["actual_start_angle"] = -90.0; + params["actual_end_angle"] = 0.0; + + db::cell_index_type lib_cell; + db::Cell *pie; + std::vector plist; + + lib_cell = lib_basic->layout ().get_pcell_variant_dict (pc.second, params); + pie = &ly.cell (ly.get_lib_proxy (lib_basic, lib_cell)); + + // change radius explicitly + + // has radius 10um, but bbox isn't correct for now (because handle was not updated) + EXPECT_EQ (pie->bbox ().to_string (), "(-1000,-10000;10000,1000)"); + EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=10,a=-90..0,n=64)"); + + // only after Library::refresh the parameters get updated and bbox is correct + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 0.0); + + lib_basic->refresh (); + EXPECT_EQ (pie->bbox ().to_string (), "(0,-10000;10000,0)"); + EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=10,a=-90..0,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 10.0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_radius].to_double (), 10.0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_end_angle].to_double (), 0); + + // change radius explicitly + + plist = ly.get_pcell_parameters (pie->cell_index ()); + plist[p_actual_radius] = 9.0; + pie = &ly.cell (ly.get_pcell_variant_cell (pie->cell_index (), plist)); + + // as the radius is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 10.0); + + lib_basic->refresh (); + EXPECT_EQ (pie->bbox ().to_string (), "(0,-9000;9000,0)"); + EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=9,a=-90..0,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle1].to_string (), "0,-9"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle2].to_string (), "9,0"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle1].to_string (), "0,-9"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle2].to_string (), "9,0"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_radius].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_end_angle].to_double (), 0); + + // change end angle explicitly + + plist = ly.get_pcell_parameters (pie->cell_index ()); + plist[p_actual_end_angle] = 90.0; + pie = &ly.cell (ly.get_pcell_variant_cell (pie->cell_index (), plist)); + + // as the end angle is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 0.0); + + lib_basic->refresh (); + EXPECT_EQ (pie->bbox ().to_string (), "(0,-9000;9000,9000)"); + EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=9,a=-90..90,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle1].to_string (), "0,-9"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle2].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle1].to_string (), "0,-9"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle2].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_radius].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 90); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_end_angle].to_double (), 90); + + // change start angle explicitly + + plist = ly.get_pcell_parameters (pie->cell_index ()); + plist[p_actual_start_angle] = 0.0; + pie = &ly.cell (ly.get_pcell_variant_cell (pie->cell_index (), plist)); + + // as the end angle is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), -90.0); + + lib_basic->refresh (); + EXPECT_EQ (pie->bbox ().to_string (), "(0,0;9000,9000)"); + EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=9,a=0..90,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle1].to_string (), "9,0"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle2].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle1].to_string (), "9,0"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle2].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_radius].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_start_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 90); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_end_angle].to_double (), 90); + + // change handle1 explicitly + + plist = ly.get_pcell_parameters (pie->cell_index ()); + plist[p_actual_handle1] = db::DPoint (0.0, -5.0); + pie = &ly.cell (ly.get_pcell_variant_cell (pie->cell_index (), plist)); + + // as the handle is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), 0.0); + + lib_basic->refresh (); + EXPECT_EQ (pie->bbox ().to_string (), "(0,-9000;9000,9000)"); + EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=9,a=-90..90,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle2].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle2].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), -90.0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_start_angle].to_double (), -90.0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 90); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_end_angle].to_double (), 90); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 9); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_radius].to_double (), 9); + + // change handle2 explicitly + + plist = ly.get_pcell_parameters (pie->cell_index ()); + plist[p_actual_handle2] = db::DPoint (5.0, 0.0); + pie = &ly.cell (ly.get_pcell_variant_cell (pie->cell_index (), plist)); + + // as the handle is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 90.0); + + lib_basic->refresh (); + EXPECT_EQ (pie->bbox ().to_string (), "(0,-5000;5000,0)"); + EXPECT_EQ (pie->get_display_name (), "Basic.PIE(l=1/0,r=5,a=-90..0,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_handle2].to_string (), "5,0"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_handle2].to_string (), "5,0"); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_start_angle].to_double (), -90.0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_start_angle].to_double (), -90.0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_end_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_end_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_radius].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (pie->cell_index ()) [p_actual_radius].to_double (), 5); +} + +TEST(3_Arc) +{ + static size_t p_layer = 0; + static size_t p_radius1 = 1; + static size_t p_radius2 = 2; + static size_t p_start_angle = 3; + static size_t p_end_angle = 4; + static size_t p_handle1 = 5; + static size_t p_handle2 = 6; + static size_t p_npoints = 7; + static size_t p_actual_radius1 = 8; + static size_t p_actual_radius2 = 9; + static size_t p_actual_start_angle = 10; + static size_t p_actual_end_angle = 11; + static size_t p_actual_handle1 = 12; + static size_t p_actual_handle2 = 13; + static size_t p_total = 14; + + db::Library *lib_basic = db::LibraryManager::instance ().lib_ptr_by_name ("Basic"); + tl_assert (lib_basic); + + db::Layout ly; + + std::pair pc = lib_basic->layout ().pcell_by_name ("ARC"); + tl_assert (pc.first); + + std::map params; + params["layer"] = db::LayerProperties (1, 0); + params["actual_radius1"] = 4.0; + params["actual_radius2"] = 10.0; + params["actual_start_angle"] = -90.0; + params["actual_end_angle"] = 0.0; + + db::cell_index_type lib_cell; + db::Cell *arc; + std::vector plist; + + lib_cell = lib_basic->layout ().get_pcell_variant_dict (pc.second, params); + arc = &ly.cell (ly.get_lib_proxy (lib_basic, lib_cell)); + + // change radius explicitly + + // has radius 10um, but bbox isn't correct for now (because handle was not updated) + EXPECT_EQ (arc->bbox ().to_string (), "(0,-10000;10000,1000)"); + EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=4..10,a=-90..0,n=64)"); + + // only after Library::refresh the parameters get updated and bbox is correct + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 0.0); + + lib_basic->refresh (); + EXPECT_EQ (arc->bbox ().to_string (), "(0,-10000;10000,0)"); + EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=4..10,a=-90..0,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 4.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 4.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 10.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 10.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 0); + + // change radius2 explicitly + + plist = ly.get_pcell_parameters (arc->cell_index ()); + plist[p_actual_radius2] = 9.0; + arc = &ly.cell (ly.get_pcell_variant_cell (arc->cell_index (), plist)); + + // as the radius is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 10.0); + + lib_basic->refresh (); + EXPECT_EQ (arc->bbox ().to_string (), "(0,-9000;9000,0)"); + EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=4..9,a=-90..0,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle1].to_string (), "0,-4"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle2].to_string (), "9,0"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle1].to_string (), "0,-4"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle2].to_string (), "9,0"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 4.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 4.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 0); + + // change radius1 explicitly + + plist = ly.get_pcell_parameters (arc->cell_index ()); + plist[p_actual_radius1] = 5.0; + arc = &ly.cell (ly.get_pcell_variant_cell (arc->cell_index (), plist)); + + // as the radius is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 4.0); + + lib_basic->refresh (); + EXPECT_EQ (arc->bbox ().to_string (), "(0,-9000;9000,0)"); + EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=5..9,a=-90..0,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle2].to_string (), "9,0"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle2].to_string (), "9,0"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 5.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 5.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 0); + + // change end angle explicitly + + plist = ly.get_pcell_parameters (arc->cell_index ()); + plist[p_actual_end_angle] = 90.0; + arc = &ly.cell (ly.get_pcell_variant_cell (arc->cell_index (), plist)); + + // as the end angle is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 0.0); + + lib_basic->refresh (); + EXPECT_EQ (arc->bbox ().to_string (), "(0,-9000;9000,9000)"); + EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=5..9,a=-90..90,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle2].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle2].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 5.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 5.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), -90); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 90); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 90); + + // change start angle explicitly + + plist = ly.get_pcell_parameters (arc->cell_index ()); + plist[p_actual_start_angle] = 0.0; + arc = &ly.cell (ly.get_pcell_variant_cell (arc->cell_index (), plist)); + + // as the end angle is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90.0); + + lib_basic->refresh (); + EXPECT_EQ (arc->bbox ().to_string (), "(0,0;9000,9000)"); + EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=5..9,a=0..90,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle1].to_string (), "5,0"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle2].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle1].to_string (), "5,0"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle2].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 5.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 5.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 90); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 90); + + // change handle1 explicitly + + plist = ly.get_pcell_parameters (arc->cell_index ()); + plist[p_actual_handle1] = db::DPoint (0.0, -5.0); + arc = &ly.cell (ly.get_pcell_variant_cell (arc->cell_index (), plist)); + + // as the handle is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), 0.0); + + lib_basic->refresh (); + EXPECT_EQ (arc->bbox ().to_string (), "(0,-9000;9000,9000)"); + EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=5..9,a=-90..90,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle2].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle2].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), -90.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 90); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 90); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 9); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 9); + + // change handle2 explicitly + + plist = ly.get_pcell_parameters (arc->cell_index ()); + plist[p_actual_handle2] = db::DPoint (9.0, 0.0); + arc = &ly.cell (ly.get_pcell_variant_cell (arc->cell_index (), plist)); + + // as the handle is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 90.0); + + lib_basic->refresh (); + EXPECT_EQ (arc->bbox ().to_string (), "(0,-9000;9000,0)"); + EXPECT_EQ (arc->get_display_name (), "Basic.ARC(l=1/0,r=5..9,a=-90..0,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_handle2].to_string (), "9,0"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_handle2].to_string (), "9,0"); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_start_angle].to_double (), -90.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_start_angle].to_double (), -90.0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_end_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_end_angle].to_double (), 0); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius1].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius1].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_radius2].to_double (), 9); + EXPECT_EQ (ly.get_pcell_parameters (arc->cell_index ()) [p_actual_radius2].to_double (), 9); +} + +TEST(4_Donut) +{ + static size_t p_layer = 0; + static size_t p_radius1 = 1; + static size_t p_radius2 = 2; + static size_t p_handle1 = 3; + static size_t p_handle2 = 4; + static size_t p_npoints = 5; + static size_t p_actual_radius1 = 6; + static size_t p_actual_radius2 = 7; + static size_t p_total = 8; + + db::Library *lib_basic = db::LibraryManager::instance ().lib_ptr_by_name ("Basic"); + tl_assert (lib_basic); + + db::Layout ly; + + std::pair pc = lib_basic->layout ().pcell_by_name ("DONUT"); + tl_assert (pc.first); + + std::map params; + params["layer"] = db::LayerProperties (1, 0); + params["actual_radius1"] = 4.0; + params["actual_radius2"] = 10.0; + params["actual_start_angle"] = -90.0; + params["actual_end_angle"] = 0.0; + + db::cell_index_type lib_cell; + db::Cell *donut; + std::vector plist; + + lib_cell = lib_basic->layout ().get_pcell_variant_dict (pc.second, params); + donut = &ly.cell (ly.get_lib_proxy (lib_basic, lib_cell)); + + // change radius explicitly + + // has radius 10um, but bbox isn't correct for now (because handle was not updated) + EXPECT_EQ (donut->bbox ().to_string (), "(-10000,-10000;10000,10000)"); + EXPECT_EQ (donut->get_display_name (), "Basic.DONUT(l=1/0,r=4..10,n=64)"); + + // only after Library::refresh the parameters get updated and bbox is correct + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 0.0); + + lib_basic->refresh (); + EXPECT_EQ (donut->bbox ().to_string (), "(-10000,-10000;10000,10000)"); + EXPECT_EQ (donut->get_display_name (), "Basic.DONUT(l=1/0,r=4..10,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 4.0); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius1].to_double (), 4.0); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius2].to_double (), 10.0); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius2].to_double (), 10.0); + + // change radius2 explicitly + + plist = ly.get_pcell_parameters (donut->cell_index ()); + plist[p_actual_radius2] = 9.0; + donut = &ly.cell (ly.get_pcell_variant_cell (donut->cell_index (), plist)); + + // as the radius is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius2].to_double (), 10.0); + + lib_basic->refresh (); + EXPECT_EQ (donut->bbox ().to_string (), "(-9000,-9000;9000,9000)"); + EXPECT_EQ (donut->get_display_name (), "Basic.DONUT(l=1/0,r=4..9,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle1].to_string (), "-4,0"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle2].to_string (), "-9,0"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 4.0); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius1].to_double (), 4.0); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius2].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius2].to_double (), 9.0); + + // change radius1 explicitly + + plist = ly.get_pcell_parameters (donut->cell_index ()); + plist[p_actual_radius1] = 5.0; + donut = &ly.cell (ly.get_pcell_variant_cell (donut->cell_index (), plist)); + + // as the radius is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 4.0); + + lib_basic->refresh (); + EXPECT_EQ (donut->bbox ().to_string (), "(-9000,-9000;9000,9000)"); + EXPECT_EQ (donut->get_display_name (), "Basic.DONUT(l=1/0,r=5..9,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle1].to_string (), "-5,0"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle2].to_string (), "-9,0"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 5.0); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius1].to_double (), 5.0); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius2].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius2].to_double (), 9.0); + + // change handle1 explicitly + + plist = ly.get_pcell_parameters (donut->cell_index ()); + plist[p_handle1] = db::DPoint (0.0, -5.0); + donut = &ly.cell (ly.get_pcell_variant_cell (donut->cell_index (), plist)); + + lib_basic->refresh (); + EXPECT_EQ (donut->bbox ().to_string (), "(-9000,-9000;9000,9000)"); + EXPECT_EQ (donut->get_display_name (), "Basic.DONUT(l=1/0,r=5..9,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle2].to_string (), "-9,0"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius1].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius2].to_double (), 9); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius2].to_double (), 9); + + // change handle2 explicitly + + plist = ly.get_pcell_parameters (donut->cell_index ()); + plist[p_handle2] = db::DPoint (9.0, 0.0); + donut = &ly.cell (ly.get_pcell_variant_cell (donut->cell_index (), plist)); + + lib_basic->refresh (); + EXPECT_EQ (donut->bbox ().to_string (), "(-9000,-9000;9000,9000)"); + EXPECT_EQ (donut->get_display_name (), "Basic.DONUT(l=1/0,r=5..9,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle1].to_string (), "0,-5"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_handle2].to_string (), "9,0"); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius1].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius1].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_radius2].to_double (), 9); + EXPECT_EQ (ly.get_pcell_parameters (donut->cell_index ()) [p_actual_radius2].to_double (), 9); + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + + db::Shapes shapes; + db::Shape s = shapes.insert (db::Box (1000, 2000, 3000, 5000)); + EXPECT_EQ (lib_basic->layout ().pcell_declaration (pc.second)->can_create_from_shape (ly, s, l1), true); + EXPECT_EQ (lib_basic->layout ().pcell_declaration (pc.second)->transformation_from_shape (ly, s, l1).to_string (), "r0 2000,3500"); + plist = lib_basic->layout ().pcell_declaration (pc.second)->parameters_from_shape (ly, s, l1); + EXPECT_EQ (plist [p_layer].to_string (), "1/0"); + EXPECT_EQ (plist [p_actual_radius1].to_string (), "1"); + EXPECT_EQ (plist [p_actual_radius2].to_string (), "0.5"); +} + +TEST(5_Ellipse) +{ + static size_t p_layer = 0; + static size_t p_radius_x = 1; + static size_t p_radius_y = 2; + static size_t p_handle_x = 3; + static size_t p_handle_y = 4; + static size_t p_npoints = 5; + static size_t p_actual_radius_x = 6; + static size_t p_actual_radius_y = 7; + static size_t p_total = 8; + + db::Library *lib_basic = db::LibraryManager::instance ().lib_ptr_by_name ("Basic"); + tl_assert (lib_basic); + + db::Layout ly; + + std::pair pc = lib_basic->layout ().pcell_by_name ("ELLIPSE"); + tl_assert (pc.first); + + std::map params; + params["layer"] = db::LayerProperties (1, 0); + params["actual_radius_x"] = 4.0; + params["actual_radius_y"] = 10.0; + params["actual_start_angle"] = -90.0; + params["actual_end_angle"] = 0.0; + + db::cell_index_type lib_cell; + db::Cell *ellipse; + std::vector plist; + + lib_cell = lib_basic->layout ().get_pcell_variant_dict (pc.second, params); + ellipse = &ly.cell (ly.get_lib_proxy (lib_basic, lib_cell)); + + // change radius explicitly + + // has radius 10um, but bbox isn't correct for now (because handle was not updated) + EXPECT_EQ (ellipse->bbox ().to_string (), "(-4000,-10000;4000,10000)"); + EXPECT_EQ (ellipse->get_display_name (), "Basic.ELLIPSE(l=1/0,rx=4,ry=10,n=64)"); + + // only after Library::refresh the parameters get updated and bbox is correct + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 0.0); + + lib_basic->refresh (); + EXPECT_EQ (ellipse->bbox ().to_string (), "(-4000,-10000;4000,10000)"); + EXPECT_EQ (ellipse->get_display_name (), "Basic.ELLIPSE(l=1/0,rx=4,ry=10,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 4.0); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_x].to_double (), 4.0); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_y].to_double (), 10.0); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_y].to_double (), 10.0); + + // change radius2 explicitly + + plist = ly.get_pcell_parameters (ellipse->cell_index ()); + plist[p_actual_radius_y] = 9.0; + ellipse = &ly.cell (ly.get_pcell_variant_cell (ellipse->cell_index (), plist)); + + // as the radius is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_y].to_double (), 10.0); + + lib_basic->refresh (); + EXPECT_EQ (ellipse->bbox ().to_string (), "(-4000,-9000;4000,9000)"); + EXPECT_EQ (ellipse->get_display_name (), "Basic.ELLIPSE(l=1/0,rx=4,ry=9,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_x].to_string (), "-4,0"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_y].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 4.0); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_x].to_double (), 4.0); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_y].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_y].to_double (), 9.0); + + // change radius1 explicitly + + plist = ly.get_pcell_parameters (ellipse->cell_index ()); + plist[p_actual_radius_x] = 5.0; + ellipse = &ly.cell (ly.get_pcell_variant_cell (ellipse->cell_index (), plist)); + + // as the radius is an input parameter, only after Library::refresh the other parameters get updated + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 4.0); + + lib_basic->refresh (); + EXPECT_EQ (ellipse->bbox ().to_string (), "(-5000,-9000;5000,9000)"); + EXPECT_EQ (ellipse->get_display_name (), "Basic.ELLIPSE(l=1/0,rx=5,ry=9,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_x].to_string (), "-5,0"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_y].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 5.0); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_x].to_double (), 5.0); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_y].to_double (), 9.0); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_y].to_double (), 9.0); + + // change handle1 explicitly + + plist = ly.get_pcell_parameters (ellipse->cell_index ()); + plist[p_handle_x] = db::DPoint (-5.0, 0.0); + ellipse = &ly.cell (ly.get_pcell_variant_cell (ellipse->cell_index (), plist)); + + lib_basic->refresh (); + EXPECT_EQ (ellipse->bbox ().to_string (), "(-5000,-9000;5000,9000)"); + EXPECT_EQ (ellipse->get_display_name (), "Basic.ELLIPSE(l=1/0,rx=5,ry=9,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_x].to_string (), "-5,0"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_y].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_x].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_y].to_double (), 9); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_y].to_double (), 9); + + // change handle2 explicitly + + plist = ly.get_pcell_parameters (ellipse->cell_index ()); + plist[p_handle_y] = db::DPoint (0.0, 9.0); + ellipse = &ly.cell (ly.get_pcell_variant_cell (ellipse->cell_index (), plist)); + + lib_basic->refresh (); + EXPECT_EQ (ellipse->bbox ().to_string (), "(-5000,-9000;5000,9000)"); + EXPECT_EQ (ellipse->get_display_name (), "Basic.ELLIPSE(l=1/0,rx=5,ry=9,n=64)"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_x].to_string (), "-5,0"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_handle_y].to_string (), "0,9"); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_x].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_x].to_double (), 5); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_radius_y].to_double (), 9); + EXPECT_EQ (ly.get_pcell_parameters (ellipse->cell_index ()) [p_actual_radius_y].to_double (), 9); + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + + db::Shapes shapes; + db::Shape s = shapes.insert (db::Box (1000, 2000, 3000, 5000)); + EXPECT_EQ (lib_basic->layout ().pcell_declaration (pc.second)->can_create_from_shape (ly, s, l1), true); + EXPECT_EQ (lib_basic->layout ().pcell_declaration (pc.second)->transformation_from_shape (ly, s, l1).to_string (), "r0 2000,3500"); + plist = lib_basic->layout ().pcell_declaration (pc.second)->parameters_from_shape (ly, s, l1); + EXPECT_EQ (plist [p_layer].to_string (), "1/0"); + EXPECT_EQ (plist [p_actual_radius_x].to_string (), "1"); + EXPECT_EQ (plist [p_actual_radius_y].to_string (), "1.5"); +} + +// regeneration of PCells after reading +TEST(10) +{ + db::Layout ly; + + { + std::string fn (tl::testdata ()); + fn += "/gds/basic_instances.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::Library *lib_basic = db::LibraryManager::instance ().lib_ptr_by_name ("Basic"); + tl_assert (lib_basic); + lib_basic->refresh (); + + CHECKPOINT(); + db::compare_layouts (_this, ly, tl::testdata () + "/gds/basic_instances_au.gds"); +} diff --git a/testdata/gds/basic_instances.gds b/testdata/gds/basic_instances.gds new file mode 100644 index 0000000000000000000000000000000000000000..ad4a521104ba48db9ef9b43c5322e5e0ac579306 GIT binary patch literal 10170 zcmeI2TWDO@6^8fB939CMNp*~4C&q+;1h(l|nUO})$cap3St&||thlNhnu{4M(<%{) zv24>6{1gZ@5a>%BLR~1uP{>Q%my)-XCM~4&p$~= zV{&5zn_p-4Wv%_Mf3LmwnQ@^@CZBTq6UpvduFLIlyWJ6&^8a_~WO!`$*xc+fw>#B! zbm~{*Km6Mt{xfm>oriz-o1ZSa{awv_?g_)e!NKVh^NTZ2EuNm8fBXcGE=W7qyDOZT zo10zu(G36ZOu6!3`2D2Y;dW)hg=y+1D{b_7kK4oN2hSImmM^ZIe(BKUz(95==bY-g ztLlDHRTtWL2UpL%xV(B{jjFM{_33i=YrK`>OJ~m?nta;uNbce6vsN3phgAFX;_A}M zSy_8}$p$!b7^4{)S*ui4E9`o$hAXX-ZokGVp1E+bxN_Q`KyGN*#z{145l^FFEu8Dm zgal#oSaEInjB~-gl!(dWC+2^=I0zH4 zJLT}fEe^3%OO8fPIj;>iy*5U(+BD+N92b2}`HLq|h*~t`uV+^{b#l6%yYGqbh&!v7 zAN@W*Rm}DIHC4>@Hc{U_E!CIyS@D?5W>8cWpq>#b^{FZgXIGcD{KU;j z1&YYQqCA_(mgC-QpUIbO%XLDW7iJq|o4&0$TfHpx`q3;e0~`IGCeci{jAm7&nnbgw zjc9ha70s}U>1dg266IX;O^;N1S2#U;a(Zs2E}w<2lF#B6idI+CXa!B8m1-HSq#ud; zgcRo+U+wiAH_JBtm3^;qzHWQxt7N{0J71jh?n2h~cfM=}tI_V*YTqk-CHo#KiTAWS z-Sx`rq0z1v?YVb>KX0`k#-ON?W?SrfMqiZg>Q4>IeYTKe71p(3f-x7xpKe zOR`={rP7C`((MKCRqz>b5?m{lHa`Pj2j2q!0xp4HfCHt{`Xi;%#x3v_@NJMWHZD{0 zlqV@yC>hEorJp`8(B^aSBk&V!U~l~<_*WsiT#1iTJ@?p$I}{Xpz*WbiZzJ_$Y# zUIzaGzU^G<0C)@hrThXJZ*z$&Yd827coh5$#C~ZKd<}dRyas*)unkV=W z_=r$E=yPxZ+=0&@sUL{_A59J!I7v&nQALSaYC*>NgFXbAoH{}|wKjj*&N97u=Ps=r|SLGV5U&}SvwOqsc zwp_z_hOB?(8s!7aHP~0KQNB>FQT|Y_Q9e^basT!W$HJ@i9Xn)_r`K811d!CvZ#;2ce!j9F+NZ*Ex)L%JC>ps?4P3-%Y z=Qsy+&eEg|&IO&bbmQ+k!}6QO8YOj3(w&nuE9Vj?h|WnmI-Tm)-Z@F%=}DRsQ2Z9Y zCey@c={Gn_FQc|J_&+eqnR-8X5j+R}F*;+XKIV>ahjnEj?gXii!GCGo_{@9}{58*6kh)YlE^mM;?^ATgxew&h5OAMJ z{uX=_WbEJr#`_caDfp;!U9@rUg1f=Tg!uJmeGcMN@F{*XX7B;{1o$TNy8-epVdD&V zA3SjXOT7aMCgYv=y!{Wi+6YU4Nm zHA?!<+|0P)FP>N+@GSVcZ*jW+=^Ul}`=grgLH3@jt@XcWJg~F2*8dK7?0Rjj|2qKL zW%RP$s^4?SYIU9cX2-sDl1;CU`BdJNTD`1#^$otEe|(|Jue#r^slGe{=`?xIaF2uXC#tO*@BQ?|<<7PktZV z_2u@D-hX1sZEUJPZmsWkb#;yGo|qbad}?}Z;=bK{bY9ZAV5h{=-{_o;18GwY_JrwYIvfTA$6$&CKrarG3W6-_^5iAU%-j9Z2={r+d@g z}rhCbJn^V!i4`hX#iCjMUP=EhP=mBe2pDjm#)bZR<1p?a>w^HnlBfEp2sT zUa@G*$!La`sberT*xNTSkjiAzeW)Y)G3265S!F5J-`_uw>Q83|`+73ns3ZD0P-V-q z)X`j)cY!*JbXe4WjUGi>tjCfHibhry=&}?P4X-*}^Ws`4h#cFsd*YF)>V3Agq@S>d z;%bTJQb=pBdD|RqF*@1dLcVM7!A*;1nHN=7B+ClYk~fKHpGY=obCvvpT_(B@mE}Wt zM#Spng95NQ>M68imCrdeHu-SPld9F!Wjj#VE10dtt<|0pxHA2ccDmwu)m+y0qS}gH z_;u8J1w6`H@i6PgYQRwsm}|x*!PksK+FE81B+H-#*@A zwM@0b{;!qH>`hb2%wDxhh8(ezyfXWjd(sDcaP>)F*n_Y3NxyU*T>qrcWHZ@;3louzt=*o)UJxc?@-lnOm6`a59RZh zJ}bNo(C6@a8QjeEopbTiJQ`vq{v5ayWVCnCx!Bv_n_w4sj5&^jTyBRjpU*SaI|fdI zZ|3t0XTgIYW4)dE{N)9(8GJ`}z%=+W{`>?6e%Vv$5)rofr6<;k7~^D>{K)4oPRbAP zDft1;%Mb8v`2n7gAK(S~fe$<62iI%irT@97HtVCl8l$nyVRLCt&5aGSC7Whjoanwd z0_Vk<#)(7lgg6B+h-29SPs=VmYzD;#ycj>?3BHUs@duB_r+5{=@N9gGcky3bk8pih zCtEMAo7RuDu=UisYJIiNthd(P)?ayWy>mevz=d%lZs5qc5@&E{9EwYE3b)3wxEAN7 zHCRqAp_cIdKt(3Sx=k(b;>iIRNrHcYJ*>t?@F;i){2V+5{=#Z(fz5UhroC?PPjHx3 zc^VuC>F15(WmfmWkHK!DXan0pB1!xL{-}A0ntq9+;9Fo1NLwNqUhjgszU9&?t^rv| z4;JDdg71OM?VV)4FTmfxyPa#IkNXN-4c;Tfudj6<#3%1J{ANz?B=`XM9`T(4$?(g1 zX|x6&$lAoW;5%Tz&oY?~pMfiw_Fx+8H-cszQJsSsLwwR6@GJNR_%}EN3mq`?2dEYP z6lC98m;qk_JHgMm&W9KO+dZ|ZkNRqi#%d1c(wsK8Y{-^u$_Hsc_=4_(-++I!ij2A3 z0Y0jEzz;z7@Yv7bE3Enkko`T5t;^@ZSLFjJUuM8F@&UyD!XK<)t9$@&1K$8Q$p;}e zH|xH909)mQ#>ofGBOgF)#XbOEl@B1k#5aVO`4zUQkNRqi#%d1c(wsK8Y{-^u7JUeP zl5g@6U*)s;t{4=HVltjVVzrnRyEqURaAMrZ7jY%d#GN>VOL1!4ieqtoPCkT49$cK{ za{(KB`oBNluic*B;TNh*)#(+xO;{nIGCL_yot@sO&?*E}VW&GP)oCx)>hzb2tr|et zst}}dRSQzRDg-H8)r6F-3c+>>PG~7x6@n?7lj+hqGMSyuvW#ppWm6%Tvb!{ntfWFv zma0OKvUU2IvQL9#wJHQwE%2stCm8)8i>Qy~R*{UX_Y*iPwOK?I<*{VKF*~h_6 zh-rsVJm@}%!c5s`HI5imp`dJ4i&D0#A5(T3glAPpQno4tDO=T(l&uOu%C-stWvkkf zvaLcu*;b9govpjAfAAd$;Vt(48WlqLR;_j>-3aGaV_*6&>`N{7WQL$_(&sYbv-fWm z@r9MNl&f7Li=s~jO1`f3NmjnF^Jpj2b-kZ?0)CcLN%Q<$d<#{1ME_L|}w+lsxWQAsx{X{z_-SJKo6Q@bhlYyRq}`3L8??EFhs z{dR5Lp~}|qt(|>~uz6)=Yxt(gTC>M1Tch8S%PzAQ?3R7cEUV>hrSBJIGtyS|&5*1{ z+H3sE;l9Z-zpB0)QF~#Aw&I)owLD!pe_f1Ukq})zf8h`x7hH0^ziZF%V-v7@E7#)v a*YT^d_5S^%6Qg^Er$%>$V|WhoJogW3G#*F* literal 0 HcmV?d00001 diff --git a/testdata/ruby/dbPCells.rb b/testdata/ruby/dbPCells.rb index 6ab969c8b..a9cbf14a2 100644 --- a/testdata/ruby/dbPCells.rb +++ b/testdata/ruby/dbPCells.rb @@ -110,6 +110,7 @@ if RBA.constants.member?(:PCellDeclarationHelper) param("layer", BoxPCell2::TypeLayer, "Layer", :default => RBA::LayerInfo::new(0, 0)) param("width", BoxPCell2::TypeDouble, "Width", :default => 1.0) param("height", BoxPCell2::TypeDouble, "Height", :default => 1.0) + param("secret", BoxPCell2::TypeInt, "Secret", :default => 0) end @@ -130,6 +131,10 @@ if RBA.constants.member?(:PCellDeclarationHelper) end + def coerce_parameters_impl + self.secret = [0, self.secret].max + end + def can_create_from_shape_impl return self.shape.is_box? end @@ -192,150 +197,145 @@ class DBPCell_TestClass < TestBase # instantiate and register the library tl = PCellTestLib::new - begin + ly = RBA::Layout::new(true) + ly.dbu = 0.01 - ly = RBA::Layout::new(true) - ly.dbu = 0.01 + li1 = ly.layer(1, 0) - li1 = ly.layer(1, 0) + ci1 = ly.add_cell("c1") + c1 = ly.cell(ci1) - ci1 = ly.add_cell("c1") - c1 = ly.cell(ci1) + lib = RBA::Library::library_by_name("NoLib") + assert_equal(lib == nil, true) + lib = RBA::Library::library_by_name("PCellTestLib") + assert_equal(lib != nil, true) + pcell_decl = lib.layout.pcell_declaration("x") + assert_equal(pcell_decl == nil, true) + pcell_decl = lib.layout.pcell_declaration("Box") + assert_equal(pcell_decl != nil, true) + pcell_decl_id = lib.layout.pcell_id("Box") + assert_equal(pcell_decl.id, pcell_decl_id) + assert_equal(lib.layout.pcell_names.join(":"), "Box") + assert_equal(lib.layout.pcell_ids, [ pcell_decl_id ]) + assert_equal(lib.layout.pcell_declaration(pcell_decl_id).id, pcell_decl_id) - lib = RBA::Library::library_by_name("NoLib") - assert_equal(lib == nil, true) - lib = RBA::Library::library_by_name("PCellTestLib") - assert_equal(lib != nil, true) - pcell_decl = lib.layout.pcell_declaration("x") - assert_equal(pcell_decl == nil, true) - pcell_decl = lib.layout.pcell_declaration("Box") - assert_equal(pcell_decl != nil, true) - pcell_decl_id = lib.layout.pcell_id("Box") - assert_equal(pcell_decl.id, pcell_decl_id) - assert_equal(lib.layout.pcell_names.join(":"), "Box") - assert_equal(lib.layout.pcell_ids, [ pcell_decl_id ]) - assert_equal(lib.layout.pcell_declaration(pcell_decl_id).id, pcell_decl_id) + 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 = ly.cell(pcell_var_id) + 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.library.inspect, lib.inspect) + assert_equal(pcell_var.is_pcell_variant?, true) + assert_equal(pcell_var.display_title, "PCellTestLib.Box(L=1/0,W=1.000,H=1.000)") + assert_equal(pcell_var.basic_name, "Box") + assert_equal(c1.is_pcell_variant?, false) + assert_equal(c1.is_pcell_variant?(pcell_inst), true) + assert_equal(pcell_var.pcell_id, pcell_decl_id) + assert_equal(pcell_var.pcell_library.inspect, lib.inspect) + assert_equal(pcell_var.pcell_parameters.inspect, "[<1/0>, 1.0, 1.0]") + assert_equal(norm_hash(pcell_var.pcell_parameters_by_name), "{\"h\"=>1.0, \"l\"=><1/0>, \"w\"=>1.0}") + assert_equal(pcell_var.pcell_parameter("h").inspect, "1.0") + assert_equal(c1.pcell_parameters(pcell_inst).inspect, "[<1/0>, 1.0, 1.0]") + assert_equal(norm_hash(c1.pcell_parameters_by_name(pcell_inst)), "{\"h\"=>1.0, \"l\"=><1/0>, \"w\"=>1.0}") + assert_equal(c1.pcell_parameter(pcell_inst, "h").inspect, "1.0") + assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name), "{\"h\"=>1.0, \"l\"=><1/0>, \"w\"=>1.0}") + assert_equal(pcell_inst["h"].inspect, "1.0") + assert_equal(pcell_inst["i"].inspect, "nil") + assert_equal(pcell_inst.pcell_parameter("h").inspect, "1.0") + assert_equal(pcell_var.pcell_declaration.inspect, pcell_decl.inspect) + assert_equal(c1.pcell_declaration(pcell_inst).inspect, pcell_decl.inspect) + assert_equal(pcell_inst.pcell_declaration.inspect, pcell_decl.inspect) - 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 = ly.cell(pcell_var_id) - 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.library.inspect, lib.inspect) - assert_equal(pcell_var.is_pcell_variant?, true) - assert_equal(pcell_var.display_title, "PCellTestLib.Box(L=1/0,W=1.000,H=1.000)") - assert_equal(pcell_var.basic_name, "Box") - assert_equal(c1.is_pcell_variant?, false) - assert_equal(c1.is_pcell_variant?(pcell_inst), true) - assert_equal(pcell_var.pcell_id, pcell_decl_id) - assert_equal(pcell_var.pcell_library.inspect, lib.inspect) - assert_equal(pcell_var.pcell_parameters.inspect, "[<1/0>, 1.0, 1.0]") - assert_equal(norm_hash(pcell_var.pcell_parameters_by_name), "{\"h\"=>1.0, \"l\"=><1/0>, \"w\"=>1.0}") - assert_equal(pcell_var.pcell_parameter("h").inspect, "1.0") - assert_equal(c1.pcell_parameters(pcell_inst).inspect, "[<1/0>, 1.0, 1.0]") - assert_equal(norm_hash(c1.pcell_parameters_by_name(pcell_inst)), "{\"h\"=>1.0, \"l\"=><1/0>, \"w\"=>1.0}") - assert_equal(c1.pcell_parameter(pcell_inst, "h").inspect, "1.0") - assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name), "{\"h\"=>1.0, \"l\"=><1/0>, \"w\"=>1.0}") - assert_equal(pcell_inst["h"].inspect, "1.0") - assert_equal(pcell_inst["i"].inspect, "nil") - assert_equal(pcell_inst.pcell_parameter("h").inspect, "1.0") - assert_equal(pcell_var.pcell_declaration.inspect, pcell_decl.inspect) - assert_equal(c1.pcell_declaration(pcell_inst).inspect, pcell_decl.inspect) - assert_equal(pcell_inst.pcell_declaration.inspect, pcell_decl.inspect) + pcell_inst["h"] = 2.0 + assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name), "{\"h\"=>2.0, \"l\"=><1/0>, \"w\"=>1.0}") + pcell_inst["abc"] = "a property" + assert_equal(pcell_inst.property("abc").inspect, "\"a property\"") - pcell_inst["h"] = 2.0 - assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name), "{\"h\"=>2.0, \"l\"=><1/0>, \"w\"=>1.0}") - pcell_inst["abc"] = "a property" - assert_equal(pcell_inst.property("abc").inspect, "\"a property\"") + c1.clear - c1.clear + param = [ RBA::LayerInfo::new(1, 0), 5.0, 10.0 ] + pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param) + pcell_var = ly.cell(pcell_var_id) + 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.library.inspect, lib.inspect) + assert_equal(pcell_var.is_pcell_variant?, true) + assert_equal(pcell_var.display_title, "PCellTestLib.Box(L=1/0,W=5.000,H=10.000)") + assert_equal(pcell_var.basic_name, "Box") + assert_equal(c1.is_pcell_variant?, false) + assert_equal(c1.is_pcell_variant?(pcell_inst), true) + assert_equal(pcell_var.pcell_id, pcell_decl_id) + assert_equal(pcell_var.pcell_library.inspect, lib.inspect) + assert_equal(pcell_var.pcell_parameters.inspect, "[<1/0>, 5.0, 10.0]") + assert_equal(c1.pcell_parameters(pcell_inst).inspect, "[<1/0>, 5.0, 10.0]") + assert_equal(pcell_inst.pcell_parameters.inspect, "[<1/0>, 5.0, 10.0]") + assert_equal(pcell_var.pcell_declaration.inspect, pcell_decl.inspect) + assert_equal(c1.pcell_declaration(pcell_inst).inspect, pcell_decl.inspect) - param = [ RBA::LayerInfo::new(1, 0), 5.0, 10.0 ] - pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param) - pcell_var = ly.cell(pcell_var_id) - 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.library.inspect, lib.inspect) - assert_equal(pcell_var.is_pcell_variant?, true) - assert_equal(pcell_var.display_title, "PCellTestLib.Box(L=1/0,W=5.000,H=10.000)") - assert_equal(pcell_var.basic_name, "Box") - assert_equal(c1.is_pcell_variant?, false) - assert_equal(c1.is_pcell_variant?(pcell_inst), true) - assert_equal(pcell_var.pcell_id, pcell_decl_id) - assert_equal(pcell_var.pcell_library.inspect, lib.inspect) - assert_equal(pcell_var.pcell_parameters.inspect, "[<1/0>, 5.0, 10.0]") - assert_equal(c1.pcell_parameters(pcell_inst).inspect, "[<1/0>, 5.0, 10.0]") - assert_equal(pcell_inst.pcell_parameters.inspect, "[<1/0>, 5.0, 10.0]") - assert_equal(pcell_var.pcell_declaration.inspect, pcell_decl.inspect) - assert_equal(c1.pcell_declaration(pcell_inst).inspect, pcell_decl.inspect) + li1 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "1/0" } + assert_equal(li1 != nil, true) + assert_equal(ly.is_valid_layer?(li1), true) + assert_equal(ly.get_info(li1).to_s, "1/0") - li1 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "1/0" } - assert_equal(li1 != nil, true) - assert_equal(ly.is_valid_layer?(li1), true) - assert_equal(ly.get_info(li1).to_s, "1/0") + lib_proxy_id = ly.add_lib_cell(lib, lib.layout.cell_by_name("StaticBox")) + lib_proxy = ly.cell(lib_proxy_id) + assert_equal(lib_proxy.display_title, "PCellTestLib.StaticBox") + assert_equal(lib_proxy.basic_name, "StaticBox") + assert_equal(lib_proxy.layout.inspect, ly.inspect) + assert_equal(lib_proxy.library.inspect, lib.inspect) + assert_equal(lib_proxy.is_pcell_variant?, false) + assert_equal(lib.layout.cell(lib.layout.cell_by_name("StaticBox")).library.inspect, "nil") - lib_proxy_id = ly.add_lib_cell(lib, lib.layout.cell_by_name("StaticBox")) - lib_proxy = ly.cell(lib_proxy_id) - assert_equal(lib_proxy.display_title, "PCellTestLib.StaticBox") - assert_equal(lib_proxy.basic_name, "StaticBox") - assert_equal(lib_proxy.layout.inspect, ly.inspect) - assert_equal(lib_proxy.library.inspect, lib.inspect) - assert_equal(lib_proxy.is_pcell_variant?, false) - assert_equal(lib.layout.cell(lib.layout.cell_by_name("StaticBox")).library.inspect, "nil") + li2 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "10/0" } + assert_equal(li2 != nil, true) - li2 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "10/0" } - assert_equal(li2 != nil, true) + assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-500;250,500)") + assert_equal(ly.begin_shapes(lib_proxy.cell_index, li2).shape.to_s, "box (0,0;10,20)") - assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-500;250,500)") - assert_equal(ly.begin_shapes(lib_proxy.cell_index, li2).shape.to_s, "box (0,0;10,20)") + param = { "w" => 1, "h" => 2 } + c1.change_pcell_parameters(pcell_inst, param) + assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-50,-100;50,100)") + + param = [ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ] + c1.change_pcell_parameters(pcell_inst, param) + assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)") + + pcell_inst.change_pcell_parameters({ "w" => 2.0, "h" => 10.0 }) + assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-100,-500;100,500)") - param = { "w" => 1, "h" => 2 } - c1.change_pcell_parameters(pcell_inst, param) - assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-50,-100;50,100)") - - param = [ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ] - c1.change_pcell_parameters(pcell_inst, param) - assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)") - - pcell_inst.change_pcell_parameters({ "w" => 2.0, "h" => 10.0 }) - assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-100,-500;100,500)") + pcell_inst.change_pcell_parameters([ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ]) + assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)") - pcell_inst.change_pcell_parameters([ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ]) - assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)") + pcell_inst.change_pcell_parameter("w", 5.0) + pcell_inst.change_pcell_parameter("h", 1.0) + assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-50;250,50)") - pcell_inst.change_pcell_parameter("w", 5.0) - pcell_inst.change_pcell_parameter("h", 1.0) - assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-50;250,50)") + c1.change_pcell_parameter(pcell_inst, "w", 10.0) + c1.change_pcell_parameter(pcell_inst, "h", 2.0) + assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-500,-100;500,100)") - c1.change_pcell_parameter(pcell_inst, "w", 10.0) - c1.change_pcell_parameter(pcell_inst, "h", 2.0) - assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-500,-100;500,100)") + assert_equal(ly.cell(pcell_inst.cell_index).is_pcell_variant?, true) + assert_equal(pcell_inst.is_pcell?, true) + new_id = ly.convert_cell_to_static(pcell_inst.cell_index) + assert_equal(new_id == pcell_inst.cell_index, false) + assert_equal(ly.cell(new_id).is_pcell_variant?, false) + param = [ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ] + c1.change_pcell_parameters(pcell_inst, param) + assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)") + pcell_inst.cell_index = new_id + assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-500,-100;500,100)") - assert_equal(ly.cell(pcell_inst.cell_index).is_pcell_variant?, true) - assert_equal(pcell_inst.is_pcell?, true) - new_id = ly.convert_cell_to_static(pcell_inst.cell_index) - assert_equal(new_id == pcell_inst.cell_index, false) - assert_equal(ly.cell(new_id).is_pcell_variant?, false) - param = [ RBA::LayerInfo::new(1, 0), 5.0, 5.0 ] - c1.change_pcell_parameters(pcell_inst, param) - assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-250,-250;250,250)") - pcell_inst.cell_index = new_id - assert_equal(ly.begin_shapes(c1.cell_index, li1).shape.to_s, "box (-500,-100;500,100)") + l10 = ly.layer(10, 0) + c1.shapes(l10).insert(RBA::Box::new(0, 10, 100, 210)) + l11 = ly.layer(11, 0) + c1.shapes(l11).insert(RBA::Text::new("hello", RBA::Trans::new)) + assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), false) + assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), true) + assert_equal(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).inspect, "[<10/0>, 1.0, 2.0]") + assert_equal(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).to_s, "r0 50,110") - l10 = ly.layer(10, 0) - c1.shapes(l10).insert(RBA::Box::new(0, 10, 100, 210)) - l11 = ly.layer(11, 0) - c1.shapes(l11).insert(RBA::Text::new("hello", RBA::Trans::new)) - assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), false) - assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), true) - assert_equal(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).inspect, "[<10/0>, 1.0, 2.0]") - assert_equal(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).to_s, "r0 50,110") - - ly.destroy - - ensure - tl.delete - end + ly._destroy + tl._destroy end @@ -348,63 +348,84 @@ class DBPCell_TestClass < TestBase # instantiate and register the library tl = PCellTestLib2::new - begin + ly = RBA::Layout::new(true) + ly.dbu = 0.01 - ly = RBA::Layout::new(true) - ly.dbu = 0.01 + ci1 = ly.add_cell("c1") + c1 = ly.cell(ci1) - 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") - 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) + pcell_var = ly.cell(pcell_var_id) + pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new)) + assert_equal(pcell_var.basic_name, "Box2") + 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(norm_hash(pcell_var.pcell_parameters_by_name()), "{\"height\"=>1.0, \"layer\"=><1/0>, \"secret\"=>0, \"width\"=>1.0}") + assert_equal(pcell_var.pcell_parameter("height").inspect(), "1.0") + assert_equal(c1.pcell_parameters(pcell_inst).inspect(), "[<1/0>, 1.0, 1.0, 0]") + assert_equal(c1.pcell_parameter(pcell_inst, "secret"), 0) + assert_equal(norm_hash(c1.pcell_parameters_by_name(pcell_inst)), "{\"height\"=>1.0, \"layer\"=><1/0>, \"secret\"=>0, \"width\"=>1.0}") + assert_equal(c1.pcell_parameter(pcell_inst, "height").inspect(), "1.0") + assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name()), "{\"height\"=>1.0, \"layer\"=><1/0>, \"secret\"=>0, \"width\"=>1.0}") + assert_equal(pcell_inst["height"].inspect(), "1.0") + assert_equal(pcell_inst.pcell_parameter("height").inspect(), "1.0") + assert_equal(pcell_var.pcell_declaration().inspect(), pcell_decl.inspect) + assert_equal(c1.pcell_declaration(pcell_inst).inspect(), pcell_decl.inspect) + assert_equal(pcell_inst.pcell_declaration().inspect(), pcell_decl.inspect) - 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 = ly.cell(pcell_var_id) - pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new)) - assert_equal(pcell_var.basic_name, "Box2") - assert_equal(pcell_var.pcell_parameters().inspect, "[<1/0>, 1.0, 1.0]") - 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>, \"width\"=>1.0}") - assert_equal(pcell_var.pcell_parameter("height").inspect(), "1.0") - assert_equal(c1.pcell_parameters(pcell_inst).inspect(), "[<1/0>, 1.0, 1.0]") - assert_equal(norm_hash(c1.pcell_parameters_by_name(pcell_inst)), "{\"height\"=>1.0, \"layer\"=><1/0>, \"width\"=>1.0}") - assert_equal(c1.pcell_parameter(pcell_inst, "height").inspect(), "1.0") - assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name()), "{\"height\"=>1.0, \"layer\"=><1/0>, \"width\"=>1.0}") - assert_equal(pcell_inst["height"].inspect(), "1.0") - assert_equal(pcell_inst.pcell_parameter("height").inspect(), "1.0") - assert_equal(pcell_var.pcell_declaration().inspect(), pcell_decl.inspect) - assert_equal(c1.pcell_declaration(pcell_inst).inspect(), pcell_decl.inspect) - assert_equal(pcell_inst.pcell_declaration().inspect(), pcell_decl.inspect) + li1 = ly.layer(1, 0) + assert_equal(li1 == nil, false) + pcell_inst.change_pcell_parameter("height", 2.0) + assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name()), "{\"height\"=>2.0, \"layer\"=><1/0>, \"secret\"=>0, \"width\"=>1.0}") - li1 = ly.layer(1, 0) - assert_equal(li1 == nil, false) - pcell_inst.change_pcell_parameter("height", 2.0) - assert_equal(norm_hash(pcell_inst.pcell_parameters_by_name()), "{\"height\"=>2.0, \"layer\"=><1/0>, \"width\"=>1.0}") + assert_equal(ly.begin_shapes(c1.cell_index(), li1).shape().to_s, "box (-50,-100;50,100)") - assert_equal(ly.begin_shapes(c1.cell_index(), li1).shape().to_s, "box (-50,-100;50,100)") + param = { "layer" => RBA::LayerInfo::new(2, 0), "width" => 2, "height" => 1 } + li2 = ly.layer(2, 0) + c1.change_pcell_parameters(pcell_inst, param) + assert_equal(ly.begin_shapes(c1.cell_index(), li2).shape().to_s, "box (-100,-50;100,50)") - param = { "layer" => RBA::LayerInfo::new(2, 0), "width" => 2, "height" => 1 } - li2 = ly.layer(2, 0) - c1.change_pcell_parameters(pcell_inst, param) - assert_equal(ly.begin_shapes(c1.cell_index(), li2).shape().to_s, "box (-100,-50;100,50)") + l10 = ly.layer(10, 0) + c1.shapes(l10).insert(RBA::Box::new(0, 10, 100, 210)) + l11 = ly.layer(11, 0) + c1.shapes(l11).insert(RBA::Text::new("hello", RBA::Trans::new)) + assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), false) + assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), true) + assert_equal(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).inspect, "[<10/0>, 1.0, 2.0, 0]") + assert_equal(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).to_s, "r0 50,110") - l10 = ly.layer(10, 0) - c1.shapes(l10).insert(RBA::Box::new(0, 10, 100, 210)) - l11 = ly.layer(11, 0) - c1.shapes(l11).insert(RBA::Text::new("hello", RBA::Trans::new)) - assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), false) - assert_equal(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), true) - assert_equal(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).inspect, "[<10/0>, 1.0, 2.0]") - assert_equal(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10).to_s, "r0 50,110") + param2 = c1.pcell_parameters(pcell_inst) + param2[3] = -2 # "secret" + pcell_var_id2 = ly.add_pcell_variant(lib, pcell_decl.id(), param2) + pcell_var2 = ly.cell(pcell_var_id2) + pcell_inst2 = c1.insert(RBA::CellInstArray::new(pcell_var_id2, RBA::Trans::new)) - ly.destroy + assert_equal(c1.pcell_parameter(pcell_inst2, "secret"), -2) # coerce_parameters NOT called! + assert_not_equal(pcell_inst.cell.library_cell_index, pcell_inst2.cell.library_cell_index) - ensure - tl.delete - end + param = { "secret" => -1 } + c1.change_pcell_parameters(pcell_inst, param) + assert_equal(c1.pcell_parameter(pcell_inst, "secret"), -1) # coerce_parameters NOT called! + + tl.refresh + assert_equal(c1.pcell_parameter(pcell_inst2, "secret"), 0) # coerce_parameters was called + assert_equal(c1.pcell_parameter(pcell_inst, "secret"), 0) # coerce_parameters was called + + # same variant now + assert_equal(pcell_inst.cell.library_cell_index, pcell_inst2.cell.library_cell_index) + + param = { "secret" => 42 } + c1.change_pcell_parameters(pcell_inst, param) + assert_equal(c1.pcell_parameter(pcell_inst, "secret"), 42) + assert_not_equal(pcell_inst.cell.library_cell_index, pcell_inst2.cell.library_cell_index) + + ly._destroy + tl._destroy end @@ -413,43 +434,38 @@ class DBPCell_TestClass < TestBase # instantiate and register the library tl = PCellTestLib::new - begin + ly = RBA::Layout::new(true) + ly.dbu = 0.01 - ly = RBA::Layout::new(true) - ly.dbu = 0.01 + ci1 = ly.add_cell("c1") + c1 = ly.cell(ci1) - ci1 = ly.add_cell("c1") - c1 = ly.cell(ci1) + lib = RBA::Library::library_by_name("PCellTestLib") + pcell_decl_id = lib.layout.pcell_id("Box") - lib = RBA::Library::library_by_name("PCellTestLib") - pcell_decl_id = lib.layout.pcell_id("Box") + param = [ RBA::LayerInfo::new(1, 0), 10.0, 2.0 ] + pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param) + pcell_var = ly.cell(pcell_var_id) + pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new)) - param = [ RBA::LayerInfo::new(1, 0), 10.0, 2.0 ] - pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param) - pcell_var = ly.cell(pcell_var_id) - pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new)) + li1 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "1/0" } + assert_equal(li1 != nil, true) + assert_equal(ly.is_valid_layer?(li1), true) + assert_equal(ly.get_info(li1).to_s, "1/0") - li1 = ly.layer_indices.find { |li| ly.get_info(li).to_s == "1/0" } - assert_equal(li1 != nil, true) - assert_equal(ly.is_valid_layer?(li1), true) - assert_equal(ly.get_info(li1).to_s, "1/0") + assert_equal(pcell_inst.is_pcell?, true) - assert_equal(pcell_inst.is_pcell?, true) + assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)") + pcell_inst.convert_to_static + assert_equal(pcell_inst.is_pcell?, false) + assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)") + pcell_inst.convert_to_static + assert_equal(pcell_inst.is_pcell?, false) + assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)") - assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)") - pcell_inst.convert_to_static - assert_equal(pcell_inst.is_pcell?, false) - assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)") - pcell_inst.convert_to_static - assert_equal(pcell_inst.is_pcell?, false) - assert_equal(ly.begin_shapes(pcell_inst.cell_index, li1).shape.to_s, "box (-500,-100;500,100)") + ly._destroy + tl._destroy -#ly.destroy - - ensure -#tl.delete - end - end def test_3 @@ -457,27 +473,24 @@ class DBPCell_TestClass < TestBase # instantiate and register the library tl = PCellTestLib::new - begin + ly = RBA::Layout::new(true) + ly.dbu = 0.01 - ly = RBA::Layout::new(true) - ly.dbu = 0.01 + c1 = ly.create_cell("c1") - c1 = ly.create_cell("c1") + lib = RBA::Library::library_by_name("PCellTestLib") + pcell_decl_id = lib.layout.pcell_id("Box") - lib = RBA::Library::library_by_name("PCellTestLib") - pcell_decl_id = lib.layout.pcell_id("Box") + param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(1, 0) } + pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param) + pcell_var = ly.cell(pcell_var_id) + pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new)) - param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(1, 0) } - pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param) - pcell_var = ly.cell(pcell_var_id) - pcell_inst = c1.insert(RBA::CellInstArray::new(pcell_var_id, RBA::Trans::new)) - - assert_equal(ly.begin_shapes(c1.cell_index, ly.layer(1, 0)).shape.to_s, "box (-200,-400;200,400)") - - ensure -#tl.delete - end + assert_equal(ly.begin_shapes(c1.cell_index, ly.layer(1, 0)).shape.to_s, "box (-200,-400;200,400)") + ly._destroy + tl._destroy + end def test_4 @@ -485,20 +498,16 @@ class DBPCell_TestClass < TestBase # instantiate and register the library tl = PCellTestLib::new - begin + lib = RBA::Library::library_by_name("PCellTestLib") + pcell_decl_id = lib.layout.pcell_id("Box") - lib = RBA::Library::library_by_name("PCellTestLib") - pcell_decl_id = lib.layout.pcell_id("Box") + param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(1, 0) } + pcell_var_id = lib.layout.add_pcell_variant(pcell_decl_id, param) - param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(1, 0) } - pcell_var_id = lib.layout.add_pcell_variant(pcell_decl_id, param) - - assert_equal(lib.layout.begin_shapes(pcell_var_id, lib.layout.layer(1, 0)).shape.to_s, "box (-2000,-4000;2000,4000)") - - ensure -#tl.delete - end + assert_equal(lib.layout.begin_shapes(pcell_var_id, lib.layout.layer(1, 0)).shape.to_s, "box (-2000,-4000;2000,4000)") + tl._destroy + end def test_5 @@ -506,19 +515,15 @@ class DBPCell_TestClass < TestBase # instantiate and register the library tl = PCellTestLib::new - begin + lib = RBA::Library::library_by_name("PCellTestLib") + pcell_decl_id = lib.layout.pcell_id("Box") - lib = RBA::Library::library_by_name("PCellTestLib") - pcell_decl_id = lib.layout.pcell_id("Box") + param = { "w" => 3.0, "h" => 7.0, "l" => RBA::LayerInfo::new(2, 0) } + pcell_var_id = lib.layout.add_pcell_variant(pcell_decl_id, param) - param = { "w" => 3.0, "h" => 7.0, "l" => RBA::LayerInfo::new(2, 0) } - pcell_var_id = lib.layout.add_pcell_variant(pcell_decl_id, param) + assert_equal(lib.layout.begin_shapes(pcell_var_id, lib.layout.layer(2, 0)).shape.to_s, "box (-1500,-3500;1500,3500)") - assert_equal(lib.layout.begin_shapes(pcell_var_id, lib.layout.layer(2, 0)).shape.to_s, "box (-1500,-3500;1500,3500)") - - ensure -#tl.delete - end + tl._destroy end @@ -527,18 +532,14 @@ class DBPCell_TestClass < TestBase # instantiate and register the library tl = PCellTestLib::new - begin + lib = RBA::Library::library_by_name("PCellTestLib") - lib = RBA::Library::library_by_name("PCellTestLib") + param = { "w" => 3.0, "h" => 8.0, "l" => RBA::LayerInfo::new(3, 0) } + pcell_var = lib.layout.create_cell("Box", param) - param = { "w" => 3.0, "h" => 8.0, "l" => RBA::LayerInfo::new(3, 0) } - pcell_var = lib.layout.create_cell("Box", param) - - assert_equal(lib.layout.begin_shapes(pcell_var.cell_index, lib.layout.layer(3, 0)).shape.to_s, "box (-1500,-4000;1500,4000)") + assert_equal(lib.layout.begin_shapes(pcell_var.cell_index, lib.layout.layer(3, 0)).shape.to_s, "box (-1500,-4000;1500,4000)") - ensure -#tl.delete - end + tl._destroy end @@ -547,19 +548,16 @@ class DBPCell_TestClass < TestBase # instantiate and register the library tl = PCellTestLib::new - begin + ly = RBA::Layout::new(true) + ly.dbu = 0.01 - ly = RBA::Layout::new(true) - ly.dbu = 0.01 + param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(4, 0) } + cell = ly.create_cell("Box", "PCellTestLib", param) - param = { "w" => 4.0, "h" => 8.0, "l" => RBA::LayerInfo::new(4, 0) } - cell = ly.create_cell("Box", "PCellTestLib", param) - - assert_equal(ly.begin_shapes(cell, ly.layer(4, 0)).shape.to_s, "box (-200,-400;200,400)") + assert_equal(ly.begin_shapes(cell, ly.layer(4, 0)).shape.to_s, "box (-200,-400;200,400)") - ensure -#tl.delete - end + tl._destroy + ly._destroy end @@ -568,23 +566,20 @@ class DBPCell_TestClass < TestBase # instantiate and register the library tl = PCellTestLib::new - begin + lib = RBA::Library::library_by_name("PCellTestLib") + ly = RBA::Layout::new(true) + ly.dbu = 0.01 - lib = RBA::Library::library_by_name("PCellTestLib") - ly = RBA::Layout::new(true) - ly.dbu = 0.01 + param = { "w" => 2.0, "h" => 6.0, "l" => RBA::LayerInfo::new(5, 0) } + pcell_var = lib.layout.create_cell("Box", param) + pcell_var.name = "BOXVAR" - param = { "w" => 2.0, "h" => 6.0, "l" => RBA::LayerInfo::new(5, 0) } - pcell_var = lib.layout.create_cell("Box", param) - pcell_var.name = "BOXVAR" + cell = ly.create_cell("BOXVAR", "PCellTestLib") - cell = ly.create_cell("BOXVAR", "PCellTestLib") + assert_equal(cell.begin_shapes_rec(ly.layer(5, 0)).shape.to_s, "box (-100,-300;100,300)") - assert_equal(cell.begin_shapes_rec(ly.layer(5, 0)).shape.to_s, "box (-100,-300;100,300)") - - ensure -#tl.delete - end + tl._destroy + ly._destroy end @@ -601,6 +596,8 @@ class DBPCell_TestClass < TestBase assert_equal(pcell.layout == nil, false) assert_equal(pcell.layout.object_id == layout.object_id, true) + layout._destroy + end end
" << tl::to_string (QObject::tr ("Path")) << ": " << m_h->filename () << "
" << tl::to_string (QObject::tr ("Format")) << ": " << m_h->save_options ().format () << "
" << tl::to_string (QObject::tr ("Technology")) << ": " << m_h->technology ()->description () << format_tech_name (m_h->tech_name ()) << "