/* KLayout Layout Viewer Copyright (C) 2006-2025 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 */ #ifndef HDR_dbLEFDEFImporter #define HDR_dbLEFDEFImporter #include "dbPluginCommon.h" #include "dbLayout.h" #include "dbReader.h" #include "dbCommonReader.h" #include "dbStreamLayers.h" #include "tlStream.h" #include "tlVariant.h" #include #include #include namespace tl { class AbsoluteProgress; } namespace db { class LEFDEFReaderState; class LEFDEFImporter; struct MacroDesc; /** * @brief Correct a path relative to the stream and technology */ DB_PLUGIN_PUBLIC std::vector correct_path (const std::string &fn, const db::Layout &layout, const std::string &base_path, bool glob); /** * @brief Convers a string to a MASKSHIFT index list */ std::vector string2masks (const std::string &s); /** * @brief Generic base class of DXF reader exceptions */ class DB_PLUGIN_PUBLIC LEFDEFReaderException : public db::ReaderException { public: LEFDEFReaderException (const std::string &msg, int line, const std::string &cell, const std::string &fn) : db::ReaderException (line >= 0 ? tl::sprintf (tl::to_string (tr ("%s (line=%d, cell=%s, file=%s)")), msg.c_str (), line, cell, fn) : tl::sprintf (tl::to_string (tr ("%s (file=%s)")), msg.c_str (), fn)) { } }; template const Value &per_mask_value (const std::map &map, const Value &def, unsigned int mask) { typename std::map::const_iterator i = map.find (mask); return i == map.end () ? def : i->second; } inline bool per_mask_value_is_null (int dt) { return dt < 0; } inline bool per_mask_value_is_null (const std::string &pfx) { return pfx.empty (); } template void set_per_mask_value (std::map &map, unsigned int mask, const Value &value) { if (per_mask_value_is_null (value)) { map.erase (mask); } else { map [mask] = value; } } template void get_max_mask_number (unsigned int &mm, const std::map &map) { if (! map.empty ()) { mm = std::max (mm, (--map.end ())->first); } } /** * @brief The LEF/DEF importer technology component * * This component provides technology specific information for the LEF/DEF importer. */ class DB_PLUGIN_PUBLIC LEFDEFReaderOptions : public db::FormatSpecificReaderOptions { public: LEFDEFReaderOptions (); LEFDEFReaderOptions (const LEFDEFReaderOptions &d); LEFDEFReaderOptions &operator= (const LEFDEFReaderOptions &d); db::FormatSpecificReaderOptions *clone () const; virtual const std::string &format_name () const; bool paths_relative_to_cwd () const { return m_paths_relative_to_cwd; } void set_paths_relative_to_cwd (bool f) { m_paths_relative_to_cwd = f; } bool read_all_layers () const { return m_read_all_layers; } void set_read_all_layers (bool a) { m_read_all_layers = a; } const db::LayerMap &layer_map () const { return m_layer_map; } db::LayerMap &layer_map () { return m_layer_map; } void set_layer_map (const db::LayerMap &lm) { m_layer_map = lm; } double dbu () const { return m_dbu; } void set_dbu (double dbu) { m_dbu = dbu; } bool produce_net_names () const { return m_produce_net_names; } void set_produce_net_names (bool f) { m_produce_net_names = f; } const tl::Variant &net_property_name () const { return m_net_property_name; } void set_net_property_name (const tl::Variant &s) { m_net_property_name = s; } bool produce_inst_names () const { return m_produce_inst_names; } void set_produce_inst_names (bool f) { m_produce_inst_names = f; } const tl::Variant &inst_property_name () const { return m_inst_property_name; } void set_inst_property_name (const tl::Variant &s) { m_inst_property_name = s; } bool produce_pin_names () const { return m_produce_pin_names; } void set_produce_pin_names (bool f) { m_produce_pin_names = f; } const tl::Variant &pin_property_name () const { return m_pin_property_name; } void set_pin_property_name (const tl::Variant &s) { m_pin_property_name = s; } bool produce_cell_outlines () const { return m_produce_cell_outlines; } void set_produce_cell_outlines (bool f) { m_produce_cell_outlines = f; } const std::string &cell_outline_layer () const { return m_cell_outline_layer; } void set_cell_outline_layer (const std::string &s) { m_cell_outline_layer = s; } bool produce_placement_blockages () const { return m_produce_placement_blockages; } void set_produce_placement_blockages (bool f) { m_produce_placement_blockages = f; } const std::string &placement_blockage_layer () const { return m_placement_blockage_layer; } void set_placement_blockage_layer (const std::string &s) { m_placement_blockage_layer = s; } bool produce_regions () const { return m_produce_regions; } void set_produce_regions (bool f) { m_produce_regions = f; } const std::string ®ion_layer () const { return m_region_layer; } void set_region_layer (const std::string &s) { m_region_layer = s; } bool produce_via_geometry () const { return m_produce_via_geometry; } void set_produce_via_geometry (bool f) { m_produce_via_geometry = f; } const std::string &via_geometry_suffix () const { return m_via_geometry_suffix; } void set_via_geometry_suffix (const std::string &s) { m_via_geometry_suffix = s; } int via_geometry_datatype () const { return m_via_geometry_datatype; } void set_via_geometry_datatype (int s) { m_via_geometry_datatype = s; } void set_via_geometry_suffix_str (const std::string &s); std::string via_geometry_suffix_str () const; void set_via_geometry_datatype_str (const std::string &s); std::string via_geometry_datatype_str () const; void clear_via_geometry_suffixes_per_mask () { m_via_geometry_suffixes.clear (); } void clear_via_geometry_datatypes_per_mask () { m_via_geometry_datatypes.clear (); } const std::string &via_geometry_suffix_per_mask (unsigned int mask) const { return per_mask_value (m_via_geometry_suffixes, m_via_geometry_suffix, mask); } void set_via_geometry_suffix_per_mask (unsigned int mask, const std::string &s) { set_per_mask_value (m_via_geometry_suffixes, mask, s); } int via_geometry_datatype_per_mask (unsigned int mask) const { return per_mask_value (m_via_geometry_datatypes, m_via_geometry_datatype, mask); } void set_via_geometry_datatype_per_mask (unsigned int mask, int s) { set_per_mask_value (m_via_geometry_datatypes, mask, s); } const std::string &via_cellname_prefix () const { return m_via_cellname_prefix; } void set_via_cellname_prefix (const std::string &s) { m_via_cellname_prefix = s; } bool produce_pins () const { return m_produce_pins; } void set_produce_pins (bool f) { m_produce_pins = f; } const std::string &pins_suffix () const { return m_pins_suffix; } void set_pins_suffix (const std::string &s) { m_pins_suffix = s; } int pins_datatype () const { return m_pins_datatype; } void set_pins_datatype (int s) { m_pins_datatype = s; } void set_pins_suffix_str (const std::string &s); std::string pins_suffix_str () const; void set_pins_datatype_str (const std::string &s); std::string pins_datatype_str () const; void clear_pins_suffixes_per_mask () { m_pins_suffixes.clear (); } void clear_pins_datatypes_per_mask () { m_pins_datatypes.clear (); } const std::string &pins_suffix_per_mask (unsigned int mask) const { return per_mask_value (m_pins_suffixes, m_pins_suffix, mask); } void set_pins_suffix_per_mask (unsigned int mask, const std::string &s) { set_per_mask_value (m_pins_suffixes, mask, s); } int pins_datatype_per_mask (unsigned int mask) const { return per_mask_value (m_pins_datatypes, m_pins_datatype, mask); } void set_pins_datatype_per_mask (unsigned int mask, int s) { set_per_mask_value (m_pins_datatypes, mask, s); } bool produce_lef_pins () const { return m_produce_lef_pins; } void set_produce_lef_pins (bool f) { m_produce_lef_pins = f; } const std::string &lef_pins_suffix () const { return m_lef_pins_suffix; } void set_lef_pins_suffix (const std::string &s) { m_lef_pins_suffix = s; } int lef_pins_datatype () const { return m_lef_pins_datatype; } void set_lef_pins_datatype (int s) { m_lef_pins_datatype = s; } void set_lef_pins_suffix_str (const std::string &s); std::string lef_pins_suffix_str () const; void set_lef_pins_datatype_str (const std::string &s); std::string lef_pins_datatype_str () const; void clear_lef_pins_suffixes_per_mask () { m_lef_pins_suffixes.clear (); } void clear_lef_pins_datatypes_per_mask () { m_lef_pins_datatypes.clear (); } const std::string &lef_pins_suffix_per_mask (unsigned int mask) const { return per_mask_value (m_lef_pins_suffixes, m_lef_pins_suffix, mask); } void set_lef_pins_suffix_per_mask (unsigned int mask, const std::string &s) { set_per_mask_value (m_lef_pins_suffixes, mask, s); } int lef_pins_datatype_per_mask (unsigned int mask) const { return per_mask_value (m_lef_pins_datatypes, m_lef_pins_datatype, mask); } void set_lef_pins_datatype_per_mask (unsigned int mask, int s) { set_per_mask_value (m_lef_pins_datatypes, mask, s); } bool produce_fills () const { return m_produce_fills; } void set_produce_fills (bool f) { m_produce_fills = f; } const std::string &fills_suffix () const { return m_fills_suffix; } void set_fills_suffix (const std::string &s) { m_fills_suffix = s; } int fills_datatype () const { return m_fills_datatype; } void set_fills_datatype (int s) { m_fills_datatype = s; } void set_fills_suffix_str (const std::string &s); std::string fills_suffix_str () const; void set_fills_datatype_str (const std::string &s); std::string fills_datatype_str () const; void clear_fills_suffixes_per_mask () { m_fills_suffixes.clear (); } void clear_fills_datatypes_per_mask () { m_fills_datatypes.clear (); } const std::string &fills_suffix_per_mask (unsigned int mask) const { return per_mask_value (m_fills_suffixes, m_fills_suffix, mask); } void set_fills_suffix_per_mask (unsigned int mask, const std::string &s) { set_per_mask_value (m_fills_suffixes, mask, s); } int fills_datatype_per_mask (unsigned int mask) const { return per_mask_value (m_fills_datatypes, m_fills_datatype, mask); } void set_fills_datatype_per_mask (unsigned int mask, int s) { set_per_mask_value (m_fills_datatypes, mask, s); } bool produce_obstructions () const { return m_produce_obstructions; } void set_produce_obstructions (bool f) { m_produce_obstructions = f; } const std::string &obstructions_suffix () const { return m_obstructions_suffix; } void set_obstructions_suffix (const std::string &s) { m_obstructions_suffix = s; } int obstructions_datatype () const { return m_obstructions_datatype; } void set_obstructions_datatype (int s) { m_obstructions_datatype = s; } bool produce_blockages () const { return m_produce_blockages; } void set_produce_blockages (bool f) { m_produce_blockages = f; } const std::string &blockages_suffix () const { return m_blockages_suffix; } void set_blockages_suffix (const std::string &s) { m_blockages_suffix = s; } int blockages_datatype () const { return m_blockages_datatype; } void set_blockages_datatype (int s) { m_blockages_datatype = s; } bool produce_labels () const { return m_produce_labels; } void set_produce_labels (bool f) { m_produce_labels = f; } const std::string &labels_suffix () const { return m_labels_suffix; } void set_labels_suffix (const std::string &s) { m_labels_suffix = s; } int labels_datatype () const { return m_labels_datatype; } void set_labels_datatype (int s) { m_labels_datatype = s; } bool produce_lef_labels () const { return m_produce_lef_labels; } void set_produce_lef_labels (bool f) { m_produce_lef_labels = f; } const std::string &lef_labels_suffix () const { return m_lef_labels_suffix; } void set_lef_labels_suffix (const std::string &s) { m_lef_labels_suffix = s; } int lef_labels_datatype () const { return m_lef_labels_datatype; } void set_lef_labels_datatype (int s) { m_lef_labels_datatype = s; } bool produce_routing () const { return m_produce_routing; } void set_produce_routing (bool f) { m_produce_routing = f; } const std::string &routing_suffix () const { return m_routing_suffix; } void set_routing_suffix (const std::string &s) { m_routing_suffix = s; } int routing_datatype () const { return m_routing_datatype; } void set_routing_datatype (int s) { m_routing_datatype = s; } void set_routing_suffix_str (const std::string &s); std::string routing_suffix_str () const; void set_routing_datatype_str (const std::string &s); std::string routing_datatype_str () const; void clear_routing_suffixes_per_mask () { m_routing_suffixes.clear (); } void clear_routing_datatypes_per_mask () { m_routing_datatypes.clear (); } const std::string &routing_suffix_per_mask (unsigned int mask) const { return per_mask_value (m_routing_suffixes, m_routing_suffix, mask); } void set_routing_suffix_per_mask (unsigned int mask, const std::string &s) { set_per_mask_value (m_routing_suffixes, mask, s); } int routing_datatype_per_mask (unsigned int mask) const { return per_mask_value (m_routing_datatypes, m_routing_datatype, mask); } void set_routing_datatype_per_mask (unsigned int mask, int s) { set_per_mask_value (m_routing_datatypes, mask, s); } bool produce_special_routing () const { return m_produce_special_routing; } void set_produce_special_routing (bool f) { m_produce_special_routing = f; } const std::string &special_routing_suffix () const { return m_special_routing_suffix; } void set_special_routing_suffix (const std::string &s) { m_special_routing_suffix = s; } int special_routing_datatype () const { return m_special_routing_datatype; } void set_special_routing_datatype (int s) { m_special_routing_datatype = s; } void set_special_routing_suffix_str (const std::string &s); std::string special_routing_suffix_str () const; void set_special_routing_datatype_str (const std::string &s); std::string special_routing_datatype_str () const; void clear_special_routing_suffixes_per_mask () { m_special_routing_suffixes.clear (); } void clear_special_routing_datatypes_per_mask () { m_special_routing_datatypes.clear (); } const std::string &special_routing_suffix_per_mask (unsigned int mask) const { return per_mask_value (m_special_routing_suffixes, m_special_routing_suffix, mask); } void set_special_routing_suffix_per_mask (unsigned int mask, const std::string &s) { set_per_mask_value (m_special_routing_suffixes, mask, s); } int special_routing_datatype_per_mask (unsigned int mask) const { return per_mask_value (m_special_routing_datatypes, m_special_routing_datatype, mask); } void set_special_routing_datatype_per_mask (unsigned int mask, int s) { set_per_mask_value (m_special_routing_datatypes, mask, s); } unsigned int max_mask_number () const { unsigned int mm = 0; get_max_mask_number (mm, m_via_geometry_suffixes); get_max_mask_number (mm, m_via_geometry_datatypes); get_max_mask_number (mm, m_pins_suffixes); get_max_mask_number (mm, m_pins_datatypes); get_max_mask_number (mm, m_lef_pins_suffixes); get_max_mask_number (mm, m_lef_pins_datatypes); get_max_mask_number (mm, m_fills_suffixes); get_max_mask_number (mm, m_fills_datatypes); get_max_mask_number (mm, m_routing_suffixes); get_max_mask_number (mm, m_routing_datatypes); get_max_mask_number (mm, m_special_routing_suffixes); get_max_mask_number (mm, m_special_routing_datatypes); return mm; } void clear_lef_files () { m_lef_files.clear (); } void push_lef_file (const std::string &l) { m_lef_files.push_back (l); } std::vector::const_iterator begin_lef_files () const { return m_lef_files.begin (); } std::vector::const_iterator end_lef_files () const { return m_lef_files.end (); } std::vector lef_files () const { return m_lef_files; } void set_lef_files (const std::vector &lf) { m_lef_files = lf; } bool read_lef_with_def () const { return m_read_lef_with_def; } void set_read_lef_with_def (bool f) { m_read_lef_with_def = f; } bool separate_groups () const { return m_separate_groups; } void set_separate_groups (bool f) { m_separate_groups = f; } bool joined_paths () const { return m_joined_paths; } void set_joined_paths (bool f) { m_joined_paths = f; } const std::string &map_file () const { return m_map_file; } void set_map_file (const std::string &f) { m_map_file = f; } /** * @brief Specify the LEF macro resolution strategy when reading DEF files * Values are: * 0: propduce LEF geometry unless a FOREIGN cell is specified (default) * 1: produce LEF geometry always and ignore FOREIGN * 2: produce a placeholder cell always (even if FOREIGN isn't given) */ unsigned int macro_resolution_mode () const { return m_macro_resolution_mode; } void set_macro_resolution_mode (unsigned int m) { m_macro_resolution_mode = m; } void set_macro_layouts (const std::vector &layouts) { for (std::vector::const_iterator l = layouts.begin (); l != layouts.end (); ++l) { m_macro_layouts.push_back (*l); } } std::vector macro_layouts () const { std::vector res; for (tl::weak_collection::const_iterator m = m_macro_layouts.begin (); m != m_macro_layouts.end (); ++m) { if (m.operator-> ()) { res.push_back (const_cast (m.operator-> ())); } } return res; } void clear_macro_layout_files () { m_macro_layout_files.clear (); } void push_macro_layout_file (const std::string &l) { m_macro_layout_files.push_back (l); } std::vector::const_iterator begin_macro_layout_files () const { return m_macro_layout_files.begin (); } std::vector::const_iterator end_macro_layout_files () const { return m_macro_layout_files.end (); } std::vector macro_layout_files () const { return m_macro_layout_files; } void set_macro_layout_files (const std::vector &lf) { m_macro_layout_files = lf; } private: bool m_read_all_layers; db::LayerMap m_layer_map; double m_dbu; bool m_produce_net_names; tl::Variant m_net_property_name; bool m_produce_inst_names; tl::Variant m_inst_property_name; bool m_produce_pin_names; tl::Variant m_pin_property_name; bool m_produce_cell_outlines; std::string m_cell_outline_layer; bool m_produce_placement_blockages; std::string m_placement_blockage_layer; bool m_produce_regions; std::string m_region_layer; bool m_produce_via_geometry; std::string m_via_geometry_suffix; int m_via_geometry_datatype; std::map m_via_geometry_suffixes; std::map m_via_geometry_datatypes; std::string m_via_cellname_prefix; bool m_produce_pins; std::string m_pins_suffix; int m_pins_datatype; std::map m_pins_suffixes; std::map m_pins_datatypes; bool m_produce_lef_pins; std::string m_lef_pins_suffix; int m_lef_pins_datatype; std::map m_lef_pins_suffixes; std::map m_lef_pins_datatypes; bool m_produce_fills; std::string m_fills_suffix; int m_fills_datatype; std::map m_fills_suffixes; std::map m_fills_datatypes; bool m_produce_obstructions; std::string m_obstructions_suffix; int m_obstructions_datatype; bool m_produce_blockages; std::string m_blockages_suffix; int m_blockages_datatype; bool m_produce_labels; std::string m_labels_suffix; int m_labels_datatype; bool m_produce_lef_labels; std::string m_lef_labels_suffix; int m_lef_labels_datatype; bool m_produce_routing; std::string m_routing_suffix; int m_routing_datatype; std::map m_routing_suffixes; std::map m_routing_datatypes; bool m_produce_special_routing; std::string m_special_routing_suffix; int m_special_routing_datatype; std::map m_special_routing_suffixes; std::map m_special_routing_datatypes; bool m_separate_groups; bool m_joined_paths; std::string m_map_file; unsigned int m_macro_resolution_mode; bool m_read_lef_with_def; std::vector m_lef_files; tl::weak_collection m_macro_layouts; std::vector m_macro_layout_files; bool m_paths_relative_to_cwd; }; /** * @brief Defines the layer purposes provided so far */ enum LayerPurpose { None = 0, Routing, // from DEF only Pins, // from DEF Fills, // from DEF FillsOPC, // from DEF SpecialRouting, // from DEF only LEFPins, // from LEF ViaGeometry, // from LEF+DEF Label, // from DEF LEFLabel, // from LEF Obstructions, // from LEF only Outline, // from LEF+DEF Blockage, // from DEF only PlacementBlockage, // from DEF only Regions, // from DEF only RegionsNone, // from DEF only RegionsFence, // from DEF only RegionsGuide, // from DEF only All // from DEF only }; /** * @brief A structure holding the layer details like purpose, mask and via size */ struct LayerDetailsKey { LayerDetailsKey () : purpose (Routing), mask (0) { } LayerDetailsKey (LayerPurpose _purpose, unsigned int _mask = 0, const db::DVector &_via_size = db::DVector ()) : purpose (_purpose), mask (_mask), via_size (_via_size) { // normalize the via size such that x is smaller than y size (issue-1065) if (via_size.y () < via_size.x ()) { via_size = db::DVector (via_size.y (), via_size.x ()); } } bool operator< (const LayerDetailsKey &other) const { if (purpose != other.purpose) { return purpose < other.purpose; } if (mask != other.mask) { return mask < other.mask; } return via_size.less (other.via_size); } bool operator== (const LayerDetailsKey &other) const { if (purpose != other.purpose) { return false; } if (mask != other.mask) { return false; } return via_size.equal (other.via_size); } LayerPurpose purpose; unsigned int mask; db::DVector via_size; }; /** * @brief An interface for resolving the number of masks from a layer name */ class DB_PLUGIN_PUBLIC LEFDEFNumberOfMasks { public: LEFDEFNumberOfMasks () { } virtual ~LEFDEFNumberOfMasks () { } virtual unsigned int number_of_masks (const std::string &layer_name) const = 0; }; /** * @brief Provides a via generator base class */ class DB_PLUGIN_PUBLIC LEFDEFLayoutGenerator { public: LEFDEFLayoutGenerator () { } virtual ~LEFDEFLayoutGenerator () { } virtual void create_cell (LEFDEFReaderState &reader, db::Layout &layout, db::Cell &cell, const std::vector *maskshift_layers, const std::vector &masks, const LEFDEFNumberOfMasks *nm) = 0; virtual std::vector maskshift_layers () const = 0; virtual bool is_fixedmask () const = 0; }; /** * @brief Provides a via generator implementation for rule-based vias */ class DB_PLUGIN_PUBLIC RuleBasedViaGenerator : public LEFDEFLayoutGenerator { public: RuleBasedViaGenerator (); virtual void create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, const std::vector *maskshift_layers, const std::vector &masks, const LEFDEFNumberOfMasks *nm); virtual std::vector maskshift_layers () const { std::vector msl; msl.push_back (m_bottom_layer); msl.push_back (m_cut_layer); msl.push_back (m_top_layer); return msl; } virtual bool is_fixedmask () const { return false; } void set_cutsize (const db::Vector &cutsize) { m_cutsize = cutsize; } void set_cutspacing (const db::Vector &cutspacing) { m_cutspacing = cutspacing; } void set_offset (const db::Point &offset) { m_offset = offset; } void set_be (const db::Vector &be) { m_be = be; } void set_te (const db::Vector &te) { m_te = te; } void set_bo (const db::Vector &bo) { m_bo = bo; } void set_to (const db::Vector &to) { m_to = to; } void set_rows (int rows) { m_rows = rows; } void set_columns (int columns) { m_columns = columns; } void set_pattern (const std::string &pattern) { m_pattern = pattern; } void set_bottom_layer (const std::string &ln) { m_bottom_layer = ln; } void set_cut_layer (const std::string &ln) { m_cut_layer = ln; } void set_top_layer (const std::string &ln) { m_top_layer = ln; } void set_bottom_mask (unsigned int m) { m_bottom_mask = m; } void set_cut_mask (unsigned int m) { m_cut_mask = m; } void set_top_mask (unsigned int m) { m_top_mask = m; } private: std::string m_bottom_layer, m_cut_layer, m_top_layer; unsigned int m_bottom_mask, m_cut_mask, m_top_mask; db::Vector m_cutsize, m_cutspacing; db::Vector m_be, m_te; db::Vector m_bo, m_to; db::Point m_offset; int m_rows, m_columns; std::string m_pattern; }; /** * @brief Provides a geometry-based via generator implementation */ class DB_PLUGIN_PUBLIC GeometryBasedLayoutGenerator : public LEFDEFLayoutGenerator { public: GeometryBasedLayoutGenerator (); virtual void create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, const std::vector *maskshift_layers, const std::vector &masks, const LEFDEFNumberOfMasks *num_cut_masks); virtual std::vector maskshift_layers () const { return m_maskshift_layers; } virtual bool is_fixedmask () const { return m_fixedmask; } void add_polygon (const std::string &ln, LayerPurpose purpose, const db::Polygon &poly, unsigned int mask, properties_id_type prop_id, const DVector &via_size = db::DVector ()); void add_box (const std::string &ln, LayerPurpose purpose, const db::Box &box, unsigned int mask, properties_id_type prop_id, const DVector &via_size = db::DVector ()); void add_path (const std::string &ln, LayerPurpose purpose, const db::Path &path, unsigned int mask, properties_id_type prop_id, const DVector &via_size = db::DVector ()); void add_via (const std::string &vn, const db::Trans &trans, unsigned int bottom_mask, unsigned int cut_mask, unsigned int top_mask); void add_text (const std::string &ln, LayerPurpose purpose, const db::Text &text, unsigned int mask, db::properties_id_type prop_id); void set_maskshift_layers (const std::vector &ln) { m_maskshift_layers = ln; } void set_maskshift_layer (unsigned int l, const std::string &s) { if (m_maskshift_layers.size () <= size_t (l)) { m_maskshift_layers.resize (l + 1, std::string ()); } m_maskshift_layers[l] = s; } void set_fixedmask (bool f) { m_fixedmask = f; } void subtract_overlap_from_outline (const std::set &overlap_layers); private: struct Via { Via () : bottom_mask (0), cut_mask (0), top_mask (0) { } std::string name; std::string nondefaultrule; unsigned int bottom_mask, cut_mask, top_mask; db::Trans trans; }; std::map , db::Shapes> m_shapes; std::list m_vias; std::vector m_maskshift_layers; bool m_fixedmask; unsigned int get_maskshift (const std::string &ln, const std::vector *maskshift_layers, const std::vector &masks); unsigned int mask_for (const std::string &ln, unsigned int m, unsigned int mshift, const LEFDEFNumberOfMasks *nm) const; unsigned int combine_maskshifts (const std::string &ln, unsigned int mshift1, unsigned int mshift2, const LEFDEFNumberOfMasks *nm) const; }; /** * @brief Layer handler delegate * * This class will handle the creation and management of layers in the LEF/DEF reader context */ class DB_PLUGIN_PUBLIC LEFDEFReaderState : public db::CommonReaderBase { public: /** * @brief Constructor */ LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout, const std::string &base_path = std::string ()); /** * @brief Destructor */ ~LEFDEFReaderState (); /** * @brief Attaches to or detaches from an importer */ void attach_reader (LEFDEFImporter *importer) { mp_importer = importer; } /** * @brief Reads the given map file * * Usually this file is read by the constructor. This method is provided for test purposes. * The filename can be a list of files, separated by "+" or ",". They are loaded together into * the same map like they were concatenated. */ void read_map_file (const std::string &filename, db::Layout &layout, const std::string &base_path); /** * @brief Gets the layer map */ const db::LayerMap &layer_map () const { return m_layer_map; } /** * @brief Create a new layer or return the index of the given layer */ std::set open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask, const DVector &via_size = db::DVector ()); /** * @brief Create a new layer or return the index of the given layer */ template std::set open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask, const Shape &via_shape) { db::Box via_box = db::box_convert () (via_shape); return open_layer (layout, name, purpose, mask, db::DVector (via_box.width () * layout.dbu (), via_box.height () * layout.dbu ())); } /** * @brief Registers a layer (assign a new default layer number) */ void register_layer (const std::string &l); /** * @brief Finish, i.e. assign GDS layer numbers to the layers */ void finish (db::Layout &layout); /** * @brief Registers a via generator for the via with the given name * * The generator is capable of creating a via for a specific mask configuration */ void register_via_cell (const std::string &vn, const std::string &nondefaultrule, LEFDEFLayoutGenerator *generator); /** * @brief Gets the via cell for the given via name or 0 if no such via is registered */ db::Cell *via_cell (const std::string &vn, const std::string &nondefaultrule, Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm); /** * @brief Gets the via generator for a given via name or 0 if there is no such generator */ LEFDEFLayoutGenerator *via_generator (const std::string &vn, const std::string &nondefaultrule); /** * @brief Registers a macro generator for the macro with the given name * * The generator is capable of creating a macro for a specific mask configuration */ void register_macro_cell (const std::string &mn, LEFDEFLayoutGenerator *generator); /** * @brief Gets the macro cell for the given macro name or 0 if no such macro is registered */ std::pair macro_cell (const std::string &mn, Layout &layout, const std::vector &maskshift_layers, const std::vector &masks, const MacroDesc ¯o_desc, const LEFDEFNumberOfMasks *nm); /** * @brief Gets the macro generator for a given macro name or 0 if there is no such generator */ LEFDEFLayoutGenerator *macro_generator (const std::string &mn); /** * @brief Get the technology component pointer */ const LEFDEFReaderOptions *tech_comp () const { return mp_tech_comp; } /** * @brief Gets a map of foreign cells vs. name */ const std::map &foreign_cells () const { return m_foreign_cells; } /** * @brief Issues an error */ void error (const std::string &msg); /** * @brief Issues a warning */ void warn (const std::string &msg, int warn_level = 1); protected: virtual void common_reader_error (const std::string &msg) { error (msg); } virtual void common_reader_warn (const std::string &msg, int warn_level) { warn (msg, warn_level); } private: /** * @brief A key for the via cache */ struct ViaKey { ViaKey (const std::string &n, const std::string &ndr, unsigned int mb, unsigned int mc, unsigned int mt) : name (n), nondefaultrule (ndr), mask_bottom (mb), mask_cut (mc), mask_top (mt) { } bool operator== (const ViaKey &other) const { return name == other.name && nondefaultrule == other.nondefaultrule && mask_bottom == other.mask_bottom && mask_cut == other.mask_cut && mask_top == other.mask_top; } bool operator< (const ViaKey &other) const { if (name != other.name) { return name < other.name; } if (nondefaultrule != other.nondefaultrule) { return nondefaultrule < other.nondefaultrule; } if (mask_bottom != other.mask_bottom) { return mask_bottom < other.mask_bottom; } if (mask_cut != other.mask_cut) { return mask_cut < other.mask_cut; } if (mask_top != other.mask_top) { return mask_top < other.mask_top; } return false; } std::string name, nondefaultrule; unsigned int mask_bottom, mask_cut, mask_top; }; /** * @brief A key for the via cache */ struct MacroKey { MacroKey () { } MacroKey (const std::string &n, const std::vector &m) : name (n), masks (m) { } bool operator== (const MacroKey &other) const { return name == other.name && masks == other.masks; } bool operator< (const MacroKey &other) const { if (name != other.name) { return name < other.name; } if (masks != other.masks) { return masks < other.masks; } return false; } std::string name; std::vector masks; }; // no copying LEFDEFReaderState (const LEFDEFReaderState &); LEFDEFReaderState &operator= (const LEFDEFReaderState &); LEFDEFImporter *mp_importer; std::map , std::set > m_layers; db::LayerMap m_layer_map; bool m_create_layers; bool m_has_explicit_layer_mapping; int m_laynum; std::map m_default_number; const LEFDEFReaderOptions *mp_tech_comp; std::map m_via_cells; std::map, LEFDEFLayoutGenerator *> m_via_generators; std::map > m_macro_cells; std::map m_macro_generators; std::map m_foreign_cells; std::set open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask); db::cell_index_type foreign_cell(Layout &layout, const std::string &name); void read_single_map_file (const std::string &path, std::map, std::vector > &layer_map); }; /** * @brief A structure describing a via */ struct DB_PLUGIN_PUBLIC ViaDesc { ViaDesc () { } /** * @brief The names of bottom and top metal respectively */ std::string m1, m2; }; /** * @brief A structure describing a macro */ struct DB_PLUGIN_PUBLIC MacroDesc { MacroDesc () { } /** * @brief The name of the FOREIGN cell if present */ std::string foreign_name; /** * @brief The transformation of the FOREIGN cell */ db::Trans foreign_trans; /** * @brief The origin */ db::Point origin; /** * @brief The bounding box */ db::Box bbox; }; /** * @brief The LEF importer object */ class DB_PLUGIN_PUBLIC LEFDEFImporter { public: friend class LEFDEFReaderState; /** * @brief Default constructor */ LEFDEFImporter (int warn_level); /** * @brief Destructor */ virtual ~LEFDEFImporter (); /** * @brief Read into an existing layout * * This method reads the layout specified into the given layout */ void read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state); /** * @brief Issue an error at the current location */ void error (const std::string &msg); /** * @brief Issue a warning at the current location */ void warn (const std::string &msg, int wl = 1); protected: /** * @brief Actually does the reading * * Reimplement that method for the LEF and DEF implementation */ virtual void do_read (db::Layout &layout) = 0; /** * @brief Returns true if the reader is at the end of the file */ bool at_end (); /** * @brief Test whether the next token matches the given one and consume it in that case */ bool test (const std::string &token); /** * @brief Test whether the next token matches the given one, but don't consume it */ bool peek (const std::string &token); /** * @brief Test whether the next token matches the given one and raise an error if it does not */ void expect (const std::string &token); /** * @brief Test whether the next token matches one of the given ones and raise an error if it does not */ void expect (const std::string &token1, const std::string &token2); /** * @brief Test whether the next token matches one of the given ones and raise an error if it does not */ void expect (const std::string &token, const std::string &token2, const std::string &token3); /** * @brief Gets the next token */ std::string get (); /** * @brief Consumes the current token */ void take (); /** * @brief Reads the next token as a double value */ double get_double (); /** * @brief Reads the next token as a long value */ long get_long (); /** * @brief Gets an orientation code * The orientation code is read employing the LEF/DEF convention ("N" for r0 etc.) */ db::FTrans get_orient (bool optional); /** * @brief Reads a point * A point is given by two coordinates, x and y */ db::Point get_point (double scale); /** * @brief Reads a vector * A vector is given by two coordinates, x and y */ db::Vector get_vector (double scale); /** * @brief Turns a number into a mask number */ unsigned int get_mask (long m); /** * @brief Create a new layer or return the index of the given layer */ std::set open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask, const db::DVector &via_size = db::DVector ()) { return mp_reader_state->open_layer (layout, name, purpose, mask, via_size); } /** * @brief Registers a layer (assign a new default layer number) */ void register_layer (const std::string &l) { mp_reader_state->register_layer (l); } /** * @brief Sets the current cell name */ void set_cellname (const std::string &cn) { m_cellname = cn; } /** * @brief Reset the current cell name */ void reset_cellname () { m_cellname.clear (); } /** * @brief Gets a flag indicating whether net names shall be produced as properties */ bool produce_net_props () const { return m_produce_net_props; } /** * @brief Gets the property name id of the net name property */ db::property_names_id_type net_prop_name_id () const { return m_net_prop_name_id; } /** * @brief Gets a flag indicating whether instance names shall be produced as properties */ bool produce_inst_props () const { return m_produce_inst_props; } /** * @brief Gets the property name id of the instance name property */ db::property_names_id_type inst_prop_name_id () const { return m_inst_prop_name_id; } /** * @brief Gets a flag indicating whether pin names shall be produced as properties */ bool produce_pin_props () const { return m_produce_pin_props; } /** * @brief Gets the property name id of the pin name property */ db::property_names_id_type pin_prop_name_id () const { return m_pin_prop_name_id; } /** * @brief Gets the reader options */ const db::LEFDEFReaderOptions &options () const { return m_options; } /** * @brief Gets the reader state object */ db::LEFDEFReaderState *reader_state () { return mp_reader_state; } private: tl::AbsoluteProgress *mp_progress; tl::TextInputStream *mp_stream; LEFDEFReaderState *mp_reader_state; std::string m_cellname; std::string m_fn; std::string m_last_token; bool m_produce_net_props; db::property_names_id_type m_net_prop_name_id; bool m_produce_inst_props; db::property_names_id_type m_inst_prop_name_id; bool m_produce_pin_props; db::property_names_id_type m_pin_prop_name_id; db::LEFDEFReaderOptions m_options; int m_warn_level; std::vector m_sections; friend class LEFDEFSection; const std::string &next (); void enter_section (const std::string &name); void leave_section (); }; class DB_PLUGIN_PUBLIC LEFDEFSection { public: LEFDEFSection (LEFDEFImporter *importer, const std::string &name) : mp_importer (importer) { mp_importer->enter_section (name); } ~LEFDEFSection () { mp_importer->leave_section (); } private: LEFDEFImporter *mp_importer; }; class DB_PLUGIN_PUBLIC LEFDEFReader : public db::ReaderBase { public: LEFDEFReader (tl::InputStream &s); virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options); virtual const db::LayerMap &read (db::Layout &layout); virtual const char *format () const; const db::LayerMap &read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &options, bool import_lef); private: tl::InputStream &m_stream; db::LayerMap m_layer_map; }; } #endif