From 50df9e5b218d9b321ced641357c088d77fdcbdf4 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 1 Apr 2017 00:45:55 +0200 Subject: [PATCH] Provide Ruby/Python binding for technology definitions The respective new classes are RBA::Technology and RBA::TechnologyComponent. This interface will replace the current way of doing tech management from scripts by using the "technology-data" configuration parameter. --- src/ext/extNetTracerPlugin.cc | 91 +++---- src/laybasic/gsiDeclLayTechnologies.cc | 318 +++++++++++++++++++++++++ src/laybasic/layTechnology.h | 12 + src/laybasic/laybasic.pro | 3 +- src/tl/tlSystemPaths.cc | 62 +++-- src/tl/tlSystemPaths.h | 14 ++ src/unit_tests/pya.cc | 2 +- src/unit_tests/rba.cc | 3 +- src/ut/utMain.cc | 4 + testdata/ruby/layTechnologies.rb | 106 +++++++++ 10 files changed, 552 insertions(+), 63 deletions(-) create mode 100644 src/laybasic/gsiDeclLayTechnologies.cc create mode 100644 testdata/ruby/layTechnologies.rb diff --git a/src/ext/extNetTracerPlugin.cc b/src/ext/extNetTracerPlugin.cc index 1222a5032..db9a499f3 100644 --- a/src/ext/extNetTracerPlugin.cc +++ b/src/ext/extNetTracerPlugin.cc @@ -139,30 +139,37 @@ public: static tl::RegisteredClass config_decl (new NetTracerPluginDeclaration (), 13000, "NetTracerPlugin"); +} + // ----------------------------------------------------------------------------------- // GSI binding -static void def_connection2 (NetTracerTechnologyComponent *tech, const std::string &la, const std::string &lb) +namespace gsi { - NetTracerLayerExpressionInfo la_info = NetTracerLayerExpressionInfo::compile (la); - NetTracerLayerExpressionInfo lb_info = NetTracerLayerExpressionInfo::compile (lb); - tech->add (NetTracerConnectionInfo (la_info, lb_info)); + +static void def_connection2 (ext::NetTracerTechnologyComponent *tech, const std::string &la, const std::string &lb) +{ + ext::NetTracerLayerExpressionInfo la_info = ext::NetTracerLayerExpressionInfo::compile (la); + ext::NetTracerLayerExpressionInfo lb_info = ext::NetTracerLayerExpressionInfo::compile (lb); + tech->add (ext::NetTracerConnectionInfo (la_info, lb_info)); } -static void def_connection3 (NetTracerTechnologyComponent *tech, const std::string &la, const std::string &via, const std::string &lb) +static void def_connection3 (ext::NetTracerTechnologyComponent *tech, const std::string &la, const std::string &via, const std::string &lb) { - NetTracerLayerExpressionInfo la_info = NetTracerLayerExpressionInfo::compile (la); - NetTracerLayerExpressionInfo via_info = NetTracerLayerExpressionInfo::compile (via); - NetTracerLayerExpressionInfo lb_info = NetTracerLayerExpressionInfo::compile (lb); - tech->add (NetTracerConnectionInfo (la_info, via_info, lb_info)); + ext::NetTracerLayerExpressionInfo la_info = ext::NetTracerLayerExpressionInfo::compile (la); + ext::NetTracerLayerExpressionInfo via_info = ext::NetTracerLayerExpressionInfo::compile (via); + ext::NetTracerLayerExpressionInfo lb_info = ext::NetTracerLayerExpressionInfo::compile (lb); + tech->add (ext::NetTracerConnectionInfo (la_info, via_info, lb_info)); } -static void def_symbol (NetTracerTechnologyComponent *tech, const std::string &name, const std::string &expr) +static void def_symbol (ext::NetTracerTechnologyComponent *tech, const std::string &name, const std::string &expr) { - tech->add_symbol (NetTracerSymbolInfo (db::LayerProperties (name), expr)); + tech->add_symbol (ext::NetTracerSymbolInfo (db::LayerProperties (name), expr)); } -gsi::Class decl_NetTracerTechnology ("NetTracerTechnology", +gsi::Class &decl_layTechnologyComponent (); + +gsi::Class decl_NetTracerTechnology (decl_layTechnologyComponent (), "NetTracerTechnology", gsi::method_ext ("connection", &def_connection2, gsi::arg("a"), gsi::arg("b"), "@brief Defines a connection between two materials\n" "See the class description for details about this method." @@ -194,90 +201,90 @@ gsi::Class decl_NetTracerTechnology ("NetTracerTec "This class has been introduced in version 0.25.\n" ); -static void trace1 (NetTracer *net_tracer, const NetTracerTechnologyComponent &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer) +static void trace1 (ext::NetTracer *net_tracer, const ext::NetTracerTechnologyComponent &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer) { - NetTracerData tracer_data = tech.get_tracer_data (layout); + ext::NetTracerData tracer_data = tech.get_tracer_data (layout); net_tracer->trace (layout, cell, start_point, start_layer, tracer_data); } -static void trace2 (NetTracer *net_tracer, const NetTracerTechnologyComponent &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer, const db::Point &stop_point, unsigned int stop_layer) +static void trace2 (ext::NetTracer *net_tracer, const ext::NetTracerTechnologyComponent &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer, const db::Point &stop_point, unsigned int stop_layer) { - NetTracerData tracer_data = tech.get_tracer_data (layout); + ext::NetTracerData tracer_data = tech.get_tracer_data (layout); net_tracer->trace (layout, cell, start_point, start_layer, stop_point, stop_layer, tracer_data); } -static NetTracerData get_tracer_data_from_cv (const lay::CellViewRef &cv) +static ext::NetTracerData get_tracer_data_from_cv (const lay::CellViewRef &cv) { const lay::Technology *tech = cv->technology (); tl_assert (tech != 0); - const NetTracerTechnologyComponent *tech_component = dynamic_cast (tech->component_by_name (net_tracer_component_name)); + const ext::NetTracerTechnologyComponent *tech_component = dynamic_cast (tech->component_by_name (ext::net_tracer_component_name)); tl_assert (tech_component != 0); return tech_component->get_tracer_data (cv->layout ()); } -static void trace1_cv (NetTracer *net_tracer, const lay::CellViewRef &cv, const db::Point &start_point, unsigned int start_layer) +static void trace1_cv (ext::NetTracer *net_tracer, const lay::CellViewRef &cv, const db::Point &start_point, unsigned int start_layer) { - NetTracerData tracer_data = get_tracer_data_from_cv (cv); + ext::NetTracerData tracer_data = get_tracer_data_from_cv (cv); net_tracer->trace (cv->layout (), *cv.cell (), start_point, start_layer, tracer_data); } -static void trace2_cv (NetTracer *net_tracer, const lay::CellViewRef &cv, const db::Point &start_point, unsigned int start_layer, const db::Point &stop_point, unsigned int stop_layer) +static void trace2_cv (ext::NetTracer *net_tracer, const lay::CellViewRef &cv, const db::Point &start_point, unsigned int start_layer, const db::Point &stop_point, unsigned int stop_layer) { - NetTracerData tracer_data = get_tracer_data_from_cv (cv); + ext::NetTracerData tracer_data = get_tracer_data_from_cv (cv); net_tracer->trace (cv->layout (), *cv.cell (), start_point, start_layer, stop_point, stop_layer, tracer_data); } -static NetTracerData get_tracer_data_from_tech (const std::string &tech_name, const db::Layout &layout) +static ext::NetTracerData get_tracer_data_from_tech (const std::string &tech_name, const db::Layout &layout) { const lay::Technology *tech = lay::Technologies::instance ()->technology_by_name (tech_name); tl_assert (tech != 0); - const NetTracerTechnologyComponent *tech_component = dynamic_cast (tech->component_by_name (net_tracer_component_name)); + const ext::NetTracerTechnologyComponent *tech_component = dynamic_cast (tech->component_by_name (ext::net_tracer_component_name)); tl_assert (tech_component != 0); return tech_component->get_tracer_data (layout); } -static void trace1_tn (NetTracer *net_tracer, const std::string &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer) +static void trace1_tn (ext::NetTracer *net_tracer, const std::string &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer) { - NetTracerData tracer_data = get_tracer_data_from_tech (tech, layout); + ext::NetTracerData tracer_data = get_tracer_data_from_tech (tech, layout); net_tracer->trace (layout, cell, start_point, start_layer, tracer_data); } -static void trace2_tn (NetTracer *net_tracer, const std::string &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer, const db::Point &stop_point, unsigned int stop_layer) +static void trace2_tn (ext::NetTracer *net_tracer, const std::string &tech, const db::Layout &layout, const db::Cell &cell, const db::Point &start_point, unsigned int start_layer, const db::Point &stop_point, unsigned int stop_layer) { - NetTracerData tracer_data = get_tracer_data_from_tech (tech, layout); + ext::NetTracerData tracer_data = get_tracer_data_from_tech (tech, layout); net_tracer->trace (layout, cell, start_point, start_layer, stop_point, stop_layer, tracer_data); } -gsi::Class decl_NetElement ("NetElement", - gsi::method ("trans", &NetTracerShape::trans, +gsi::Class decl_NetElement ("NetElement", + gsi::method ("trans", &ext::NetTracerShape::trans, "@brief Gets the transformation to apply for rendering the shape in the original top cell\n" "See the class description for more details about this attribute." ) + - gsi::method ("shape", (const db::Shape &(NetTracerShape::*) () const) &NetTracerShape::shape, + gsi::method ("shape", (const db::Shape &(ext::NetTracerShape::*) () const) &ext::NetTracerShape::shape, "@brief Gets the shape that makes up this net element\n" "See the class description for more details about this attribute." ) + #if 0 - gsi::method ("is_valid?", &NetTracerShape::is_valid, + gsi::method ("is_valid?", &ext::NetTracerShape::is_valid, "@brief Gets a value indicating whether the shape is valid\n" "Currently this flag is not used." ) + - gsi::method ("is_pseudo?", &NetTracerShape::is_pseudo, + gsi::method ("is_pseudo?", &ext::NetTracerShape::is_pseudo, "@brief Gets a value indicating whether the shape is a pseudo shape\n" "Currently this flag is not used." ) + #endif - gsi::method ("cell_index", &NetTracerShape::cell_index, + gsi::method ("cell_index", &ext::NetTracerShape::cell_index, "@brief Gets the index of the cell the shape is inside" ) + - gsi::method ("layer", &NetTracerShape::layer, + gsi::method ("layer", &ext::NetTracerShape::layer, "@brief Gets the index of the layer the shape is on" ) + - gsi::method ("bbox", &NetTracerShape::bbox, + gsi::method ("bbox", &ext::NetTracerShape::bbox, "@brief Delivers the bounding box of the shape as seen from the original top cell" ), "@brief A net element for the \\NetTracer net tracing facility\n" @@ -297,7 +304,7 @@ gsi::Class decl_NetElement ("NetElement", "This class has been introduced in version 0.25.\n" ); -gsi::Class decl_NetTracer ("NetTracer", +gsi::Class decl_NetTracer ("NetTracer", gsi::method_ext ("trace", &trace1, gsi::arg ("tech"), gsi::arg ("layout"), gsi::arg ("cell"), gsi::arg ("start_point"), gsi::arg ("start_layer"), "@brief Runs a net extraction\n" "\n" @@ -353,23 +360,23 @@ gsi::Class decl_NetTracer ("NetTracer", "This method behaves identical as the version with a technology, layout and cell object, except that it will take these " "from the cellview specified." ) + - gsi::iterator ("each_element", &NetTracer::begin, &NetTracer::end, + gsi::iterator ("each_element", &ext::NetTracer::begin, &ext::NetTracer::end, "@brief Iterates over the elements found during extraction\n" "The elements are available only after the extraction has been performed." ) + - gsi::method ("num_elements", &NetTracer::size, + gsi::method ("num_elements", &ext::NetTracer::size, "@brief Returns the number of elements found during extraction\n" "This attribute is useful only after the extraction has been performed." ) + - gsi::method ("clear", &NetTracer::clear, + gsi::method ("clear", &ext::NetTracer::clear, "@brief Clears the data from the last extraction\n" ) + - gsi::method ("name", &NetTracer::name, + gsi::method ("name", &ext::NetTracer::name, "@brief Returns the name of the net found during extraction\n" "The net name is extracted from labels found during the extraction. " "This attribute is useful only after the extraction has been performed." ) + - gsi::method ("incomplete?", &NetTracer::incomplete, + gsi::method ("incomplete?", &ext::NetTracer::incomplete, "@brief Returns a value indicating whether the net is incomplete\n" "A net may be incomplete if the extraction has been stopped by the user for example. " "This attribute is useful only after the extraction has been performed." diff --git a/src/laybasic/gsiDeclLayTechnologies.cc b/src/laybasic/gsiDeclLayTechnologies.cc new file mode 100644 index 000000000..7480ac225 --- /dev/null +++ b/src/laybasic/gsiDeclLayTechnologies.cc @@ -0,0 +1,318 @@ +/* + + KLayout Layout Viewer + Copyright (C) 2006-2017 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "gsiDecl.h" +#include "layTechnology.h" +#include "tlXMLWriter.h" +#include "tlXMLParser.h" + +namespace gsi +{ + +static std::vector technology_names () +{ + std::vector names; + for (lay::Technologies::const_iterator t = lay::Technologies::instance ()->begin (); t != lay::Technologies::instance ()->end (); ++t) { + names.push_back (t->name ()); + } + return names; +} + +static lay::Technology *technology_by_name (const std::string &name) +{ + return lay::Technologies::instance ()->technology_by_name (name); +} + +static lay::Technology *create_technology (const std::string &name) +{ + lay::Technology *tech = new lay::Technology (); + tech->set_name (name); + lay::Technologies::instance ()->add (tech); + return tech; +} + +static void remove_technology (const std::string &name) +{ + lay::Technologies::instance ()->remove (name); +} + +static bool has_technology (const std::string &name) +{ + return lay::Technologies::instance ()->has_technology (name); +} + +static std::string technologies_to_xml () +{ + return lay::Technologies::instance ()->to_xml (); +} + +static void technologies_from_xml (const std::string &s) +{ + lay::Technologies::instance ()->load_from_xml (s); +} + +static lay::Technology technology_from_xml (const std::string &s) +{ + lay::Technology tech; + tl::XMLStringSource source (s); + tl::XMLStruct xml_struct ("technology", lay::Technology::xml_elements ()); + xml_struct.parse (source, tech); + return tech; +} + +static std::string technology_to_xml (const lay::Technology *tech) +{ + if (! tech) { + return std::string (); + } else { + tl::OutputStringStream os; + tl::XMLStruct xml_struct ("technology", lay::Technology::xml_elements ()); + tl::OutputStream oss (os); + xml_struct.write (oss, *tech); + return os.string (); + } +} + +static lay::TechnologyComponent *get_component (lay::Technology *tech, const std::string &name) +{ + return tech->component_by_name (name); +} + +static std::vector get_component_names (const lay::Technology *tech) +{ + return tech->component_names (); +} + +gsi::Class technology_component_decl ("TechnologyComponent", + gsi::method ("name", &lay::TechnologyComponent::name, + "@brief Gets the formal name of the technology component\n" + "This is the name by which the component can be obtained from a technology using " + "\\Technology#component." + ) + + gsi::method ("description", &lay::TechnologyComponent::description, + "@brief Gets the human-readable description string of the technology component\n" + ), + "@brief A part of a technology definition\n" + "Technology components extend technology definitions (class \\Technology) by " + "specialized subfeature definitions. For example, the net tracer supplies " + "it's technology-dependent specification through a technology component called " + "\\NetTracerTechnology.\n" + "\n" + "Components are managed within technologies and can be accessed from a technology " + "using \\Technology#component.\n" + "\n" + "This class has been introduced in version 0.25." +); + +LAYBASIC_PUBLIC gsi::Class &decl_layTechnologyComponent () { return technology_component_decl; } + +gsi::Class technology_decl ("Technology", + gsi::method ("name", &lay::Technology::name, + "@brief Gets the name of the technology" + ) + + gsi::method ("name=", &lay::Technology::set_name, gsi::arg ("name"), + "@brief Sets the name of the technology" + ) + + gsi::method ("base_path", &lay::Technology::base_path, + "@brief Gets the base path of the technology\n" + "\n" + "The base path is the effective path where files are read from if their " + "file path is a relative one. If the explicit path is set (see \\explicit_base_path=), it is\n" + "used. If not, the default path is used. The default path is the one from which\n" + "a technology file was imported. The explicit one is the one that is specified\n" + "explicitly with \\explicit_base_path=.\n" + ) + + gsi::method ("default_base_path", &lay::Technology::default_base_path, + "@brief Gets the default base path\n" + "\n" + "See \\base_path for details about the default base path.\n" + ) + + gsi::method ("default_base_path=", &lay::Technology::set_default_base_path, gsi::arg ("path"), + "@hide\n" // only for testing + ) + + gsi::method ("correct_path", &lay::Technology::correct_path, gsi::arg ("path"), + "@brief Makes a file path relative to the base path if one is specified\n" + "\n" + "This method turns an absolute path into one relative to the base path. " + "Only files below the base path will be made relative. Files above or beside " + "won't be made relative.\n" + "\n" + "See \\base_path for details about the default base path.\n" + ) + + gsi::method ("eff_path", &lay::Technology::build_effective_path, gsi::arg ("path"), + "@brief Makes a file path relative to the base path if one is specified\n" + "\n" + "This method will return the actual path for a file from the file's path. " + "If the input path is a relative one, it will be made absolute by using the " + "base path.\n" + "\n" + "See \\base_path for details about the default base path.\n" + ) + + gsi::method ("explicit_base_path", &lay::Technology::explicit_base_path, + "@brief Gets the explicit base path\n" + "\n" + "See \\base_path for details about the explicit base path.\n" + ) + + gsi::method ("explicit_base_path=", &lay::Technology::set_explicit_base_path, gsi::arg ("path"), + "@brief Sets the explicit base path\n" + "\n" + "See \\base_path for details about the explicit base path.\n" + ) + + gsi::method ("description", &lay::Technology::description, + "@brief Gets the description\n" + "\n" + "The technology description is shown to the user in technology selection dialogs and for " + "display purposes." + ) + + gsi::method ("description=", &lay::Technology::set_description, gsi::arg ("description"), + "@brief Sets the description\n" + ) + + gsi::method ("dbu", &lay::Technology::dbu, + "@brief Gets the default database unit\n" + "\n" + "The default database unit is the one used when creating a layout for example." + ) + + gsi::method ("dbu=", &lay::Technology::set_dbu, gsi::arg ("dbu"), + "@brief Sets the default database unit\n" + ) + + gsi::method ("layer_properties_file", &lay::Technology::layer_properties_file, + "@brief Gets the path of the layer properties file\n" + "\n" + "If empty, no layer properties file is associated with the technology. " + "If non-empty, this path will be corrected by the base path (see \\correct_path) and " + "this layer properties file will be loaded for layouts with this technology." + ) + + gsi::method ("layer_properties_file=", &lay::Technology::set_layer_properties_file, gsi::arg ("file"), + "@brief Sets the path of the layer properties file\n" + "\n" + "See \\layer_properties_file for details about this property." + ) + + gsi::method ("eff_layer_properties_file", &lay::Technology::eff_layer_properties_file, + "@brief Gets the effective path of the layer properties file\n" + ) + + gsi::method ("add_other_layers?", &lay::Technology::add_other_layers, + "@brief Gets the flag indicating whether to add other layers to the layer properties\n" + ) + + gsi::method ("add_other_layers=", &lay::Technology::set_add_other_layers, gsi::arg ("add"), + "@brief Sets the flag indicating whether to add other layers to the layer properties\n" + ) + + gsi::method ("load_layout_options", &lay::Technology::load_layout_options, + "@brief Gets the layout reader options\n" + "\n" + "This method returns the layout reader options that are used when reading layouts " + "with this technology.\n" + "\n" + "Change the reader options by modifying the object and using the setter to change it:\n" + "\n" + "@code\n" + "opt = tech.load_layout_options\n" + "opt.dxf_dbu = 2.5\n" + "tech.load_layout_options = opt\n" + "@/code\n" + ) + + gsi::method ("load_layout_options=", &lay::Technology::set_load_layout_options, gsi::arg ("options"), + "@brief Sets the layout reader options\n" + "\n" + "See \\load_layout_options for a description of this property.\n" + ) + + gsi::method ("save_layout_options", &lay::Technology::save_layout_options, + "@brief Gets the layout writer options\n" + "\n" + "This method returns the layout writer options that are used when writing layouts " + "with this technology.\n" + "\n" + "Change the reader options by modifying the object and using the setter to change it:\n" + "\n" + "@code\n" + "opt = tech.save_layout_options\n" + "opt.dbu = 0.01\n" + "tech.save_layout_options = opt\n" + "@/code\n" + ) + + gsi::method ("save_layout_options=", &lay::Technology::set_save_layout_options, gsi::arg ("options"), + "@brief Sets the layout writer options\n" + "\n" + "See \\save_layout_options for a description of this property.\n" + ) + + gsi::method ("load", &lay::Technology::load, gsi::arg ("file"), + "@brief Loads the technology definition from a file\n" + ) + + gsi::method ("load", &lay::Technology::save, gsi::arg ("file"), + "@brief Saves the technology definition to a file\n" + ) + + gsi::method ("technology_names", &technology_names, + "@brief Gets a list of technology names defined in the system\n" + ) + + gsi::method ("technology_by_name", &technology_by_name, gsi::arg ("name"), + "@brief Gets the technology object for a given name\n" + ) + + gsi::method ("has_technology?", &has_technology, gsi::arg ("name"), + "@brief Returns a value indicating whether there is a technology with this name\n" + ) + + gsi::method ("create_technology", &create_technology, gsi::arg ("name"), + "@brief Creates a new (empty) technology with the given name\n" + "\n" + "This method returns a reference to the new technology." + ) + + gsi::method ("remove_technology", &remove_technology, gsi::arg ("name"), + "@brief Removes the technology with the given name\n" + ) + + gsi::method ("technologies_to_xml", &technologies_to_xml, + "@brief Returns a XML representation of all technologies registered in the system\n" + "\n" + "\\technologies_from_xml can be used to restore the technology definitions. " + "This method is provided mainly as a substitute for the pre-0.25 way of accessing " + "technology data through the 'technology-data' configuration parameter. This method " + "will return the equivalent string." + ) + + gsi::method_ext ("to_xml", &technology_to_xml, + "@brief Returns a XML representation of this technolog\n" + "\n" + "\\technology_from_xml can be used to restore the technology definition." + ) + + gsi::method ("technologies_from_xml", &technologies_from_xml, gsi::arg ("xml"), + "@brief Loads the technologies from a XML representation\n" + "\n" + "See \\technologies_to_xml for details. This method is the corresponding setter." + ) + + gsi::method ("technology_from_xml", &technology_from_xml, gsi::arg ("xml"), + "@brief Loads the technology from a XML representation\n" + "\n" + "See \\technology_to_xml for details." + ) + + gsi::method_ext ("component_names", &get_component_names, + "@brief Gets the names of all components available for \\component" + ) + + gsi::method_ext ("component", &get_component, gsi::arg ("name"), + "@brief Gets the technology component with the given name\n" + "The names are unique system identifiers. For all names, use \\component_names." + ), + "@brief Represents a technology\n" + "\n" + "This class represents one technology from a set of technologies. The set of technologies " + "available in the system can be obtained with \\technology_names. Individual technology " + "definitions are returned with \\technology_by_name. Use \\create_technology to register " + "new technologies and \\remove_technology to delete technologies.\n" + "\n" + "The Technology class has been introduced in version 0.25.\n" +); + +} diff --git a/src/laybasic/layTechnology.h b/src/laybasic/layTechnology.h index 2393de430..82f4fd028 100644 --- a/src/laybasic/layTechnology.h +++ b/src/laybasic/layTechnology.h @@ -30,6 +30,7 @@ #include "tlString.h" #include "tlEvents.h" #include "tlXMLParser.h" +#include "tlTypeTraits.h" #include "dbStreamLayers.h" #include "dbLoadLayoutOptions.h" #include "dbSaveLayoutOptions.h" @@ -821,5 +822,16 @@ public: } +namespace tl +{ + /** + * @brief Type traits + */ + template <> struct type_traits : public type_traits { + typedef tl::false_tag has_default_constructor; + typedef tl::false_tag has_copy_constructor; + }; +} + #endif diff --git a/src/laybasic/laybasic.pro b/src/laybasic/laybasic.pro index 74fc3adb5..4c226c4e9 100644 --- a/src/laybasic/laybasic.pro +++ b/src/laybasic/laybasic.pro @@ -177,7 +177,8 @@ SOURCES = \ layLineStylePalette.cc \ layEditLineStylesForm.cc \ layEditLineStyleWidget.cc \ - layBackgroundAwareTreeStyle.cc + layBackgroundAwareTreeStyle.cc \ + gsiDeclLayTechnologies.cc HEADERS = \ gtf.h \ diff --git a/src/tl/tlSystemPaths.cc b/src/tl/tlSystemPaths.cc index e097b927b..d1847b853 100644 --- a/src/tl/tlSystemPaths.cc +++ b/src/tl/tlSystemPaths.cc @@ -110,32 +110,58 @@ split_path (const std::string &path, std::vector &pc) } } + +static std::vector s_klayout_path; +static bool s_klayout_path_set = false; + +void +set_klayout_path (const std::vector &path) +{ + s_klayout_path = path; + s_klayout_path_set = true; +} + +void +reset_klayout_path () +{ + s_klayout_path.clear (); + s_klayout_path_set = false; +} + std::vector get_klayout_path () { - std::vector klayout_path; + if (s_klayout_path_set) { - // generate the klayout path: the first component is always the appdata path - klayout_path.push_back (get_appdata_path ()); + return s_klayout_path; + + } else { + + std::vector klayout_path; + + // generate the klayout path: the first component is always the appdata path + klayout_path.push_back (get_appdata_path ()); #ifdef _WIN32 - wchar_t *env = _wgetenv (L"KLAYOUT_PATH"); - if (env) { - split_path (tl::to_string (QString ((const QChar *) env)), klayout_path); - } else { - get_other_system_paths (klayout_path); - klayout_path.push_back (get_inst_path ()); - } + wchar_t *env = _wgetenv (L"KLAYOUT_PATH"); + if (env) { + split_path (tl::to_string (QString ((const QChar *) env)), klayout_path); + } else { + get_other_system_paths (klayout_path); + klayout_path.push_back (get_inst_path ()); + } #else - char *env = getenv ("KLAYOUT_PATH"); - if (env) { - split_path (tl::system_to_string (env), klayout_path); - } else { - get_other_system_paths (klayout_path); - klayout_path.push_back (get_inst_path ()); - } + char *env = getenv ("KLAYOUT_PATH"); + if (env) { + split_path (tl::system_to_string (env), klayout_path); + } else { + get_other_system_paths (klayout_path); + klayout_path.push_back (get_inst_path ()); + } #endif - return klayout_path; + return klayout_path; + + } } } diff --git a/src/tl/tlSystemPaths.h b/src/tl/tlSystemPaths.h index 7fa982689..16187c8a3 100644 --- a/src/tl/tlSystemPaths.h +++ b/src/tl/tlSystemPaths.h @@ -52,6 +52,20 @@ TL_PUBLIC std::string get_inst_path (); */ TL_PUBLIC std::vector get_klayout_path (); +/** + * @brief Sets the KLayout path + * This method is mainly used for test purposes. It will force the application + * is use a specific KLAYOUT_PATH. Use reset_klayout_path to restore the + * default behavior. + */ +TL_PUBLIC void set_klayout_path (const std::vector &path); + +/** + * @brief Resets the KLayout path + * See "set_klayout_path" for a description. + */ +TL_PUBLIC void reset_klayout_path (); + } #endif diff --git a/src/unit_tests/pya.cc b/src/unit_tests/pya.cc index 9e2dcfa79..f79c88b70 100644 --- a/src/unit_tests/pya.cc +++ b/src/unit_tests/pya.cc @@ -101,7 +101,7 @@ void run_pythontest (ut::TestBase *_this, const std::string &fn) } #define PYTHONTEST(n, file) \ - TEST(2_##n) { run_pythontest(_this, file); } + TEST(n) { run_pythontest(_this, file); } PYTHONTEST (dbLayoutTest, "dbLayoutTest.py") PYTHONTEST (dbRegionTest, "dbRegionTest.py") diff --git a/src/unit_tests/rba.cc b/src/unit_tests/rba.cc index e9deda6d0..502c695d1 100644 --- a/src/unit_tests/rba.cc +++ b/src/unit_tests/rba.cc @@ -85,7 +85,7 @@ void run_rubytest (ut::TestBase * /*_this*/, const std::string &fn) } #define RUBYTEST(n, file) \ - TEST(2_##n) { run_rubytest(_this, file); } + TEST(n) { run_rubytest(_this, file); } RUBYTEST (antTest, "antTest.rb") RUBYTEST (dbBooleanTest, "dbBooleanTest.rb") @@ -123,6 +123,7 @@ RUBYTEST (layLayoutView, "layLayoutView.rb") RUBYTEST (layMarkers, "layMarkers.rb") RUBYTEST (layMenuTest, "layMenuTest.rb") RUBYTEST (laySession, "laySession.rb") +RUBYTEST (layTechnologies, "layTechnologies.rb") #if defined(HAVE_QTBINDINGS) RUBYTEST (qtbinding, "qtbinding.rb") #endif diff --git a/src/ut/utMain.cc b/src/ut/utMain.cc index 8a563e177..310d6a0ab 100644 --- a/src/ut/utMain.cc +++ b/src/ut/utMain.cc @@ -26,6 +26,7 @@ #include "pya.h" #include "tlStaticObjects.h" #include "tlTimer.h" +#include "tlSystemPaths.h" #include "layApplication.h" #include "gsiExpression.h" #include "gsiExternalMain.h" @@ -762,6 +763,9 @@ main_cont (int argc, char **argv) pya::PythonInterpreter::initialize (); gsi::initialize_external (); + // No side effects + tl::set_klayout_path (std::vector ()); + int ac = 2; static char av0[] = "unit_test"; static char av1[] = "-z"; // don't show main window diff --git a/testdata/ruby/layTechnologies.rb b/testdata/ruby/layTechnologies.rb new file mode 100644 index 000000000..2c7c52e07 --- /dev/null +++ b/testdata/ruby/layTechnologies.rb @@ -0,0 +1,106 @@ + +$:.push(File::dirname($0)) + +load("test_prologue.rb") + +class LAYTechnologies_TestClass < TestBase + + def test_1 + + RBA::Technology::technologies_from_xml(< + + + + + MINE + + +END + assert_equal(RBA::Technology::technology_names.inspect, '["", "MINE"]') + + s = RBA::Technology::technologies_to_xml + RBA::Technology::technologies_from_xml("") + assert_equal(RBA::Technology::technology_names.inspect, '[""]') + RBA::Technology::technologies_from_xml(s) + assert_equal(RBA::Technology::technology_names.inspect, '["", "MINE"]') + + tech = RBA::Technology::technology_by_name("MINE") + assert_equal(tech.name, "MINE") + tech.name = "MINE2" + assert_equal(tech.name, "MINE2") + + assert_equal(RBA::Technology::technology_names.inspect, '["", "MINE2"]') + + assert_equal(RBA::Technology::has_technology?("MINE"), false) + assert_equal(RBA::Technology::has_technology?("MINE2"), true) + tech = RBA::Technology::technology_by_name("MINE") + assert_equal(tech != nil, true) + assert_equal(tech.name, "") + tech2 = RBA::Technology::technology_by_name("MINE2") + assert_equal(tech != nil, true) + + RBA::Technology::remove_technology("X") + assert_equal(RBA::Technology::technology_names.inspect, '["", "MINE2"]') + RBA::Technology::remove_technology("MINE2") + assert_equal(RBA::Technology::technology_names.inspect, '[""]') + + end + + def test_2 + + tech = RBA::Technology::technology_from_xml(< + X + +END + assert_equal(tech.name, "X") + + tech.name = "Y" + assert_equal(tech.name, "Y") + + tech.description = "A big Y" + assert_equal(tech.description, "A big Y") + + tech.dbu = 5.0 + assert_equal(tech.dbu, 5.0) + + tech.default_base_path = "/default/path" + assert_equal(tech.default_base_path, "/default/path") + assert_equal(tech.base_path, "/default/path") + assert_equal(tech.correct_path("/default/path/myfile.xml"), "myfile.xml") + assert_equal(tech.eff_path("myfile.xml"), "/default/path/myfile.xml") + + tech.explicit_base_path = "/basic/path" + assert_equal(tech.explicit_base_path, "/basic/path") + assert_equal(tech.base_path, "/basic/path") + assert_equal(tech.correct_path("/basic/path/myfile.xml"), "myfile.xml") + assert_equal(tech.eff_path("myfile.xml"), "/basic/path/myfile.xml") + + tech.layer_properties_file = "x.lyp" + assert_equal(tech.layer_properties_file, "x.lyp") + assert_equal(tech.eff_layer_properties_file, "/basic/path/x.lyp") + + tech.add_other_layers = true + assert_equal(tech.add_other_layers?, true) + tech.add_other_layers = false + assert_equal(tech.add_other_layers?, false) + + opt = tech.load_layout_options + opt.dxf_dbu = 2.5 + tech.load_layout_options = opt + assert_equal(tech.load_layout_options.dxf_dbu, 2.5) + opt = tech.save_layout_options + opt.dbu = 0.125 + tech.save_layout_options = opt + assert_equal(tech.save_layout_options.dbu, 0.125) + + assert_equal(tech.component_names.size > 0, true) + assert_equal(tech.component_names.find("connectivity") != nil, true) + assert_equal(tech.component("connectivity").class.to_s, "RBA::NetTracerTechnology") + + end + +end + +load("test_epilogue.rb")