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" 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'] 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/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 68b420586..b7bdabddf 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -2048,6 +2048,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)) { @@ -2296,12 +2300,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; @@ -2338,7 +2344,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 c3d5fe319..3cef7204d 100644 --- a/src/laybasic/laybasic/layCellView.cc +++ b/src/laybasic/laybasic/layCellView.cc @@ -296,7 +296,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; } @@ -370,6 +370,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); @@ -389,6 +391,7 @@ LayoutHandle::load (const db::LoadLayoutOptions &options, const std::string &tec remove_file_from_watcher (filename ()); add_file_to_watcher (filename ()); + m_save_options.set_format (reader.format ()); m_dirty = false; return new_lmap; } @@ -397,6 +400,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 ()); @@ -414,6 +419,7 @@ LayoutHandle::load () remove_file_from_watcher (filename ()); add_file_to_watcher (filename ()); + m_save_options.set_format (reader.format ()); m_dirty = false; return new_lmap; } diff --git a/src/laybasic/laybasic/layStream.h b/src/laybasic/laybasic/layStream.h index c6ba13660..963775132 100644 --- a/src/laybasic/laybasic/layStream.h +++ b/src/laybasic/laybasic/layStream.h @@ -232,6 +232,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/layui/layui/layLayoutStatisticsForm.cc b/src/layui/layui/layLayoutStatisticsForm.cc index 52b3fc9f1..a5dd164ee 100644 --- a/src/layui/layui/layLayoutStatisticsForm.cc +++ b/src/layui/layui/layLayoutStatisticsForm.cc @@ -683,8 +683,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/layui/layui/laySaveLayoutOptionsDialog.cc b/src/layui/layui/laySaveLayoutOptionsDialog.cc index d629ba568..dc741a3c5 100644 --- a/src/layui/layui/laySaveLayoutOptionsDialog.cc +++ b/src/layui/layui/laySaveLayoutOptionsDialog.cc @@ -339,16 +339,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); + + } } @@ -441,7 +472,7 @@ SaveLayoutAsOptionsDialog::get_options (lay::LayoutViewBase *view, unsigned int 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/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/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"); diff --git a/testdata/gds/basic_instances.gds b/testdata/gds/basic_instances.gds new file mode 100644 index 000000000..ad4a52110 Binary files /dev/null and b/testdata/gds/basic_instances.gds differ diff --git a/testdata/gds/basic_instances_au.gds b/testdata/gds/basic_instances_au.gds new file mode 100644 index 000000000..7eef6e0be Binary files /dev/null and b/testdata/gds/basic_instances_au.gds differ 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 ()) << "