Merge pull request #620 from KLayout/lefdef-enhancments

Lefdef enhancments
This commit is contained in:
Matthias Köfferlein 2020-09-14 18:32:02 +02:00 committed by GitHub
commit 12ac7c1036
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
112 changed files with 9552 additions and 2856 deletions

51
TODO
View File

@ -1,51 +0,0 @@
Plan:
DONE 1. Combine AbstractMenuProvider, PluginRoot and the AbstractMenuProvider's
implementation in MainWindow/LayoutView into lay::Dispatcher
DONE 2. Base MainWindow and LayoutView on lay::Dispatcher
DONE 3. lay::Plugin::plugin_root -> lay::Dispatcher *lay::Plugin::dispatcher()
This method will find the MainWindow or LayoutView depending
which is the root.
DONE 4. Don't use AbstractMenuProvider::instance anymore, rather use lay::Dispatcher::instance
when necessary (should not be)
DONE 5. Instead of slots, bind abstract menu items to symbols passed to
Dispatcher::menu_activated
DONE 6. MainWindow will automatically dispatch menu_activated to LayoutView
DONE 7. GSI-expose menu_activated in LayoutView and MainWindow as "call_menu"
DONE 8. We can move menu initialization of LV-specifics to the LayoutView and
remove the cm_... and the code which just passes signals to the current view! :)
9. BTW: make QWidget::setParent and QObject::setParent transfer ownership for
Qt binding.
10. Provide the layer toolbox for GSI
11. Tests for new features and GSI tests
12. Default ctor for MainWindow so a pymod script can instantiate one (?)
DONE 13. Re-think concept of Action as "smart pointers": ConfigureAction
violates this. ConfigureAction should be ActionHandle variant?
Action as pointer and smart pointers for managing?
Tests:
- DONE: compare menu layout
- DONE: test every menu function
- adding of new tech
- DONE: adding of rulers/removing
- ruby plugin (debugging, re-running)
- DONE: changing of macro title, move macro to different place
- DONE: funktionieren die check marks vor den menus? (Mode, selection modes, ruler template)
- DONE: check whether there is a replacement for the "cm_..." methods and tests them (at least one)
- DONE: check if changing the default grid works
- Run unit tests -> klayout_main_tests:main is failing

View File

@ -41,7 +41,9 @@ int converter_main (int argc, char *argv[], const std::string &format)
generic_writer_options.add_options (cmd, format);
generic_reader_options.add_options (cmd);
cmd << tl::arg ("input", &infile, "The input file (any format, may be gzip compressed)")
cmd << tl::arg ("input", &infile, "The input file (any format, may be gzip compressed)",
"You can use '+' to supply multiple files which will be read after each other into the same layout. "
"This provides some cheap, but risky way of merging files. Beware of cell name conflicts.")
<< tl::arg ("output", &outfile, tl::sprintf ("The output file (%s format)", format))
;
@ -55,9 +57,13 @@ int converter_main (int argc, char *argv[], const std::string &format)
db::LoadLayoutOptions load_options;
generic_reader_options.configure (load_options);
tl::InputStream stream (infile);
db::Reader reader (stream);
reader.read (layout, load_options);
std::vector<std::string> files = tl::split (infile, "+");
for (std::vector<std::string>::const_iterator f = files.begin (); f != files.end (); ++f) {
tl::InputStream stream (*f);
db::Reader reader (stream);
reader.read (layout, load_options);
}
}
{

View File

@ -28,33 +28,98 @@ namespace bd
{
GenericReaderOptions::GenericReaderOptions ()
: m_prefix ("i"), m_group_prefix ("Input"), m_create_other_layers (true),
m_common_enable_text_objects (true),
m_common_enable_properties (true),
m_gds2_box_mode (1),
m_gds2_allow_big_records (true),
m_gds2_allow_multi_xy_records (true),
m_oasis_read_all_properties (true),
m_oasis_expect_strict_mode (-1),
m_cif_wire_mode (0),
m_cif_dbu (0.001),
m_cif_keep_layer_names (false),
m_dxf_dbu (0.001),
m_dxf_unit (1.0),
m_dxf_text_scaling (100.0),
m_dxf_polyline_mode (0),
m_dxf_circle_points (100),
m_dxf_circle_accuracy (0.0),
m_dxf_contour_accuracy (0.0),
m_dxf_render_texts_as_polygons (false),
m_dxf_keep_layer_names (false),
m_dxf_keep_other_cells (false),
m_magic_lambda (1.0),
m_magic_dbu (0.001),
m_magic_keep_layer_names (false),
m_magic_merge (true)
: m_prefix ("i"), m_group_prefix ("Input"), m_layer_map (), m_create_other_layers (true),
m_dbu (0.001), m_keep_layer_names (false)
{
// .. nothing yet ..
// initialize from the default settings
db::LoadLayoutOptions load_options;
m_common_enable_text_objects = load_options.get_option_by_name ("text_enabled").to_bool ();
m_common_enable_properties = load_options.get_option_by_name ("properties_enabled").to_bool ();
m_gds2_box_mode = load_options.get_option_by_name ("gds2_box_mode").to_uint ();
m_gds2_allow_big_records = load_options.get_option_by_name ("gds2_allow_big_records").to_bool ();
m_gds2_allow_multi_xy_records = load_options.get_option_by_name ("gds2_allow_multi_xy_records").to_bool ();
m_oasis_read_all_properties = load_options.get_option_by_name ("oasis_read_all_properties").to_bool ();
m_oasis_expect_strict_mode = (load_options.get_option_by_name ("oasis_expect_strict_mode").to_int () > 0);
m_create_other_layers = load_options.get_option_by_name ("cif_create_other_layers").to_bool ();
m_cif_wire_mode = load_options.get_option_by_name ("cif_wire_mode").to_uint ();
m_dxf_unit = load_options.get_option_by_name ("dxf_unit").to_double ();
m_dxf_text_scaling = load_options.get_option_by_name ("dxf_text_scaling").to_double ();
m_dxf_polyline_mode = load_options.get_option_by_name ("dxf_polyline_mode").to_int ();
m_dxf_circle_points = load_options.get_option_by_name ("dxf_circle_points").to_int ();
m_dxf_circle_accuracy = load_options.get_option_by_name ("dxf_circle_accuracy").to_double ();
m_dxf_contour_accuracy = load_options.get_option_by_name ("dxf_contour_accuracy").to_double ();
m_dxf_render_texts_as_polygons = load_options.get_option_by_name ("dxf_render_texts_as_polygons").to_bool ();
m_dxf_keep_other_cells = load_options.get_option_by_name ("dxf_keep_other_cells").to_bool ();
m_magic_lambda = load_options.get_option_by_name ("mag_lambda").to_double ();
m_magic_merge = load_options.get_option_by_name ("mag_merge").to_bool ();
tl::Variant mag_library_paths = load_options.get_option_by_name ("mag_library_paths");
for (tl::Variant::const_iterator i = mag_library_paths.begin (); i != mag_library_paths.end (); ++i) {
m_magic_lib_path.push_back (i->to_string ());
}
tl::Variant v;
v = load_options.get_option_by_name ("lefdef_config.net_property_name");
m_lefdef_produce_net_names = ! v.is_nil ();
m_lefdef_net_property_name = v .to_parsable_string ();
v = load_options.get_option_by_name ("lefdef_config.instance_property_name");
m_lefdef_produce_inst_names = ! v.is_nil ();
m_lefdef_inst_property_name = v .to_parsable_string ();
v = load_options.get_option_by_name ("lefdef_config.pin_property_name");
m_lefdef_produce_pin_names = ! v.is_nil ();
m_lefdef_pin_property_name = v .to_parsable_string ();
m_lefdef_produce_cell_outlines = load_options.get_option_by_name ("lefdef_config.produce_cell_outlines").to_bool ();
m_lefdef_cell_outline_layer = load_options.get_option_by_name ("lefdef_config.cell_outline_layer").to_string ();
m_lefdef_produce_placement_blockages = load_options.get_option_by_name ("lefdef_config.produce_placement_blockages").to_bool ();
m_lefdef_placement_blockage_layer = load_options.get_option_by_name ("lefdef_config.placement_blockage_layer").to_string ();
m_lefdef_produce_regions = load_options.get_option_by_name ("lefdef_config.produce_regions").to_bool ();
m_lefdef_region_layer = load_options.get_option_by_name ("lefdef_config.region_layer").to_string ();
m_lefdef_produce_via_geometry = load_options.get_option_by_name ("lefdef_config.produce_via_geometry").to_bool ();
m_lefdef_via_geometry_suffix = load_options.get_option_by_name ("lefdef_config.via_geometry_suffix_str").to_string ();
m_lefdef_via_geometry_datatype = load_options.get_option_by_name ("lefdef_config.via_geometry_datatype_str").to_string ();
m_lefdef_via_cellname_prefix = load_options.get_option_by_name ("lefdef_config.via_cellname_prefix").to_string ();
m_lefdef_produce_pins = load_options.get_option_by_name ("lefdef_config.produce_pins").to_bool ();
m_lefdef_pins_suffix = load_options.get_option_by_name ("lefdef_config.pins_suffix_str").to_string ();
m_lefdef_pins_datatype = load_options.get_option_by_name ("lefdef_config.pins_datatype_str").to_string ();
m_lefdef_produce_lef_pins = load_options.get_option_by_name ("lefdef_config.produce_lef_pins").to_bool ();
m_lefdef_lef_pins_suffix = load_options.get_option_by_name ("lefdef_config.lef_pins_suffix_str").to_string ();
m_lefdef_lef_pins_datatype = load_options.get_option_by_name ("lefdef_config.lef_pins_datatype_str").to_string ();
m_lefdef_produce_obstructions = load_options.get_option_by_name ("lefdef_config.produce_obstructions").to_bool ();
m_lefdef_obstruction_suffix = load_options.get_option_by_name ("lefdef_config.obstructions_suffix").to_string ();
m_lefdef_obstruction_datatype = load_options.get_option_by_name ("lefdef_config.obstructions_datatype").to_int ();
m_lefdef_produce_blockages = load_options.get_option_by_name ("lefdef_config.produce_blockages").to_bool ();
m_lefdef_blockage_suffix = load_options.get_option_by_name ("lefdef_config.blockages_suffix").to_string ();
m_lefdef_blockage_datatype = load_options.get_option_by_name ("lefdef_config.blockages_datatype").to_int ();
m_lefdef_produce_labels = load_options.get_option_by_name ("lefdef_config.produce_labels").to_bool ();
m_lefdef_label_suffix = load_options.get_option_by_name ("lefdef_config.labels_suffix").to_string ();
m_lefdef_label_datatype = load_options.get_option_by_name ("lefdef_config.labels_datatype").to_int ();
m_lefdef_produce_routing = load_options.get_option_by_name ("lefdef_config.produce_routing").to_bool ();
m_lefdef_routing_suffix = load_options.get_option_by_name ("lefdef_config.routing_suffix_str").to_string ();
m_lefdef_routing_datatype = load_options.get_option_by_name ("lefdef_config.routing_datatype_str").to_string ();
m_lefdef_produce_special_routing = load_options.get_option_by_name ("lefdef_config.produce_special_routing").to_bool ();
m_lefdef_special_routing_suffix = load_options.get_option_by_name ("lefdef_config.special_routing_suffix_str").to_string ();
m_lefdef_special_routing_datatype = load_options.get_option_by_name ("lefdef_config.special_routing_datatype_str").to_string ();
tl::Variant lef_files = load_options.get_option_by_name ("lefdef_config.lef_files");
for (tl::Variant::const_iterator i = lef_files.begin (); i != lef_files.end (); ++i) {
m_lefdef_lef_files.push_back (i->to_string ());
}
m_lefdef_read_lef_with_def = load_options.get_option_by_name ("lefdef_config.read_lef_with_def").to_bool ();
m_lefdef_separate_groups = load_options.get_option_by_name ("lefdef_config.separate_groups").to_bool ();
m_lefdef_map_file = load_options.get_option_by_name ("lefdef_config.map_file").to_string ();
m_lefdef_produce_lef_macros = (load_options.get_option_by_name ("lefdef_config.macro_resolution_mode").to_int () == 0);
}
void
@ -263,6 +328,274 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
)
;
}
{
std::string group ("[" + m_group_prefix + " options - LEF/DEF specific]");
cmd << tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-net-names", &m_lefdef_produce_net_names, "Disables producing net names as shape properties",
"If this option is present, net names will not be emitted as shape properties."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-net-property-name=spec", &m_lefdef_net_property_name, "Specifies which property name to use for net names",
"This option gives the name of the shape property used to annotate net names. For 'spec' use:\n"
"\n"
"* \"#n\" for property number \"n\" (compatible with GDS2)\n"
"* A plain word for a named property (not compatible with GDS2)\n"
"\n"
"Producing net name annotation properties can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-net-names'."
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-instance-names", &m_lefdef_produce_inst_names, "Disables producing DEF macro instance names as instance properties",
"If this option is present, DEF macro instance names will not be emitted as instance properties."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-instance-property-name=spec", &m_lefdef_inst_property_name, "Specifies which property name to use for DEF macro instance names",
"This option gives the name of the instance property used to annotate DEF macro instance names. "
"For the 'spec' format see '--" + m_long_prefix + "lefdef-net-property-name'."
"\n"
"Producing instance name annotation properties can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-instance-names'."
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-pin-names", &m_lefdef_produce_pin_names, "Disables producing pin names as shape or instance properties",
"If this option is present, Pin names will not be emitted as shape or instance properties."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-pin-property-name=spec", &m_lefdef_pin_property_name, "Specifies which property name to use for pin names",
"This option gives the name of the shape or instance property used to annotate pin names. "
"For the 'spec' format see '--" + m_long_prefix + "lefdef-net-property-name'."
"\n"
"Producing pin name annotation properties can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-pin-names'."
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-cell-outlines", &m_lefdef_produce_cell_outlines, "Disables producing cell outlines",
"If this option is present, cell outlines will be skipped. Otherwise the cell outlines will be written to a layer given with '--" + m_long_prefix + "lefdef-cell-outline-layer'."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-cell-outline-layer=spec", &m_lefdef_cell_outline_layer, "Specifies which layer to use for the cell outlines",
"This option specifies the layer to use for the cell outline polygons. For 'spec' use:\n"
"\n"
"* \"l\" or \"l/d\" for a numerical layer or layer/datatype combination.\n"
"* A plain word for a named layer\n"
"* A name followed by a layer or layer/datatype combination in round brackets for a combined specification\n"
"\n"
"Producing cell outline markers can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-cell-outlines'."
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-placement-blockages", &m_lefdef_produce_placement_blockages, "Disables producing blockage markers",
"If this option is present, blockages will be skipped. Otherwise the blockage markers will be written to a layer given with '--" + m_long_prefix + "lefdef-placement-blockage-layer'."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-placement-blockage-layer=spec", &m_lefdef_placement_blockage_layer, "Specifies which layer to use for the placement blockage markers",
"For the 'spec' format see '--" + m_long_prefix + "lefdef-cell-outline-layer'.\n"
"\n"
"Producing cell placement blockage markers can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-placement-blockages'."
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-regions", &m_lefdef_produce_regions, "Disables producing regions",
"If this option is present, regions will be skipped. Otherwise the regions will be written to a layer given with '--" + m_long_prefix + "lefdef-region-layer'."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-region-layer=spec", &m_lefdef_region_layer, "Specifies which layer to use for the regions",
"For the 'spec' format see '--" + m_long_prefix + "lefdef-cell-outline-layer'.\n"
"\n"
"Producing regions can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-regions'."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-separate-groups", &m_lefdef_separate_groups, "Specifies to separate groups of regions into a hierarchy",
"This option is used together with '--" + m_long_prefix + "lefdef-produce-regions'. If given, the region polygons will be put "
"into a cell hierarchy where the cells indicate the region groups.\n"
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-via-geometry", &m_lefdef_produce_via_geometry, "Skips vias when producing geometry",
"If this option is given, no via geometry will be produced."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-via-geometry-suffix", &m_lefdef_via_geometry_suffix, "Specifies the via geometry layer suffix in pattern-based mode",
"Use '" + m_long_prefix + "lefdef-via-geometry-suffix' and '--" + m_long_prefix + "lefdef-via-geometry-datatype' together with "
"a layer map (see '-" + m_prefix + "m') to customize where the via geometry will be put.\n"
"\n"
"This option is part of the 'pattern-based' LEF/DEF layer mapping scheme.\n"
"\n"
"The mechanism is this: from the geometry's layer name and the suffix an effective layer name is produced. For example if the "
"geometry is on layer 'M1' and the suffix is '_VIA', the effective layer name will be 'M1_VIA'. This layer is looked up in the "
"layer map. If no such layer is found, the geometry layer name without suffix is looked up. If this layer is found, the datatype "
"is substituted by the datatype specified with the '--" + m_long_prefix + "lefdef-via-geometry-datatype'. So eventually it's "
"possible to use a detailed mapping by layer name + suffix or a generic mapping by layer name + datatype.\n"
"\n"
"Suffix and datatype can be made MASK specific by giving a list of values in the form: \"<generic>,1:<for-mask1>,2:<for-mask2>...\". "
"For example, a datatype specification of \"6,1:61,2:62\" will use datatype 6 for via geometry without a mask assignment, "
"datatype 61 for via geometry assigned to MASK 1 and datatype 62 for via geometry assigned to MASK 2.\n"
"\n"
"An alternative way to provide a layer mapping is through a map file (see '--" + m_long_prefix + "lefdef-map-file')."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-via-geometry-datatype", &m_lefdef_via_geometry_datatype, "Specifies the via geometry layer datatype in pattern-based mode",
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of this option.\n"
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-via-cell-prefix", &m_lefdef_via_cellname_prefix, "Specifies the prefix for the cell names generated for vias",
"Vias will be put into their own cells by the LEF/DEF reader. This option gives a prefix that is used to form the name of "
"these cells. The name is built from the prefix plus the via name.\n"
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-pins", &m_lefdef_produce_pins, "Skips pins when producing geometry",
"If this option is given, no pin geometry will be produced."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-pins-suffix", &m_lefdef_pins_suffix, "Specifies the pin geometry layer suffix in pattern-based mode",
"The pin geometry generation and layer mapping is designed in the same way than via geometry mapping. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-pins-datatype", &m_lefdef_pins_datatype, "Specifies the pin geometry layer datatype in pattern-based mode",
"The pin geometry generation and layer mapping is designed in the same way than via geometry mapping. "
"See '--" + m_long_prefix + "lefdef-produce-via-geometry' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-lef-pins", &m_lefdef_produce_lef_pins, "Skips LEF pins when producing geometry",
"If this option is given, no LEF pin geometry will be produced."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-lef-pins-suffix", &m_lefdef_lef_pins_suffix, "Specifies the LEF pin geometry layer suffix in pattern-based mode",
"The LEF pin geometry generation and layer mapping is designed in the same way than via geometry mapping. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-lef-pins-datatype", &m_lefdef_lef_pins_datatype, "Specifies the LEF pin geometry layer datatype in pattern-based mode",
"The LEF pin geometry generation and layer mapping is designed in the same way than via geometry mapping. "
"See '--" + m_long_prefix + "lefdef-produce-via-geometry' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-routing", &m_lefdef_produce_routing, "Skips routing when producing geometry",
"If this option is given, no routing geometry will be produced."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-routing-suffix", &m_lefdef_routing_suffix, "Specifies the routing geometry layer suffix in pattern-based mode",
"The routing geometry generation and layer mapping is designed in the same way than via geometry mapping. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-routing-datatype", &m_lefdef_routing_datatype, "Specifies the routing geometry layer datatype in pattern-based mode",
"The routing geometry generation and layer mapping is designed in the same way than via geometry mapping. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-special-routing", &m_lefdef_produce_special_routing, "Skips special routing when producing geometry",
"If this option is given, no special routing geometry will be produced."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-special-routing-suffix", &m_lefdef_special_routing_suffix, "Specifies the special routing geometry layer suffix in pattern-based mode",
"The special routing geometry generation and layer mapping is designed in the same way than via geometry mapping. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-special-routing-datatype", &m_lefdef_special_routing_datatype, "Specifies the special routing geometry layer datatype in pattern-based mode",
"The special routing geometry generation and layer mapping is designed in the same way than via geometry mapping. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-obstructions", &m_lefdef_produce_obstructions, "Skips obstructions when producing geometry",
"If this option is given, no obstruction marker geometry will be produced."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-obstruction-suffix", &m_lefdef_obstruction_suffix, "Specifies the obstruction markers layer suffix in pattern-based mode",
"The obstruction marker generation and layer mapping is designed in the same way than via geometry mapping, except the option to use mask specific target layers. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-obstruction-datatype", &m_lefdef_obstruction_datatype, "Specifies the obstruction markers layer datatype in pattern-based mode",
"The obstruction marker generation and layer mapping is designed in the same way than via geometry mapping, except the option to use mask specific target layers. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-blockages", &m_lefdef_produce_blockages, "Skips blockages when producing geometry",
"If this option is given, no blockage geometry will be produced."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-blockage-suffix", &m_lefdef_blockage_suffix, "Specifies the blockage markers layer suffix in pattern-based mode",
"The blockage marker generation and layer mapping is designed in the same way than via geometry mapping, except the option to use mask specific target layers. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-blockage-datatype", &m_lefdef_blockage_datatype, "Specifies the blockage markers layer datatype in pattern-based mode",
"The blockage marker generation and layer mapping is designed in the same way than via geometry mapping, except the option to use mask specific target layers. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-labels", &m_lefdef_produce_labels, "Skips label when producing geometry",
"If this option is given, no blockage geometry will be produced."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-label-suffix", &m_lefdef_label_suffix, "Specifies the label markers layer suffix in pattern-based mode",
"The label marker generation and layer mapping is designed in the same way than via geometry mapping, except the option to use mask specific target layers. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-label-datatype", &m_lefdef_label_datatype, "Specifies the label markers layer datatype in pattern-based mode",
"The label marker generation and layer mapping is designed in the same way than via geometry mapping, except the option to use mask specific target layers. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the mapping scheme.\n"
)
<< tl::arg (group +
"--" + m_long_prefix + "lefdef-map", &m_lefdef_map_file, "Specifies to use a layer map file",
"Use this option to turn off pattern-based layer mapping and to use an explicit mapping file instead. "
"See '--" + m_long_prefix + "lefdef-via-geometry-suffix' for a description of the pattern-based mapping scheme.\n"
"\n"
"Using a map file is an alternative way to specify layer mapping. With a layer mapping file, the individual target "
"layers need to specified individually for different layer/purpose combinations.\n"
"\n"
"The mapping file is one layer mapping entry per line. Each line is a layer name, followed by a list of purposes (VIA, PIN ...) "
"and a layer and datatype number. In addition, 'DIEAREA' can be used to map the design outline to a layer. 'NAME' in place of the "
"layer name and using layer/purpose in the purpose column allows mapping labels to specific layers.\n"
"\n"
"This is an example for a layer map file:\n"
"\n"
"DIEAREA ALL 100 0\n"
"M1 LEFPIN 12 0\n"
"M1 PIN 12 2\n"
"M1 NET 12 3\n"
"M1 SPNET 12 4\n"
"M1 VIA 12 5\n"
"M1 BLOCKAGE 12 10\n"
"NAME M1/PIN 12 10\n"
"VIA1 LEFPIN,VIA,PIN,NET,SPNET 13 0\n"
"M2 LEFPIN,PIN,NET,SPNET,VIA 14 0\n"
"\n"
"If a map file is used, only the layers present in the map file are generated. No other layers are produced."
)
<< tl::arg (group +
"!--" + m_long_prefix + "lefdef-no-lef-macros", &m_lefdef_produce_lef_macros, "Don't produce LEF macro geometry",
"This option applies when reading DEF files.\n"
"\n"
"If this option is present, no geometry will be produced for LEF macros. Instead, a ghost cell with the name of the LEF "
"macro will be produced. If this option is not given, the LEF macros will be inserted in to these cells "
"unless a FOREIGN specification is present in the LEF macro. If a FOREIGN specification is given, LEF geometry is never "
"inserted into a DEF file. Instead ghost cells are created."
)
<< tl::arg (group +
"!--" + m_long_prefix + "lefdef-no-implicit-lef", &m_lefdef_read_lef_with_def, "Disables reading all LEF files together with DEF files",
"This option applies when reading DEF files.\n"
"\n"
"If this option is given, only the LEF files specified with '--" + m_long_prefix + "lefdef-lef-files' will be read."
"\n"
"If this option is not present, the DEF reader will look for all files with 'LEF' or related extensions "
"in the same place than the DEF file and read these files before the DEF file is read. In addition, it will read the "
"LEF files specified with '--" + m_long_prefix + "lefdef-lef-files'."
)
<< tl::arg (group +
"--" + m_long_prefix + "lefdef-lefs", &m_lefdef_lef_files, "Specifies which additional LEF files to read",
"This option applies when reading DEF files.\n"
"\n"
"Use a comma-separated list of file names here to specify which LEF files to read. "
"See also '--" + m_long_prefix + "lefdef-read-lef-with-def' for an option to implicitly read all LEF files in the same "
"place than the DEF file.\n"
"\n"
"Relative paths are resolved based on the location of the DEF file which is read."
)
;
}
}
void GenericReaderOptions::set_layer_map (const std::string &lm)
@ -279,16 +612,12 @@ void GenericReaderOptions::set_layer_map (const std::string &lm)
void GenericReaderOptions::set_read_named_layers (bool f)
{
m_dxf_keep_layer_names = f;
m_cif_keep_layer_names = f;
m_magic_keep_layer_names = f;
m_keep_layer_names = f;
}
void GenericReaderOptions::set_dbu (double dbu)
{
m_dxf_dbu = dbu;
m_cif_dbu = dbu;
m_magic_dbu = dbu;
m_dbu = dbu;
}
void
@ -304,17 +633,17 @@ GenericReaderOptions::configure (db::LoadLayoutOptions &load_options) const
load_options.set_option_by_name ("gds2_allow_multi_xy_records", m_gds2_allow_multi_xy_records);
load_options.set_option_by_name ("oasis_read_all_properties", m_oasis_read_all_properties);
load_options.set_option_by_name ("oasis_expect_strict_mode", m_oasis_expect_strict_mode);
load_options.set_option_by_name ("oasis_expect_strict_mode", m_oasis_expect_strict_mode ? 1 : 0);
load_options.set_option_by_name ("cif_layer_map", tl::Variant::make_variant (m_layer_map));
load_options.set_option_by_name ("cif_create_other_layers", m_create_other_layers);
load_options.set_option_by_name ("cif_dbu", m_dxf_dbu);
load_options.set_option_by_name ("cif_dbu", m_dbu);
load_options.set_option_by_name ("cif_wire_mode", m_cif_wire_mode);
load_options.set_option_by_name ("cif_keep_layer_names", m_cif_keep_layer_names);
load_options.set_option_by_name ("cif_keep_layer_names", m_keep_layer_names);
load_options.set_option_by_name ("dxf_layer_map", tl::Variant::make_variant (m_layer_map));
load_options.set_option_by_name ("dxf_create_other_layers", m_create_other_layers);
load_options.set_option_by_name ("dxf_dbu", m_dxf_dbu);
load_options.set_option_by_name ("dxf_dbu", m_dbu);
load_options.set_option_by_name ("dxf_unit", m_dxf_unit);
load_options.set_option_by_name ("dxf_text_scaling", m_dxf_text_scaling);
load_options.set_option_by_name ("dxf_polyline_mode", m_dxf_polyline_mode);
@ -322,16 +651,59 @@ GenericReaderOptions::configure (db::LoadLayoutOptions &load_options) const
load_options.set_option_by_name ("dxf_circle_accuracy", m_dxf_circle_accuracy);
load_options.set_option_by_name ("dxf_contour_accuracy", m_dxf_contour_accuracy);
load_options.set_option_by_name ("dxf_render_texts_as_polygons", m_dxf_render_texts_as_polygons);
load_options.set_option_by_name ("dxf_keep_layer_names", m_dxf_keep_layer_names);
load_options.set_option_by_name ("dxf_keep_layer_names", m_keep_layer_names);
load_options.set_option_by_name ("dxf_keep_other_cells", m_dxf_keep_other_cells);
load_options.set_option_by_name ("mag_layer_map", tl::Variant::make_variant (m_layer_map));
load_options.set_option_by_name ("mag_create_other_layers", m_create_other_layers);
load_options.set_option_by_name ("mag_dbu", m_magic_dbu);
load_options.set_option_by_name ("mag_dbu", m_dbu);
load_options.set_option_by_name ("mag_lambda", m_magic_lambda);
load_options.set_option_by_name ("mag_merge", m_magic_merge);
load_options.set_option_by_name ("mag_keep_layer_names", m_magic_keep_layer_names);
load_options.set_option_by_name ("mag_keep_layer_names", m_keep_layer_names);
load_options.set_option_by_name ("mag_library_paths", tl::Variant (m_magic_lib_path.begin (), m_magic_lib_path.end ()));
load_options.set_option_by_name ("lefdef_config.layer_map", tl::Variant::make_variant (m_layer_map));
load_options.set_option_by_name ("lefdef_config.create_other_layers", m_create_other_layers);
load_options.set_option_by_name ("lefdef_config.dbu", m_dbu);
load_options.set_option_by_name ("lefdef_config.net_property_name", m_lefdef_produce_net_names ? tl::Variant (m_lefdef_net_property_name) : tl::Variant ());
load_options.set_option_by_name ("lefdef_config.instance_property_name", m_lefdef_produce_inst_names ? tl::Variant (m_lefdef_inst_property_name) : tl::Variant ());
load_options.set_option_by_name ("lefdef_config.pin_property_name", m_lefdef_produce_pin_names ? tl::Variant (m_lefdef_pin_property_name) : tl::Variant ());
load_options.set_option_by_name ("lefdef_config.produce_cell_outlines", m_lefdef_produce_cell_outlines);
load_options.set_option_by_name ("lefdef_config.cell_outline_layer", m_lefdef_cell_outline_layer);
load_options.set_option_by_name ("lefdef_config.produce_placement_blockages", m_lefdef_produce_placement_blockages);
load_options.set_option_by_name ("lefdef_config.placement_blockage_layer", m_lefdef_placement_blockage_layer);
load_options.set_option_by_name ("lefdef_config.produce_regions", m_lefdef_produce_regions);
load_options.set_option_by_name ("lefdef_config.region_layer", m_lefdef_region_layer);
load_options.set_option_by_name ("lefdef_config.produce_via_geometry", m_lefdef_produce_via_geometry);
load_options.set_option_by_name ("lefdef_config.via_geometry_suffix_str", m_lefdef_via_geometry_suffix);
load_options.set_option_by_name ("lefdef_config.via_geometry_datatype_str", m_lefdef_via_geometry_datatype);
load_options.set_option_by_name ("lefdef_config.via_cellname_prefix", m_lefdef_via_cellname_prefix);
load_options.set_option_by_name ("lefdef_config.produce_pins", m_lefdef_produce_pins);
load_options.set_option_by_name ("lefdef_config.pins_suffix_str", m_lefdef_pins_suffix);
load_options.set_option_by_name ("lefdef_config.pins_datatype_str", m_lefdef_pins_datatype);
load_options.set_option_by_name ("lefdef_config.produce_lef_pins", m_lefdef_produce_lef_pins);
load_options.set_option_by_name ("lefdef_config.lef_pins_suffix_str", m_lefdef_lef_pins_suffix);
load_options.set_option_by_name ("lefdef_config.lef_pins_datatype_str", m_lefdef_lef_pins_datatype);
load_options.set_option_by_name ("lefdef_config.produce_obstructions", m_lefdef_produce_obstructions);
load_options.set_option_by_name ("lefdef_config.obstructions_suffix", m_lefdef_obstruction_suffix);
load_options.set_option_by_name ("lefdef_config.obstructions_datatype", m_lefdef_obstruction_datatype);
load_options.set_option_by_name ("lefdef_config.produce_blockages", m_lefdef_produce_blockages);
load_options.set_option_by_name ("lefdef_config.blockages_suffix", m_lefdef_blockage_suffix);
load_options.set_option_by_name ("lefdef_config.blockages_datatype", m_lefdef_blockage_datatype);
load_options.set_option_by_name ("lefdef_config.produce_labels", m_lefdef_produce_labels);
load_options.set_option_by_name ("lefdef_config.labels_suffix", m_lefdef_label_suffix);
load_options.set_option_by_name ("lefdef_config.labels_datatype", m_lefdef_label_datatype);
load_options.set_option_by_name ("lefdef_config.produce_routing", m_lefdef_produce_routing);
load_options.set_option_by_name ("lefdef_config.routing_suffix_str", m_lefdef_routing_suffix);
load_options.set_option_by_name ("lefdef_config.routing_datatype_str", m_lefdef_routing_datatype);
load_options.set_option_by_name ("lefdef_config.produce_special_routing", m_lefdef_produce_special_routing);
load_options.set_option_by_name ("lefdef_config.special_routing_suffix_str", m_lefdef_special_routing_suffix);
load_options.set_option_by_name ("lefdef_config.special_routing_datatype_str", m_lefdef_special_routing_datatype);
load_options.set_option_by_name ("lefdef_config.lef_files", tl::Variant (m_lefdef_lef_files.begin (), m_lefdef_lef_files.end ()));
load_options.set_option_by_name ("lefdef_config.read_lef_with_def", m_lefdef_read_lef_with_def);
load_options.set_option_by_name ("lefdef_config.separate_groups", m_lefdef_separate_groups);
load_options.set_option_by_name ("lefdef_config.map_file", m_lefdef_map_file);
load_options.set_option_by_name ("lefdef_config.macro_resolution_mode", m_lefdef_produce_lef_macros ? 0 : 2);
}
}

View File

@ -99,6 +99,8 @@ private:
// generic
db::LayerMap m_layer_map;
bool m_create_other_layers;
double m_dbu;
bool m_keep_layer_names;
// common GDS2+OASIS
bool m_common_enable_text_objects;
@ -115,11 +117,8 @@ private:
// CIF
unsigned int m_cif_wire_mode;
double m_cif_dbu;
bool m_cif_keep_layer_names;
// DXF
double m_dxf_dbu;
double m_dxf_unit;
double m_dxf_text_scaling;
int m_dxf_polyline_mode;
@ -127,19 +126,60 @@ private:
double m_dxf_circle_accuracy;
double m_dxf_contour_accuracy;
bool m_dxf_render_texts_as_polygons;
bool m_dxf_keep_layer_names;
bool m_dxf_keep_other_cells;
// MAGIC
double m_magic_lambda;
double m_magic_dbu;
bool m_magic_keep_layer_names;
bool m_magic_merge;
std::vector<std::string> m_magic_lib_path;
void set_layer_map (const std::string &lm);
void set_dbu (double dbu);
void set_read_named_layers (bool f);
// LEFDEF
bool m_lefdef_produce_net_names;
std::string m_lefdef_net_property_name;
bool m_lefdef_produce_inst_names;
std::string m_lefdef_inst_property_name;
bool m_lefdef_produce_pin_names;
std::string m_lefdef_pin_property_name;
bool m_lefdef_produce_cell_outlines;
std::string m_lefdef_cell_outline_layer;
bool m_lefdef_produce_placement_blockages;
std::string m_lefdef_placement_blockage_layer;
bool m_lefdef_produce_regions;
std::string m_lefdef_region_layer;
bool m_lefdef_produce_via_geometry;
std::string m_lefdef_via_geometry_suffix;
std::string m_lefdef_via_geometry_datatype;
std::string m_lefdef_via_cellname_prefix;
bool m_lefdef_produce_pins;
std::string m_lefdef_pins_suffix;
std::string m_lefdef_pins_datatype;
bool m_lefdef_produce_lef_pins;
std::string m_lefdef_lef_pins_suffix;
std::string m_lefdef_lef_pins_datatype;
bool m_lefdef_produce_obstructions;
std::string m_lefdef_obstruction_suffix;
int m_lefdef_obstruction_datatype;
bool m_lefdef_produce_blockages;
std::string m_lefdef_blockage_suffix;
int m_lefdef_blockage_datatype;
bool m_lefdef_produce_labels;
std::string m_lefdef_label_suffix;
int m_lefdef_label_datatype;
bool m_lefdef_produce_routing;
std::string m_lefdef_routing_suffix;
std::string m_lefdef_routing_datatype;
bool m_lefdef_produce_special_routing;
std::string m_lefdef_special_routing_suffix;
std::string m_lefdef_special_routing_datatype;
std::vector<std::string> m_lefdef_lef_files;
bool m_lefdef_read_lef_with_def;
bool m_lefdef_separate_groups;
std::string m_lefdef_map_file;
bool m_lefdef_produce_lef_macros;
};
}

View File

@ -140,7 +140,7 @@ struct XORData
double tile_size;
db::Layout *output_layout;
db::cell_index_type output_cell;
std::map<db::LayerProperties, std::pair<int, int> > l2l_map;
std::map<db::LayerProperties, std::pair<int, int>, db::LPLogicalLessFunc> l2l_map;
std::map<std::pair<int, db::LayerProperties>, ResultDescriptor> *results;
};
@ -299,7 +299,7 @@ BD_PUBLIC int strmxor (int argc, char *argv[])
throw tl::Exception ("'" + top_b + "' is not a valid cell name in second layout");
}
std::map<db::LayerProperties, std::pair<int, int> > l2l_map;
std::map<db::LayerProperties, std::pair<int, int>, db::LPLogicalLessFunc> l2l_map;
for (db::Layout::layer_iterator l = layout_a.begin_layers (); l != layout_a.end_layers (); ++l) {
l2l_map.insert (std::make_pair (*(*l).second, std::make_pair (-1, -1))).first->second.first = (*l).first;

View File

@ -26,6 +26,9 @@
#include "dbManager.h"
#include "dbBox.h"
#include "dbPCellVariant.h"
#include "dbLayoutUtils.h"
#include "dbLayerMapping.h"
#include "dbCellMapping.h"
#include <limits>
@ -726,5 +729,313 @@ Cell::set_name (const std::string &name)
layout ()->rename_cell (cell_index (), name.c_str ());
}
void
Cell::copy_shapes (const db::Cell &source_cell, const db::LayerMapping &layer_mapping)
{
if (this == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell")));
}
db::Layout *target_layout = layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
const db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
if (target_layout != source_layout) {
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
for (std::map<unsigned int, unsigned int>::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) {
shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm);
}
} else {
for (std::map<unsigned int, unsigned int>::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) {
shapes (lm->second).insert (source_cell.shapes (lm->first));
}
}
}
void
Cell::copy_shapes (const db::Cell &source_cell)
{
if (this == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell")));
}
db::Layout *target_layout = layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
if (target_layout != source_cell.layout ()) {
if (! source_cell.layout ()) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::LayerMapping lm;
lm.create_full (*target_layout, *source_cell.layout ());
this->copy_shapes (source_cell, lm);
} else {
for (db::Layout::layer_iterator l = target_layout->begin_layers (); l != target_layout->end_layers (); ++l) {
shapes ((*l).first).insert (source_cell.shapes ((*l).first));
}
}
}
void
Cell::copy_instances (const db::Cell &source_cell)
{
if (this == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot copy instances within the same cell")));
}
if (layout () != source_cell.layout ()) {
throw tl::Exception (tl::to_string (tr ("Cells do not reside in the same layout")));
}
for (db::Cell::const_iterator i = source_cell.begin (); ! i.at_end (); ++i) {
insert (*i);
}
}
std::vector<db::cell_index_type>
Cell::copy_tree (const db::Cell &source_cell)
{
if (this == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell")));
}
db::Layout *target_layout = layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
const db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
db::CellMapping cm;
std::vector <db::cell_index_type> new_cells = cm.create_single_mapping_full (*target_layout, cell_index (), *source_layout, source_cell.cell_index ());
db::LayerMapping lm;
lm.create_full (*target_layout, *source_cell.layout ());
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_cell.cell_index ());
db::copy_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ());
return new_cells;
}
void
Cell::copy_tree_shapes (const db::Cell &source_cell, const db::CellMapping &cm)
{
if (this == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell")));
}
db::Layout *target_layout = layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
const db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
db::LayerMapping lm;
lm.create_full (*target_layout, *source_cell.layout ());
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_cell.cell_index ());
db::copy_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ());
}
void
Cell::copy_tree_shapes (const db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm)
{
if (this == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell")));
}
db::Layout *target_layout = layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
const db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_cell.cell_index ());
db::copy_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ());
}
void
Cell::move_shapes (db::Cell &source_cell, const db::LayerMapping &layer_mapping)
{
if (this == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell")));
}
db::Layout *target_layout = layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
if (target_layout != source_layout) {
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
for (std::map<unsigned int, unsigned int>::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) {
shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm);
source_cell.shapes (lm->first).clear ();
}
} else {
for (std::map<unsigned int, unsigned int>::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) {
shapes (lm->second).insert (source_cell.shapes (lm->first));
source_cell.shapes (lm->first).clear ();
}
}
}
void
Cell::move_shapes (db::Cell &source_cell)
{
if (this == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell")));
}
db::Layout *target_layout = layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
if (target_layout != source_cell.layout ()) {
if (! source_cell.layout ()) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::LayerMapping lm;
lm.create_full (*target_layout, *source_cell.layout ());
move_shapes (source_cell, lm);
} else {
for (db::Layout::layer_iterator l = target_layout->begin_layers (); l != target_layout->end_layers (); ++l) {
shapes ((*l).first).insert (source_cell.shapes ((*l).first));
source_cell.shapes ((*l).first).clear ();
}
}
}
void
Cell::move_instances (db::Cell &source_cell)
{
if (this == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot move instances within the same cell")));
}
if (layout () != source_cell.layout ()) {
throw tl::Exception (tl::to_string (tr ("Cells do not reside in the same layout")));
}
for (db::Cell::const_iterator i = source_cell.begin (); ! i.at_end (); ++i) {
insert (*i);
}
source_cell.clear_insts ();
}
std::vector<db::cell_index_type>
Cell::move_tree (db::Cell &source_cell)
{
if (this == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell")));
}
db::Layout *target_layout = layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
db::CellMapping cm;
std::vector <db::cell_index_type> new_cells = cm.create_single_mapping_full (*target_layout, cell_index (), *source_layout, source_cell.cell_index ());
db::LayerMapping lm;
lm.create_full (*target_layout, *source_cell.layout ());
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_cell.cell_index ());
db::move_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ());
source_layout->prune_subcells (source_cell.cell_index ());
return new_cells;
}
void
Cell::move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm)
{
if (this == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell")));
}
db::Layout *target_layout = layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
db::LayerMapping lm;
lm.create_full (*target_layout, *source_cell.layout ());
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_cell.cell_index ());
db::move_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ());
}
void
Cell::move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm)
{
if (this == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell")));
}
db::Layout *target_layout = layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_cell.cell_index ());
db::move_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ());
}
}

View File

@ -55,6 +55,8 @@ template <class Coord> class generic_repository;
class Layout;
class Library;
class ImportLayerMapping;
class CellMapping;
class LayerMapping;
/**
* @brief The cell object
@ -937,6 +939,84 @@ public:
return mp_layout;
}
/**
* @brief Copies the shapes from the source cell's tree to this cell
*
* This variant uses the given cell mapping and layer mapping.
*/
void copy_tree_shapes (const db::Cell &source_cell, const db::CellMapping &cm);
/**
* @brief Copies the shapes from the source cell's tree to this cell
*
* This variant uses the given cell mapping and layer mapping.
*/
void copy_tree_shapes (const db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm);
/**
* @brief Copies instances and shapes from the source cell to this cell
*
* If the source and target layout are different ones, the whole cell tree of the source cell
* will be copied.
* This will create new cells in the target layout to accomodate the source cell tree.
* Returns an array with the freshly created cells which acommodate the cell tree.
*/
std::vector<db::cell_index_type> copy_tree (const db::Cell &source_cell);
/**
* @brief Copies the instances from the source to this cell.
*/
void copy_instances (const db::Cell &source_cell);
/**
* @brief Copies all shapes from the source cell to this cell
*/
void copy_shapes (const db::Cell &source_cell);
/**
* @brief Copies all shapes from the source cell to this cell using the given layer mapping
*/
void copy_shapes (const db::Cell &source_cell, const db::LayerMapping &layer_mapping);
/**
* @brief Moves the shapes from the source cell's tree to this cell
*
* This variant uses the given cell mapping and layer mapping.
*/
void move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm);
/**
* @brief Moves the shapes from the source cell's tree to this cell
*
* This variant uses the given cell mapping and layer mapping.
*/
void move_tree_shapes (db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm);
/**
* @brief Moves instances and shapes from the source cell to this cell
*
* If the source and target layout are different ones, the whole cell tree of the source cell
* will be copied.
* This will create new cells in the target layout to accomodate the source cell tree.
* Returns an array with the freshly created cells which acommodate the cell tree.
*/
std::vector<db::cell_index_type> move_tree (db::Cell &source_cell);
/**
* @brief Moves the instances from the source to this cell.
*/
void move_instances (db::Cell &source_cell);
/**
* @brief Moves all shapes from the source cell to this cell
*/
void move_shapes (db::Cell &source_cell);
/**
* @brief Moves all shapes from the source cell to this cell using the given layer mapping
*/
void move_shapes (db::Cell &source_cell, const db::LayerMapping &layer_mapping);
protected:
/**
* @brief Standard constructor: create an empty cell object

View File

@ -269,6 +269,17 @@ void CellMapping::clear ()
m_b2a_mapping.clear ();
}
std::vector<db::cell_index_type> CellMapping::source_cells () const
{
std::vector<db::cell_index_type> s;
s.reserve (m_b2a_mapping.size ());
for (iterator m = begin (); m != end (); ++m) {
s.push_back (m->first);
}
return s;
}
void
CellMapping::create_single_mapping (const db::Layout & /*layout_a*/, db::cell_index_type cell_index_a, const db::Layout & /*layout_b*/, db::cell_index_type cell_index_b)
{
@ -276,7 +287,19 @@ CellMapping::create_single_mapping (const db::Layout & /*layout_a*/, db::cell_in
map (cell_index_b, cell_index_a);
}
void
void
CellMapping::create_multi_mapping (const db::Layout & /*layout_a*/, const std::vector<db::cell_index_type> &cell_index_a, const db::Layout & /*layout_b*/, const std::vector<db::cell_index_type> &cell_index_b)
{
clear ();
if (cell_index_a.size () != cell_index_b.size ()) {
throw tl::Exception (tl::to_string (tr ("cell index arrays for A and B cells must have same length in 'create_multi_mapping'")));
}
for (std::vector<db::cell_index_type>::const_iterator ia = cell_index_a.begin (), ib = cell_index_b.begin (); ia != cell_index_a.end (); ++ia, ++ib) {
map (*ib, *ia);
}
}
void
CellMapping::create_from_names (const db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b)
{
clear ();
@ -295,31 +318,33 @@ CellMapping::create_from_names (const db::Layout &layout_a, db::cell_index_type
}
std::vector<db::cell_index_type>
CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells)
CellMapping::create_missing_mapping (db::Layout &layout_a, const db::Layout &layout_b, const std::vector<db::cell_index_type> &cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells)
{
std::vector<db::cell_index_type> new_cells;
do_create_missing_mapping (layout_a, cell_index_a, layout_b, cell_index_b, exclude_cells, include_cells, &new_cells, 0);
do_create_missing_mapping (layout_a, layout_b, cell_index_b, exclude_cells, include_cells, &new_cells, 0);
return new_cells;
}
std::vector<std::pair<db::cell_index_type, db::cell_index_type> >
CellMapping::create_missing_mapping2 (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells)
CellMapping::create_missing_mapping2 (db::Layout &layout_a, const db::Layout &layout_b, const std::vector<db::cell_index_type> &cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells)
{
std::vector<std::pair<db::cell_index_type, db::cell_index_type> > cell_pairs;
do_create_missing_mapping (layout_a, cell_index_a, layout_b, cell_index_b, exclude_cells, include_cells, 0, &cell_pairs);
do_create_missing_mapping (layout_a, layout_b, cell_index_b, exclude_cells, include_cells, 0, &cell_pairs);
return cell_pairs;
}
void
CellMapping::do_create_missing_mapping (db::Layout &layout_a, db::cell_index_type /*cell_index_a*/, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells, std::vector<db::cell_index_type> *new_cells_ptr, std::vector<std::pair<db::cell_index_type, db::cell_index_type> > *mapped_pairs)
CellMapping::do_create_missing_mapping (db::Layout &layout_a, const db::Layout &layout_b, const std::vector<db::cell_index_type> &cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells, std::vector<db::cell_index_type> *new_cells_ptr, std::vector<std::pair<db::cell_index_type, db::cell_index_type> > *mapped_pairs)
{
std::vector<db::cell_index_type> new_cells_int;
std::vector<db::cell_index_type> &new_cells = *(new_cells_ptr ? new_cells_ptr : &new_cells_int);
std::vector<db::cell_index_type> new_cells_b;
std::set<db::cell_index_type> called_b;
layout_b.cell (cell_index_b).collect_called_cells (called_b);
called_b.insert (cell_index_b);
for (std::vector<db::cell_index_type>::const_iterator i = cell_index_b.begin (); i != cell_index_b.end (); ++i) {
layout_b.cell (*i).collect_called_cells (called_b);
called_b.insert (*i);
}
for (std::set<db::cell_index_type>::const_iterator b = called_b.begin (); b != called_b.end (); ++b) {
if (m_b2a_mapping.find (*b) == m_b2a_mapping.end ()

View File

@ -81,7 +81,30 @@ public:
std::vector<db::cell_index_type> create_single_mapping_full (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b)
{
create_single_mapping (layout_a, cell_index_a, layout_b, cell_index_b);
return create_missing_mapping (layout_a, cell_index_a, layout_b, cell_index_b);
return create_missing_mapping (layout_a, layout_b, cell_index_b);
}
/**
* @brief Create a multi-cell mapping
*
* The mapping created by this function will map the cells of cell_indexes_b to cell_indexes_a. Both arrays need to have
* the same length.
* This cell mapping will not map the child cells. When used for hierarchical copy this will basically
* flatten the cells on copy.
*/
void create_multi_mapping (const db::Layout &layout_a, const std::vector<db::cell_index_type> &cell_indexes_a, const db::Layout &layout_b, const std::vector<db::cell_index_type> &cell_indexes_b);
/**
* @brief Create a single cell full mapping
*
* The mapping created by this function will map the cells of cell_indexes_a to cell_indexes_b. Both arrays need to have
* the same length. In addition, new cells for the child cells of all cell_indexes_b cells are created in layout_a and
* included in the mapping.
*/
std::vector<db::cell_index_type> create_multi_mapping_full (db::Layout &layout_a, const std::vector<db::cell_index_type> &cell_indexes_a, const db::Layout &layout_b, const std::vector<db::cell_index_type> &cell_indexes_b)
{
create_multi_mapping (layout_a, cell_indexes_a, layout_b, cell_indexes_b);
return create_missing_mapping (layout_a, layout_b, cell_indexes_b);
}
/**
@ -100,7 +123,7 @@ public:
std::vector<db::cell_index_type> create_from_geometry_full (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b)
{
create_from_geometry (layout_a, cell_index_a, layout_b, cell_index_b);
return create_missing_mapping (layout_a, cell_index_a, layout_b, cell_index_b);
return create_missing_mapping (layout_a, layout_b, cell_index_b);
}
/**
@ -119,7 +142,7 @@ public:
std::vector<db::cell_index_type> create_from_names_full (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b)
{
create_from_names (layout_a, cell_index_a, layout_b, cell_index_b);
return create_missing_mapping (layout_a, cell_index_a, layout_b, cell_index_b);
return create_missing_mapping (layout_a, layout_b, cell_index_b);
}
/**
@ -173,6 +196,11 @@ public:
return m_b2a_mapping.end ();
}
/**
* @brief Gets the source cells
*/
std::vector<db::cell_index_type> source_cells () const;
/**
* @brief Access to the mapping table
*/
@ -184,8 +212,9 @@ public:
/**
* @brief Creates mappings for all cells not mapped yet
*
* When constructing a cell mapping by explicit mapping (map (a, b)), some cells may be
* left unmapped. This method allows creating mappings for these missing cells by adding
* When constructing a cell mapping by explicit mapping (map (a, b)), some child cells of the
* mapped other cells may be left unmapped.
* This method allows creating mappings for these missing cells by adding
* new cells and the corresponding instances into the target layout_a.
*
* If given, "exclude_cells" can specify a list of cells not to map.
@ -195,7 +224,18 @@ public:
*
* The returned vector lists the new cells.
*/
std::vector<db::cell_index_type> create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells = 0, const std::set<db::cell_index_type> *include_cells = 0);
std::vector<db::cell_index_type> create_missing_mapping (db::Layout &layout_a, const db::Layout &layout_b, const std::vector<db::cell_index_type> &cell_index_b, const std::set<db::cell_index_type> *exclude_cells = 0, const std::set<db::cell_index_type> *include_cells = 0);
/**
* @brief A convenience version of create_missing_mappings which takes a single cell for cell_index_a and cell_index_b.
*/
std::vector<db::cell_index_type> create_missing_mapping (db::Layout &layout_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells = 0, const std::set<db::cell_index_type> *include_cells = 0)
{
std::vector<db::cell_index_type> cib;
cib.reserve (1);
cib.push_back (cell_index_b);
return create_missing_mapping (layout_a, layout_b, cib, exclude_cells, include_cells);
}
/**
* @brief Like create_missing_mapping, but returns the newly mapped pairs
@ -203,7 +243,21 @@ public:
* The first cell index of the pair is the old cell in layout_a, the second cell index
* is the new cell in layout_b.
*/
std::vector<std::pair<db::cell_index_type, db::cell_index_type> > create_missing_mapping2 (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells = 0, const std::set<db::cell_index_type> *include_cells = 0);
std::vector<std::pair<db::cell_index_type, db::cell_index_type> > create_missing_mapping2 (db::Layout &layout_a, const db::Layout &layout_b, const std::vector<db::cell_index_type> &cell_index_b, const std::set<db::cell_index_type> *exclude_cells = 0, const std::set<db::cell_index_type> *include_cells = 0);
/**
* @brief Like create_missing_mapping, but returns the newly mapped pairs (single-cell version)
*
* The first cell index of the pair is the old cell in layout_a, the second cell index
* is the new cell in layout_b.
*/
std::vector<std::pair<db::cell_index_type, db::cell_index_type> > create_missing_mapping2 (db::Layout &layout_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells = 0, const std::set<db::cell_index_type> *include_cells = 0)
{
std::vector<db::cell_index_type> cib;
cib.reserve (1);
cib.push_back (cell_index_b);
return create_missing_mapping2 (layout_a, layout_b, cib, exclude_cells, include_cells);
}
private:
void extract_unique (std::map <db::cell_index_type, std::vector<db::cell_index_type> >::const_iterator cand,
@ -213,7 +267,7 @@ private:
void dump_mapping (const std::map <db::cell_index_type, std::vector<db::cell_index_type> > &candidates,
const db::Layout &layout_a, const db::Layout &layout_b);
void do_create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells, std::vector<db::cell_index_type> *new_cells, std::vector<std::pair<db::cell_index_type, db::cell_index_type> > *mapped_pairs);
void do_create_missing_mapping (db::Layout &layout_a, const db::Layout &layout_b, const std::vector<db::cell_index_type> &cell_index_b, const std::set<db::cell_index_type> *exclude_cells, const std::set<db::cell_index_type> *include_cells, std::vector<db::cell_index_type> *new_cells, std::vector<std::pair<db::cell_index_type, db::cell_index_type> > *mapped_pairs);
std::map <db::cell_index_type, db::cell_index_type> m_b2a_mapping;
};

View File

@ -977,7 +977,7 @@ DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout
// Add new cells for the variants and (possible) devices which are cells added during the device
// extraction process
std::vector<std::pair<db::cell_index_type, db::cell_index_type> > new_pairs = cm->second.create_missing_mapping2 (*into_layout, into_cell, *source_layout, source_top, excluded_cells, included_cells);
std::vector<std::pair<db::cell_index_type, db::cell_index_type> > new_pairs = cm->second.create_missing_mapping2 (*into_layout, *source_layout, source_top, excluded_cells, included_cells);
// the variant's originals we are going to delete
std::set<db::cell_index_type> cells_to_delete;

View File

@ -35,6 +35,9 @@
#include "dbEdgePairs.h"
#include "dbEdges.h"
#include "dbTexts.h"
#include "dbCellMapping.h"
#include "dbLayerMapping.h"
#include "dbLayoutUtils.h"
#include "tlTimer.h"
#include "tlLog.h"
#include "tlInternational.h"
@ -1171,6 +1174,60 @@ Layout::topological_sort ()
}
void
Layout::copy_tree_shapes (const db::Layout &source_layout, const db::CellMapping &cm)
{
if (this == &source_layout) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same layout")));
}
db::ICplxTrans trans (source_layout.dbu () / dbu ());
db::LayerMapping lm;
lm.create_full (*this, source_layout);
db::copy_shapes (*this, source_layout, trans, cm.source_cells (), cm.table (), lm.table ());
}
void
Layout::copy_tree_shapes (const db::Layout &source_layout, const db::CellMapping &cm, const db::LayerMapping &lm)
{
if (this == &source_layout) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same layout")));
}
db::ICplxTrans trans (source_layout.dbu () / dbu ());
db::copy_shapes (*this, source_layout, trans, cm.source_cells (), cm.table (), lm.table ());
}
void
Layout::move_tree_shapes (db::Layout &source_layout, const db::CellMapping &cm)
{
if (this == &source_layout) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same layout")));
}
db::ICplxTrans trans (source_layout.dbu () / dbu ());
db::LayerMapping lm;
lm.create_full (*this, source_layout);
db::move_shapes (*this, source_layout, trans, cm.source_cells (), cm.table (), lm.table ());
}
void
Layout::move_tree_shapes (db::Layout &source_layout, const db::CellMapping &cm, const db::LayerMapping &lm)
{
if (this == &source_layout) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same layout")));
}
db::ICplxTrans trans (source_layout.dbu () / dbu ());
db::move_shapes (*this, source_layout, trans, cm.source_cells (), cm.table (), lm.table ());
}
bool
Layout::is_valid_cell_index (cell_index_type ci) const
{

View File

@ -67,6 +67,8 @@ class Region;
class Edges;
class EdgePairs;
class Texts;
class CellMapping;
class LayerMapping;
template <class Coord> class generic_repository;
typedef generic_repository<db::Coord> GenericRepository;
@ -1257,6 +1259,34 @@ public:
*/
void delete_layer (unsigned int n);
/**
* @brief Copies the shapes of certain cells from the given source layout into this layout
*
* The affected cells are derived from the cell mapping object.
*/
void copy_tree_shapes (const db::Layout &source_layout, const db::CellMapping &cm);
/**
* @brief Copies the shapes of certain cells from the given source layout into this layout using the given layer mapping
*
* The affected cells are derived from the cell mapping object.
*/
void copy_tree_shapes (const db::Layout &source_layout, const db::CellMapping &cm, const db::LayerMapping &lm);
/**
* @brief Moves the shapes of certain cells from the given source layout into this layout
*
* The affected cells are derived from the cell mapping object.
*/
void move_tree_shapes (db::Layout &source_layout, const db::CellMapping &cm);
/**
* @brief Moves the shapes of certain cells from the given source layout into this layout using the given layer mapping
*
* The affected cells are derived from the cell mapping object.
*/
void move_tree_shapes (db::Layout &source_layout, const db::CellMapping &cm, const db::LayerMapping &lm);
/**
* @brief Return true, if the cell index is a valid one
*/

View File

@ -42,7 +42,7 @@ namespace db
*
* This implementation will create new layers if required.
*/
class DirectLayerMapping
class DB_PUBLIC DirectLayerMapping
: public ImportLayerMapping
{
public:

View File

@ -108,32 +108,74 @@ namespace db
}
void
LoadLayoutOptions::set_option_by_name (const std::string &method, const tl::Variant &value)
LoadLayoutOptions::set_option_by_method (const std::string &method, const tl::Variant &value)
{
// Utilizes the GSI binding to set the values
tl::Variant options_ref = tl::Variant::make_variant_ref (this);
const tl::EvalClass *eval_cls = options_ref.user_cls ()->eval_cls ();
tl::ExpressionParserContext context;
tl::Variant ref = tl::Variant::make_variant_ref (this);
tl::Variant out;
std::vector<tl::Variant> args;
args.push_back (value);
eval_cls->execute (context, out, options_ref, method + "=", args);
tl::Extractor ex (method.c_str ());
while (! ex.at_end ()) {
std::string m;
ex.read_word (m, "_=");
if (! ex.at_end ()) {
ex.expect (".");
}
tl::Variant out;
std::vector<tl::Variant> args;
if (ex.at_end ()) {
args.push_back (value);
}
tl::ExpressionParserContext context;
ref.user_cls ()->eval_cls ()->execute (context, out, ref, m, args);
ref = out;
}
}
tl::Variant
LoadLayoutOptions::get_option_by_method (const std::string &method)
{
// Utilizes the GSI binding to set the values
tl::Variant ref = tl::Variant::make_variant_ref (this);
tl::Extractor ex (method.c_str ());
while (! ex.at_end ()) {
std::string m;
ex.read_word (m, "_=");
if (! ex.at_end ()) {
ex.expect (".");
}
tl::Variant out;
std::vector<tl::Variant> args;
tl::ExpressionParserContext context;
ref.user_cls ()->eval_cls ()->execute (context, out, ref, m, args);
ref = out;
}
return ref;
}
void
LoadLayoutOptions::set_option_by_name (const std::string &method, const tl::Variant &value)
{
return set_option_by_method (method + "=", value);
}
tl::Variant
LoadLayoutOptions::get_option_by_name (const std::string &method)
{
// Utilizes the GSI binding to set the values
tl::Variant options_ref = tl::Variant::make_variant_ref (this);
const tl::EvalClass *eval_cls = options_ref.user_cls ()->eval_cls ();
tl::ExpressionParserContext context;
tl::Variant out;
std::vector<tl::Variant> args;
eval_cls->execute (context, out, options_ref, method, args);
return out;
return get_option_by_method (method);
}
}

View File

@ -200,6 +200,21 @@ public:
*/
tl::Variant get_option_by_name (const std::string &name);
/**
* @brief Sets a layout reader option by calling method
*
* The name is taken to be a GSI method which is called to set the
* option.
*/
void set_option_by_method (const std::string &name, const tl::Variant &value);
/**
* @brief Gets a layout reader option by calling a method
*
* See "set_option_by_method" for details.
*/
tl::Variant get_option_by_method (const std::string &name);
private:
std::map <std::string, FormatSpecificReaderOptions *> m_options;

View File

@ -24,6 +24,8 @@
#include "dbReader.h"
#include "dbStream.h"
#include "tlClassRegistry.h"
#include "tlTimer.h"
#include "tlLog.h"
namespace db
{
@ -74,5 +76,21 @@ Reader::~Reader ()
}
}
const db::LayerMap &
Reader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
{
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading file: ")) + m_stream.source ());
return mp_actual_reader->read (layout, options);
}
const db::LayerMap &
Reader::read (db::Layout &layout)
{
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading file: ")) + m_stream.source ());
return mp_actual_reader->read (layout);
}
}

View File

@ -125,10 +125,7 @@ public:
* @param layout The layout object to write to
* @param options The LayerMap object
*/
const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options)
{
return mp_actual_reader->read (layout, options);
}
const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options);
/**
* @brief The basic read method (without mapping)
@ -143,10 +140,7 @@ public:
* @param layout The layout object to write to
* @return The LayerMap object
*/
const db::LayerMap &read (db::Layout &layout)
{
return mp_actual_reader->read (layout);
}
const db::LayerMap &read (db::Layout &layout);
/**
* @brief Returns a format describing the file format found

View File

@ -137,6 +137,17 @@ LayerMap::is_placeholder (unsigned int l) const
return (m_placeholders.size () > std::numeric_limits<unsigned int>::max () - l);
}
const db::LayerProperties *
LayerMap::target (unsigned int l) const
{
std::map<unsigned int, LayerProperties>::const_iterator i = m_target_layers.find (l);
if (i != m_target_layers.end ()) {
return & i->second;
} else {
return 0;
}
}
std::pair<bool, unsigned int>
LayerMap::logical (const db::LayerProperties &p, db::Layout &layout) const
{

View File

@ -236,6 +236,13 @@ public:
*/
std::pair<bool, unsigned int> logical (const db::LDPair &p, db::Layout &layout) const;
/**
* @brief Gets the target layer for a given logical layer
*
* Returns 0 if no target layer mapping is supplied.
*/
const db::LayerProperties *target (unsigned int l) const;
/**
* @brief String description for the mapping of a logical layer
*

View File

@ -26,6 +26,8 @@
#include "tlClassRegistry.h"
#include "tlAssert.h"
#include "tlStream.h"
#include "tlTimer.h"
#include "tlLog.h"
namespace db
{
@ -54,6 +56,8 @@ Writer::~Writer ()
void
Writer::write (db::Layout &layout, tl::OutputStream &stream)
{
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Writing file: ")) + stream.path ());
tl_assert (mp_writer != 0);
mp_writer->write (layout, stream, m_options);
}

View File

@ -1206,298 +1206,42 @@ begin_shapes_rec_overlapping_um (const db::Cell *cell, unsigned int layer, db::D
static void copy_shapes2 (db::Cell *cell, const db::Cell &source_cell, const db::LayerMapping &layer_mapping)
{
if (cell == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell")));
}
db::Layout *target_layout = cell->layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
const db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
if (target_layout != source_layout) {
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
for (std::map<unsigned int, unsigned int>::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) {
cell->shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm);
}
} else {
for (std::map<unsigned int, unsigned int>::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) {
cell->shapes (lm->second).insert (source_cell.shapes (lm->first));
}
}
cell->copy_shapes (source_cell, layer_mapping);
}
static void copy_shapes1 (db::Cell *cell, const db::Cell &source_cell)
{
if (cell == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell")));
}
db::Layout *layout = cell->layout ();
if (! layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
if (layout != source_cell.layout ()) {
if (! source_cell.layout ()) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::LayerMapping lm;
lm.create_full (*layout, *source_cell.layout ());
copy_shapes2 (cell, source_cell, lm);
} else {
for (db::Layout::layer_iterator l = layout->begin_layers (); l != layout->end_layers (); ++l) {
cell->shapes ((*l).first).insert (source_cell.shapes ((*l).first));
}
}
}
static void copy_instances (db::Cell *cell, const db::Cell &source_cell)
{
if (cell == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot copy instances within the same cell")));
}
if (cell->layout () != source_cell.layout ()) {
throw tl::Exception (tl::to_string (tr ("Cells do not reside in the same layout")));
}
for (db::Cell::const_iterator i = source_cell.begin (); ! i.at_end (); ++i) {
cell->insert (*i);
}
}
static std::vector<db::cell_index_type> copy_tree (db::Cell *cell, const db::Cell &source_cell)
{
if (cell == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell")));
}
db::Layout *target_layout = cell->layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
const db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
db::CellMapping cm;
std::vector <db::cell_index_type> new_cells = cm.create_single_mapping_full (*target_layout, cell->cell_index (), *source_layout, source_cell.cell_index ());
db::LayerMapping lm;
lm.create_full (*target_layout, *source_cell.layout ());
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_cell.cell_index ());
db::copy_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ());
return new_cells;
cell->copy_shapes (source_cell);
}
static void copy_tree_shapes2 (db::Cell *cell, const db::Cell &source_cell, const db::CellMapping &cm)
{
if (cell == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell")));
}
db::Layout *target_layout = cell->layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
const db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
db::LayerMapping lm;
lm.create_full (*target_layout, *source_cell.layout ());
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_cell.cell_index ());
db::copy_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ());
cell->copy_tree_shapes (source_cell, cm);
}
static void copy_tree_shapes3 (db::Cell *cell, const db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm)
{
if (cell == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same cell")));
}
db::Layout *target_layout = cell->layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
const db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_cell.cell_index ());
db::copy_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ());
cell->copy_tree_shapes (source_cell, cm, lm);
}
static void move_shapes2 (db::Cell *cell, db::Cell &source_cell, const db::LayerMapping &layer_mapping)
{
if (cell == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell")));
}
db::Layout *target_layout = cell->layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
if (target_layout != source_layout) {
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
for (std::map<unsigned int, unsigned int>::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) {
cell->shapes (lm->second).insert_transformed (source_cell.shapes (lm->first), trans, pm);
source_cell.shapes (lm->first).clear ();
}
} else {
for (std::map<unsigned int, unsigned int>::const_iterator lm = layer_mapping.begin (); lm != layer_mapping.end (); ++lm) {
cell->shapes (lm->second).insert (source_cell.shapes (lm->first));
source_cell.shapes (lm->first).clear ();
}
}
cell->move_shapes (source_cell, layer_mapping);
}
static void move_shapes1 (db::Cell *cell, db::Cell &source_cell)
{
if (cell == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell")));
}
db::Layout *layout = cell->layout ();
if (! layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
if (layout != source_cell.layout ()) {
if (! source_cell.layout ()) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::LayerMapping lm;
lm.create_full (*layout, *source_cell.layout ());
move_shapes2 (cell, source_cell, lm);
} else {
for (db::Layout::layer_iterator l = layout->begin_layers (); l != layout->end_layers (); ++l) {
cell->shapes ((*l).first).insert (source_cell.shapes ((*l).first));
source_cell.shapes ((*l).first).clear ();
}
}
}
static void move_instances (db::Cell *cell, db::Cell &source_cell)
{
if (cell == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot move instances within the same cell")));
}
if (cell->layout () != source_cell.layout ()) {
throw tl::Exception (tl::to_string (tr ("Cells do not reside in the same layout")));
}
for (db::Cell::const_iterator i = source_cell.begin (); ! i.at_end (); ++i) {
cell->insert (*i);
}
source_cell.clear_insts ();
}
static std::vector<db::cell_index_type> move_tree (db::Cell *cell, db::Cell &source_cell)
{
if (cell == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell")));
}
db::Layout *target_layout = cell->layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
db::CellMapping cm;
std::vector <db::cell_index_type> new_cells = cm.create_single_mapping_full (*target_layout, cell->cell_index (), *source_layout, source_cell.cell_index ());
db::LayerMapping lm;
lm.create_full (*target_layout, *source_cell.layout ());
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_cell.cell_index ());
db::move_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ());
source_layout->prune_subcells (source_cell.cell_index ());
return new_cells;
cell->move_shapes (source_cell);
}
static void move_tree_shapes2 (db::Cell *cell, db::Cell &source_cell, const db::CellMapping &cm)
{
if (cell == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell")));
}
db::Layout *target_layout = cell->layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
db::LayerMapping lm;
lm.create_full (*target_layout, *source_cell.layout ());
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_cell.cell_index ());
db::move_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ());
cell->move_tree_shapes (source_cell, cm);
}
static void move_tree_shapes3 (db::Cell *cell, db::Cell &source_cell, const db::CellMapping &cm, const db::LayerMapping &lm)
{
if (cell == &source_cell) {
throw tl::Exception (tl::to_string (tr ("Cannot move shapes within the same cell")));
}
db::Layout *target_layout = cell->layout ();
if (! target_layout) {
throw tl::Exception (tl::to_string (tr ("Cell does not reside in a layout")));
}
db::Layout *source_layout = source_cell.layout ();
if (! source_layout) {
throw tl::Exception (tl::to_string (tr ("Source cell does not reside in a layout")));
}
db::PropertyMapper pm (*target_layout, *source_layout);
db::ICplxTrans trans (source_layout->dbu () / target_layout->dbu ());
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (source_cell.cell_index ());
db::move_shapes (*target_layout, *source_layout, trans, source_cells, cm.table (), lm.table ());
cell->move_tree_shapes (source_cell, cm, lm);
}
static void
@ -1686,6 +1430,21 @@ static const db::Shapes *shapes_of_cell_const (const db::Cell *cell, unsigned in
return &cell->shapes (layer);
}
static db::Cell *dup_cell (const db::Cell *cell)
{
if (! cell->layout ()) {
throw tl::Exception (tl::to_string (tr ("Cannot create a copy of a cell which is not part of a layout")));
}
db::Layout *layout = const_cast<db::Layout *> (cell->layout ());
db::Cell *new_cell = &layout->cell (layout->add_cell (layout->cell_name (cell->cell_index ())));
new_cell->copy_shapes (*cell);
new_cell->copy_instances (*cell);
return new_cell;
}
Class<db::Cell> decl_Cell ("db", "Cell",
gsi::method ("name", &db::Cell::get_basic_name,
"@brief Gets the cell's name\n"
@ -1759,6 +1518,15 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"\n"
"This method has been introduced in version 0.23.\n"
) +
gsi::method_ext ("dup", &dup_cell,
"@brief Creates a copy of the cell\n"
"\n"
"This method will create a copy of the cell. The new cell will be member of the same layout the original cell "
"was member of. The copy will inherit all shapes and instances, but get "
"a different cell_index and a modified name as duplicate cell names are not allowed in the same layout.\n"
"\n"
"This method has been introduced in version 0.27.\n"
) +
gsi::method ("shapes", (db::Cell::shapes_type &(db::Cell::*) (unsigned int)) &db::Cell::shapes, gsi::arg ("layer_index"),
"@brief Returns the shapes list of the given layer\n"
"\n"
@ -2092,7 +1860,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"\n"
"This method has been added in version 0.23.\n"
) +
gsi::method_ext ("copy_instances", &copy_instances, gsi::arg ("source_cell"),
gsi::method ("copy_instances", &db::Cell::copy_instances, gsi::arg ("source_cell"),
"@brief Copies the instances of child cells in the source cell to this cell\n"
"@param source_cell The cell where the instances are copied from\n"
"The source cell must reside in the same layout than this cell. The instances of "
@ -2106,7 +1874,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"\n"
"This method has been added in version 0.23.\n"
) +
gsi::method_ext ("copy_tree", &copy_tree, gsi::arg ("source_cell"),
gsi::method ("copy_tree", &db::Cell::copy_tree, gsi::arg ("source_cell"),
"@brief Copies the cell tree of the given cell into this cell\n"
"@param source_cell The cell from where to copy the cell tree\n"
"@return A list of indexes of newly created cells\n"
@ -2196,7 +1964,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"\n"
"This method has been added in version 0.23.\n"
) +
gsi::method_ext ("move_instances", &move_instances, gsi::arg ("source_cell"),
gsi::method ("move_instances", &db::Cell::move_instances, gsi::arg ("source_cell"),
"@brief Moves the instances of child cells in the source cell to this cell\n"
"@param source_cell The cell where the instances are moved from\n"
"The source cell must reside in the same layout than this cell. The instances of "
@ -2210,7 +1978,7 @@ Class<db::Cell> decl_Cell ("db", "Cell",
"\n"
"This method has been added in version 0.23.\n"
) +
gsi::method_ext ("move_tree", &move_tree, gsi::arg ("source_cell"),
gsi::method ("move_tree", &db::Cell::move_tree, gsi::arg ("source_cell"),
"@brief Moves the cell tree of the given cell into this cell\n"
"@param source_cell The cell from where to move the cell tree\n"
"@return A list of indexes of newly created cells\n"

View File

@ -76,10 +76,42 @@ Class<db::CellMapping> decl_CellMapping ("db", "CellMapping",
"The cell mapping is created for cell_b to cell_a in the respective layouts. "
"This method clears the mapping and creates one for the single cell pair. "
"In addition and in contrast to \\for_single_cell, this method completes the mapping by adding all the child cells "
"of cell_b to layout_a and creating the proper instances. "
"of cell_b to layout_a and creating the proper instances.\n"
"\n"
"This method has been introduced in version 0.23."
) +
gsi::method ("for_multi_cells", &db::CellMapping::create_multi_mapping, gsi::arg ("layout_a"), gsi::arg ("cell_indexes_a"), gsi::arg ("layout_b"), gsi::arg ("cell_indexes_b"),
"@brief Initializes the cell mapping for top-level identity\n"
"\n"
"@param layout_a The target layout.\n"
"@param cell_indexes_a A list of cell indexes for the target cells.\n"
"@param layout_b The source layout.\n"
"@param cell_indexes_b A list of cell indexes for the source cells (same number of indexes than \\cell_indexes_a).\n"
"\n"
"The cell mapping is created for cells from cell_indexes_b to cell from cell_indexes_a in the respective layouts. "
"This method clears the mapping and creates one for each cell pair from cell_indexes_b vs. cell_indexes_a. "
"If used for \\Layout#copy_tree or \\Layout#move_tree, this cell mapping will essentially "
"flatten the source cells in the target layout.\n"
"\n"
"This method is equivalent to \\clear, followed by \\map(cell_index_a, cell_index_b) for each cell pair.\n"
"\n"
"This method has been introduced in version 0.27."
) +
gsi::method ("for_multi_cells_full", &db::CellMapping::create_multi_mapping_full, gsi::arg ("layout_a"), gsi::arg ("cell_indexes_a"), gsi::arg ("layout_b"), gsi::arg ("cell_indexes_b"),
"@brief Initializes the cell mapping for top-level identity\n"
"\n"
"@param layout_a The target layout.\n"
"@param cell_indexes_a A list of cell indexes for the target cells.\n"
"@param layout_b The source layout.\n"
"@param cell_indexes_b A list of cell indexes for the source cells (same number of indexes than \\cell_indexes_a).\n"
"\n"
"The cell mapping is created for cells from cell_indexes_b to cell from cell_indexes_a in the respective layouts. "
"This method clears the mapping and creates one for each cell pair from cell_indexes_b vs. cell_indexes_a. "
"In addition and in contrast to \\for_multi_cells, this method completes the mapping by adding all the child cells "
"of all cells in cell_indexes_b to layout_a and creating the proper instances.\n"
"\n"
"This method has been introduced in version 0.27."
) +
gsi::method ("from_geometry_full", &db::CellMapping::create_from_geometry_full, gsi::arg ("layout_a"), gsi::arg ("cell_index_a"), gsi::arg ("layout_b"), gsi::arg ("cell_index_b"),
"@brief Initializes the cell mapping using the geometrical identity in full mapping mode\n"
"\n"
@ -234,6 +266,26 @@ Class<db::CellMapping> decl_CellMapping ("db", "CellMapping",
"\n"
"CellMapping objects play a role mainly in the hierarchical copy or move operations of \\Layout. "
"However, use is not restricted to these applications.\n"
"\n"
"Here is one example for using \\CellMapping. It extracts cells 'A', 'B' and 'C' from one layout "
"and copies them to another. It will also copy all shapes and all child cells. Child cells which are "
"shared between the three initial cells will be shared in the target layout too.\n"
"\n"
"@code\n"
"cell_names = [ \"A\", \"B\", \"C\" ]\n"
"\n"
"source = RBA::Layout::new\n"
"source.read(\"input.gds\")\n"
"\n"
"target = RBA::Layout::new\n"
"\n"
"source_cells = cell_names.collect { |n| source.cell_by_name(n).cell_index }\n"
"target_cells = cell_names.collect { |n| target.create_cell(n).cell_index }\n"
"\n"
"cm = RBA::CellMapping::new\n"
"cm.for_multi_cells_full(source, source_cells, target, target_cells)\n"
"target.copy_tree_shapes(source, cm)\n"
"@/code\n"
);
}

View File

@ -37,6 +37,8 @@
#include "dbEdgePairs.h"
#include "dbTexts.h"
#include "dbLayoutUtils.h"
#include "dbLayerMapping.h"
#include "dbCellMapping.h"
#include "tlStream.h"
namespace gsi
@ -822,6 +824,56 @@ static void scale_and_snap2 (db::Layout *layout, db::cell_index_type ci, db::Coo
scale_and_snap (*layout, layout->cell (ci), g, m, d);
}
static void copy_tree_shapes2 (db::Layout *layout, const db::Layout &source_layout, const db::CellMapping &cm)
{
if (layout == &source_layout) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same layout")));
}
db::ICplxTrans trans (source_layout.dbu () / layout->dbu ());
db::LayerMapping lm;
lm.create_full (*layout, source_layout);
db::copy_shapes (*layout, source_layout, trans, cm.source_cells (), cm.table (), lm.table ());
}
static void copy_tree_shapes3 (db::Layout *layout, const db::Layout &source_layout, const db::CellMapping &cm, const db::LayerMapping &lm)
{
if (layout == &source_layout) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same layout")));
}
db::ICplxTrans trans (source_layout.dbu () / layout->dbu ());
db::copy_shapes (*layout, source_layout, trans, cm.source_cells (), cm.table (), lm.table ());
}
static void move_tree_shapes2 (db::Layout *layout, db::Layout &source_layout, const db::CellMapping &cm)
{
if (layout == &source_layout) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same layout")));
}
db::ICplxTrans trans (source_layout.dbu () / layout->dbu ());
db::LayerMapping lm;
lm.create_full (*layout, source_layout);
db::move_shapes (*layout, source_layout, trans, cm.source_cells (), cm.table (), lm.table ());
}
static void move_tree_shapes3 (db::Layout *layout, db::Layout &source_layout, const db::CellMapping &cm, const db::LayerMapping &lm)
{
if (layout == &source_layout) {
throw tl::Exception (tl::to_string (tr ("Cannot copy shapes within the same layout")));
}
db::ICplxTrans trans (source_layout.dbu () / layout->dbu ());
db::move_shapes (*layout, source_layout, trans, cm.source_cells (), cm.table (), lm.table ());
}
Class<db::MetaInfo> decl_LayoutMetaInfo ("db", "LayoutMetaInfo",
gsi::constructor ("new", &layout_meta_info_ctor, gsi::arg ("name"), gsi::arg ("value"), gsi::arg ("description", std::string ()),
"@brief Creates a layout meta info object\n"
@ -1529,6 +1581,49 @@ Class<db::Layout> decl_Layout ("db", "Layout",
"an index in the range of 0 to layers-1 needs to be a valid layer. These layers can be either valid, "
"special or unused. Use \\is_valid_layer? and \\is_special_layer? to test for the first two states.\n"
) +
gsi::method_ext ("copy_tree_shapes", &copy_tree_shapes2, gsi::arg ("source_layout"), gsi::arg ("cell_mapping"),
"@brief Copies the shapes for all given mappings in the \\CellMapping object\n"
"@param source_layout The layout where to take the shapes from\n"
"@param cell_mapping The cell mapping object that determines how cells are identified between source and target layout\n"
"\n"
"Provide a \\CellMapping object to specify pairs of cells which are mapped from the source layout to this "
"layout. When constructing such a cell mapping object for example with \\CellMapping#for_multi_cell_full, use self "
"as the target layout. During the cell mapping construction, the cell mapper will usually create a suitable target "
"hierarchy already. After having completed the cell mapping, use \\copy_tree_shapes to copy over the shapes from "
"the source to the target layout.\n"
"\n"
"This method has been added in version 0.27.\n"
) +
gsi::method_ext ("copy_tree_shapes", &copy_tree_shapes3, gsi::arg ("source_layout"), gsi::arg ("cell_mapping"), gsi::arg ("layer_mapping"),
"@brief Copies the shapes for all given mappings in the \\CellMapping object using the given layer mapping\n"
"@param source_layout The layout where to take the shapes from\n"
"@param cell_mapping The cell mapping object that determines how cells are identified between source and target layout\n"
"@param layer_mapping Specifies which layers are copied from the source layout to the target layout\n"
"\n"
"Provide a \\CellMapping object to specify pairs of cells which are mapped from the source layout to this "
"layout. When constructing such a cell mapping object for example with \\CellMapping#for_multi_cell_full, use self "
"as the target layout. During the cell mapping construction, the cell mapper will usually create a suitable target "
"hierarchy already. After having completed the cell mapping, use \\copy_tree_shapes to copy over the shapes from "
"the source to the target layout.\n"
"\n"
"This method has been added in version 0.27.\n"
) +
gsi::method_ext ("move_tree_shapes", &move_tree_shapes2, gsi::arg ("source_layout"), gsi::arg ("cell_mapping"),
"@brief Moves the shapes for all given mappings in the \\CellMapping object\n"
"\n"
"This method acts like the corresponding \\copy_tree_shapes method, but removes the shapes from the source layout "
"after they have been copied.\n"
"\n"
"This method has been added in version 0.27.\n"
) +
gsi::method_ext ("move_tree_shapes", &move_tree_shapes3, gsi::arg ("source_layout"), gsi::arg ("cell_mapping"), gsi::arg ("layer_mapping"),
"@brief Moves the shapes for all given mappings in the \\CellMapping object using the given layer mapping\n"
"\n"
"This method acts like the corresponding \\copy_tree_shapes method, but removes the shapes from the source layout "
"after they have been copied.\n"
"\n"
"This method has been added in version 0.27.\n"
) +
gsi::method_ext ("scale_and_snap", &scale_and_snap1, gsi::arg ("cell"), gsi::arg ("grid"), gsi::arg ("mult"), gsi::arg ("div"),
"@brief Scales and snaps the layout below a given cell by the given rational factor and snaps to the given grid\n"
"\n"

View File

@ -453,3 +453,40 @@ TEST(6)
EXPECT_EQ (l2s (h), "a0top#0:cell_index=1 r90 0,0 array=(0,10,10,0 5x2),cell_index=2 r90 0,0 array=(0,10,10,0 5x2);a4#1:;a5#2:");
}
// Multi-mapping
TEST(7)
{
std::auto_ptr<db::Layout> g (new db::Layout ());
db::Cell &a0 (g->cell (g->add_cell ("a0")));
db::Cell &a1 (g->cell (g->add_cell ("a1")));
db::Cell &a2 (g->cell (g->add_cell ("a2")));
db::Cell &a3 (g->cell (g->add_cell ("a3")));
db::Cell &a4 = g->cell (g->add_cell ("a4"));
db::Cell &a5 = g->cell (g->add_cell ("a5"));
a3.insert (db::CellInstArray (db::CellInst (a4.cell_index ()), db::Trans ()));
a3.insert (db::CellInstArray (db::CellInst (a5.cell_index ()), db::Trans ()));
a1.insert (db::CellInstArray (db::CellInst (a4.cell_index ()), db::Trans ()));
a1.insert (db::CellInstArray (db::CellInst (a3.cell_index ()), db::Trans ()));
a2.insert (db::CellInstArray (db::CellInst (a4.cell_index ()), db::Trans ()));
db::Layout h;
db::Cell &b0 (h.cell (h.add_cell ("b0")));
db::Cell &b1 (h.cell (h.add_cell ("b1")));
db::Cell &b2 (h.cell (h.add_cell ("b2")));
db::CellMapping cm;
std::vector<db::cell_index_type> cib, cia;
cia.push_back (a0.cell_index ());
cia.push_back (a1.cell_index ());
cia.push_back (a2.cell_index ());
cib.push_back (b0.cell_index ());
cib.push_back (b1.cell_index ());
cib.push_back (b2.cell_index ());
cm.create_multi_mapping_full (h, cib, *g, cia);
EXPECT_EQ (m2s (cm, *g, h), "a0->b0;a1->b1;a2->b2;a3->a3;a4->a4;a5->a5");
EXPECT_EQ (l2s (h), "b0#0:;b1#1:cell_index=3 r0 0,0,cell_index=4 r0 0,0;b2#2:cell_index=4 r0 0,0;a3#3:cell_index=4 r0 0,0,cell_index=5 r0 0,0;a4#4:;a5#5:");
}

View File

@ -12,6 +12,7 @@
<topics>
<topic href="/about/layer_mapping.xml"/>
<topic href="/about/layer_specs.xml"/>
<topic href="/about/transformations.xml"/>
<topic href="/about/expressions.xml"/>
<topic href="/about/variant_notation.xml"/>

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
<doc>
<title>About Layer Specifications</title>
<p>
Layer specifications are used in various places, for example in layer mapping
files (<link href="/about/layer_mapping.xml"/>).
Layer specifications are used inside the database to give a layer a name or
a number/datatype pair or both. Layer specifications are the text representation
of <class_doc href="LayerInfo">LayerInfo</class_doc> objects.
</p>
<p>
Blanks within layer specifications are ignored and can be put between
the different components of the specification.
</p>
<p>
A simple number for the specification will indicate a layer with this layer number and a
datatype of zero:
</p>
<pre>17</pre>
<p>will give layer 17, datatype 0.
</p>
<p>
A number followed by a slash and another number will indicate a layer number
and datatype:
</p>
<pre>17/5</pre>
<p>
will give layer 17, datatype 5.
</p>
<p>
Layers can be named. Named layers are present in DXF, CIF or other formats
which don't use the GDS layer/datatype number scheme. Just giving a name
will indicate such a layer:
</p>
<pre>METAL1</pre>
<p>
will give a named layer called "METAL1".
</p>
<p>
If you want to use a name that is a number, use quotes:
</p>
<pre>"17"</pre>
<p>
will give a named layer called "17".
</p>
<p>
If you want to use a name that includes blanks, put it into quotes
as well:
</p>
<pre>"METAL 1"</pre>
<p>
will give a named layer called "METAL 1" (however, such layer names are usually illegal).
</p>
<p>
Finally, a layer can have both a name and layer/datatype numbers.
In this case, add the layer/datatype number to the name in round
brackets:
</p>
<pre>METAL1 (17)</pre>
<p>
will give a layer named "METAL1" with layer 17 and datatype 0 and
</p>
<pre>METAL1 (17/5)</pre>
<p>
will give a layer named "METAL1" with layer 17 and datatype 5.
</p>
<h4>Layer specifications as targets</h4>
<p>
When used in a target context (e.g. for layer mapping), a layer specification
can use wildcards and relative layer/datatype specifications.
Using "*" instead of a layer or datatype number means to reuse the source
layer or datatype number. Using "+x" or "-x" for layer or datatype number means
to add or subtract "x" from the source layer or datatype number.
</p>
</doc>

View File

@ -21,6 +21,7 @@
<file alias="ide_snapshot.png">doc/about/ide_snapshot.png</file>
<file alias="index.xml">doc/about/index.xml</file>
<file alias="layer_mapping.xml">doc/about/layer_mapping.xml</file>
<file alias="layer_specs.xml">doc/about/layer_specs.xml</file>
<file alias="layer_sources.xml">doc/about/layer_sources.xml</file>
<file alias="macro_editor.xml">doc/about/macro_editor.xml</file>
<file alias="macro_in_menu.xml">doc/about/macro_in_menu.xml</file>

View File

@ -1839,10 +1839,15 @@ LayerPropertiesList::load (tl::XMLSource &stream, std::vector <lay::LayerPropert
lay::LayerPropertiesList properties_list;
layer_prop_list_structure.parse (stream, properties_list);
properties_lists.push_back (properties_list);
} catch (...) {
// "new" way
stream.reset ();
layer_prop_lists_structure.parse (stream, properties_lists);
} catch (tl::Exception &ex) {
try {
// "new" way
stream.reset ();
layer_prop_lists_structure.parse (stream, properties_lists);
} catch (tl::Exception &) {
// the first exception is likely to be the root cause, so let's rather throw this one
throw ex;
}
}
}

View File

@ -818,8 +818,6 @@ CIFReader::read_cell (db::Layout &layout, db::Cell &cell, double sf, int level)
void
CIFReader::do_read (db::Layout &layout)
{
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("File read: ")) + m_stream.source ());
try {
double sf = 0.01 / m_dbu;

View File

@ -379,8 +379,6 @@ DXFReader::open_layer (db::Layout &layout, const std::string &n)
void
DXFReader::do_read (db::Layout &layout, db::cell_index_type top)
{
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("File read: ")) + m_stream.source ());
// create the zero layer - this is not mapped to GDS but can be specified in the layer mapping as
// a layer named "0".
std::pair<bool, unsigned int> ll = layer_map ().logical (zero_layer_name, layout);

View File

@ -233,8 +233,6 @@ eq_y (const GDS2XY &a, const GDS2XY &b)
void
GDS2ReaderBase::do_read (db::Layout &layout)
{
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("File read: ")) + path ());
m_cellname = "";
m_libname = "";
m_mapped_cellnames.clear ();

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,8 @@
namespace db
{
struct DEFImporterGroup;
/**
* @brief The DEF importer object
*/
@ -54,18 +56,39 @@ public:
* This method reads the layout specified into the given layout.
* Multiple LEF files can be read.
*/
void read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFLayerDelegate &ld);
void read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state);
/**
* @brief Provided for test purposes
*/
void finish_lef (Layout &layout);
protected:
void do_read (db::Layout &layout);
private:
LEFImporter m_lef_importer;
std::map<std::string, std::map<std::string, double> > m_nondefault_widths;
std::map<std::string, std::map<std::string, db::Coord> > m_nondefault_widths;
std::map<std::string, ViaDesc> m_via_desc;
std::map<int, db::Polygon> m_styles;
std::vector<std::string> m_component_maskshift;
db::FTrans get_orient (bool optional);
void read_polygon (db::Polygon &poly, double scale);
void read_rect (db::Polygon &poly, double scale);
std::pair<Coord, Coord> get_wire_width_for_rule(const std::string &rule, const std::string &ln, double dbu);
std::pair<db::Coord, db::Coord> get_def_ext (const std::string &ln, const std::pair<db::Coord, db::Coord> &wxy, double dbu);
void read_diearea (db::Layout &layout, db::Cell &design, double scale);
void read_nondefaultrules (double scale);
void read_regions (std::map<std::string, std::vector<db::Polygon> > &regions, double scale);
void read_groups (std::list<DEFImporterGroup> &groups, double scale);
void read_blockages (db::Layout &layout, db::Cell &design, double scale);
void read_nets (db::Layout &layout, db::Cell &design, double scale, bool specialnets);
void read_vias (db::Layout &layout, db::Cell &design, double scale);
void read_pins (db::Layout &layout, db::Cell &design, double scale);
void read_styles (double scale);
void read_components (Layout &layout, std::list<std::pair<std::string, db::CellInstArray> > &instances, double scale);
void read_single_net (std::string &nondefaultrule, db::Layout &layout, db::Cell &design, double scale, properties_id_type prop_id, bool specialnets);
void produce_routing_geometry (db::Cell &design, const db::Polygon *style, unsigned int layer, properties_id_type prop_id, const std::vector<db::Point> &pts, const std::vector<std::pair<db::Coord, db::Coord> > &ext, std::pair<db::Coord, db::Coord> w);
};
}

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,20 @@ namespace tl
namespace db
{
class LEFDEFReaderState;
struct MacroDesc;
/**
* @brief Correct a path relative to the stream and technology
*/
DB_PLUGIN_PUBLIC
std::string correct_path (const std::string &fn, const db::Layout &layout, const std::string &base_path);
/**
* @brief Convers a string to a MASKSHIFT index list
*/
std::vector<unsigned int> string2masks (const std::string &s);
/**
* @brief Generic base class of DXF reader exceptions
*/
@ -55,6 +69,34 @@ public:
{ }
};
template <class Value>
const Value &per_mask_value (const std::map<unsigned int, Value> &map, const Value &def, unsigned int mask)
{
typename std::map<unsigned int, Value>::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 <class Value>
void set_per_mask_value (std::map<unsigned int, Value> &map, unsigned int mask, const Value &value)
{
if (per_mask_value_is_null (value)) {
map.erase (mask);
} else {
map [mask] = value;
}
}
template <class Value>
void get_max_mask_number (unsigned int &mm, const std::map<unsigned int, Value> &map)
{
if (! map.empty ()) {
mm = std::max (mm, (--map.end ())->first);
}
}
/**
* @brief The LEF/DEF importer technology component
*
@ -256,6 +298,52 @@ public:
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;
@ -286,6 +374,108 @@ public:
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_obstructions () const
{
return m_produce_obstructions;
@ -406,6 +596,124 @@ public:
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_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 ();
@ -436,6 +744,71 @@ public:
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;
}
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
* 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<db::Layout *> &layouts)
{
for (std::vector<db::Layout *>::const_iterator l = layouts.begin (); l != layouts.end (); ++l) {
m_macro_layouts.push_back (*l);
}
}
std::vector<db::Layout *> macro_layouts () const
{
std::vector<db::Layout *> res;
for (tl::weak_collection<db::Layout>::const_iterator m = m_macro_layouts.begin (); m != m_macro_layouts.end (); ++m) {
if (m.operator-> ()) {
res.push_back (const_cast<db::Layout *> (m.operator-> ()));
}
}
return res;
}
private:
bool m_read_all_layers;
db::LayerMap m_layer_map;
@ -455,9 +828,19 @@ private:
bool m_produce_via_geometry;
std::string m_via_geometry_suffix;
int m_via_geometry_datatype;
std::map<unsigned int, std::string> m_via_geometry_suffixes;
std::map<unsigned int, int> 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<unsigned int, std::string> m_pins_suffixes;
std::map<unsigned int, int> m_pins_datatypes;
bool m_produce_lef_pins;
std::string m_lef_pins_suffix;
int m_lef_pins_datatype;
std::map<unsigned int, std::string> m_lef_pins_suffixes;
std::map<unsigned int, int> m_lef_pins_datatypes;
bool m_produce_obstructions;
std::string m_obstructions_suffix;
int m_obstructions_datatype;
@ -470,7 +853,19 @@ private:
bool m_produce_routing;
std::string m_routing_suffix;
int m_routing_datatype;
std::map<unsigned int, std::string> m_routing_suffixes;
std::map<unsigned int, int> m_routing_datatypes;
bool m_produce_special_routing;
std::string m_special_routing_suffix;
int m_special_routing_datatype;
std::map<unsigned int, std::string> m_special_routing_suffixes;
std::map<unsigned int, int> m_special_routing_datatypes;
bool m_separate_groups;
std::string m_map_file;
unsigned int m_macro_resolution_mode;
bool m_read_lef_with_def;
std::vector<std::string> m_lef_files;
tl::weak_collection<db::Layout> m_macro_layouts;
};
/**
@ -478,15 +873,148 @@ private:
*/
enum LayerPurpose
{
Routing = 0,
ViaGeometry = 1,
Label = 2,
Pins = 3,
Obstructions = 4,
Outline = 5,
Blockage = 6,
PlacementBlockage = 7,
Region = 8
Routing = 0, // from DEF only
Pins, // from DEF
SpecialRouting, // from DEF only
LEFPins, // from LEF
ViaGeometry, // from LEF+DEF
Label, // from LEF+DEF
Obstructions, // from LEF only
Outline, // from LEF+DEF
Blockage, // from DEF only
PlacementBlockage, // from DEF only
Regions, // from DEF only
};
/**
* @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<std::string> *maskshift_layers, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm) = 0;
virtual std::vector<std::string> 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<std::string> *maskshift_layers, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm);
virtual std::vector<std::string> maskshift_layers () const
{
std::vector<std::string> 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<std::string> *maskshift_layers, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *num_cut_masks);
virtual std::vector<std::string> 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);
void add_box (const std::string &ln, LayerPurpose purpose, const db::Box &box, unsigned int mask, properties_id_type prop_id);
void add_path (const std::string &ln, LayerPurpose purpose, const db::Path &path, unsigned int mask, properties_id_type prop_id);
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<std::string> &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;
}
private:
struct Via {
Via () : bottom_mask (0), cut_mask (0), top_mask (0) { }
std::string name;
unsigned int bottom_mask, cut_mask, top_mask;
db::Trans trans;
};
std::map <std::pair<std::string, std::pair<LayerPurpose, unsigned int> >, db::Shapes> m_shapes;
std::list<Via> m_vias;
std::vector<std::string> m_maskshift_layers;
bool m_fixedmask;
unsigned int get_maskshift (const std::string &ln, const std::vector<std::string> *maskshift_layers, const std::vector<unsigned int> &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;
};
/**
@ -494,25 +1022,28 @@ enum LayerPurpose
*
* This class will handle the creation and management of layers in the LEF/DEF reader context
*/
class DB_PLUGIN_PUBLIC LEFDEFLayerDelegate
class DB_PLUGIN_PUBLIC LEFDEFReaderState
{
public:
/**
* @brief Constructor
*/
LEFDEFLayerDelegate (const LEFDEFReaderOptions *tc);
LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout, const std::string &base_path = std::string ());
/**
* @brief Set the layer map
* @brief Destructor
*/
virtual void set_layer_map (const db::LayerMap &lm, bool create_layers)
{
m_layer_map = lm;
m_create_layers = create_layers;
}
~LEFDEFReaderState ();
/**
* @brief Get the layer map
* @brief Reads the given map file
*
* Usually this file is read by the constructor. This method is provided for test purposes.
*/
void read_map_file (const std::string &path, db::Layout &layout);
/**
* @brief Gets the layer map
*/
const db::LayerMap &layer_map () const
{
@ -522,23 +1053,52 @@ public:
/**
* @brief Create a new layer or return the index of the given layer
*/
std::pair <bool, unsigned int> open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose);
std::pair <bool, unsigned int> open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
/**
* @brief Registers a layer (assign a new default layer number)
*/
void register_layer (const std::string &l);
/**
* @brief Prepare, i.e. create layers required by the layer map
*/
void prepare (db::Layout &layout);
/**
* @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, 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, 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);
/**
* @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 maco is registered
*/
std::pair<db::Cell *, db::Trans> macro_cell (const std::string &mn, Layout &layout, const std::vector<std::string> &maskshift_layers, const std::vector<unsigned int> &masks, const MacroDesc &macro_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
*/
@ -547,13 +1107,102 @@ public:
return mp_tech_comp;
}
/**
* @brief Gets a map of foreign cells vs. name
*/
const std::map<std::string, db::cell_index_type> &foreign_cells () const
{
return m_foreign_cells;
}
private:
std::map <std::pair<std::string, LayerPurpose>, unsigned int> m_layers;
/**
* @brief A key for the via cache
*/
struct ViaKey
{
ViaKey (const std::string &n, unsigned int mb, unsigned int mc, unsigned int mt)
: name (n), mask_bottom (mb), mask_cut (mc), mask_top (mt)
{ }
bool operator== (const ViaKey &other) const
{
return name == other.name && 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 (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;
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<unsigned int> &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<unsigned int> masks;
};
// no copying
LEFDEFReaderState (const LEFDEFReaderState &);
LEFDEFReaderState &operator= (const LEFDEFReaderState &);
std::map <std::pair<std::string, std::pair<LayerPurpose, unsigned int> >, std::pair<bool, unsigned int> > m_layers;
db::LayerMap m_layer_map;
bool m_create_layers;
bool m_has_explicit_layer_mapping;
int m_laynum;
std::map<std::string, int> m_default_number;
const LEFDEFReaderOptions *mp_tech_comp;
std::map<ViaKey, db::Cell *> m_via_cells;
std::map<std::string, LEFDEFLayoutGenerator *> m_via_generators;
std::map<MacroKey, std::pair<db::Cell *, db::Trans> > m_macro_cells;
std::map<std::string, LEFDEFLayoutGenerator *> m_macro_generators;
std::map<std::string, db::cell_index_type> m_foreign_cells;
std::pair <bool, unsigned int> open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
void map_layer_explicit (const std::string &n, LayerPurpose purpose, const LayerProperties &lp, unsigned int layer, unsigned int mask);
db::cell_index_type foreign_cell(Layout &layout, const std::string &name);
};
/**
@ -561,12 +1210,7 @@ private:
*/
struct DB_PLUGIN_PUBLIC ViaDesc
{
ViaDesc () : cell (0) { }
/**
* @brief The cell representing the via
*/
db::Cell *cell;
ViaDesc () { }
/**
* @brief The names of bottom and top metal respectively
@ -574,6 +1218,34 @@ struct DB_PLUGIN_PUBLIC ViaDesc
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
*/
@ -595,7 +1267,7 @@ public:
*
* This method reads the layout specified into the given layout
*/
void read (tl::InputStream &stream, db::Layout &layout, LEFDEFLayerDelegate &layer_delegate);
void read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state);
protected:
/**
@ -635,6 +1307,16 @@ protected:
*/
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
*/
@ -655,12 +1337,35 @@ protected:
*/
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::pair <bool, unsigned int> open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose)
std::pair <bool, unsigned int> open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask)
{
return mp_layer_delegate->open_layer (layout, name, purpose);
return mp_reader_state->open_layer (layout, name, purpose, mask);
}
/**
@ -668,7 +1373,7 @@ protected:
*/
void register_layer (const std::string &l)
{
mp_layer_delegate->register_layer (l);
mp_reader_state->register_layer (l);
}
/**
@ -735,22 +1440,26 @@ protected:
return m_pin_prop_name_id;
}
protected:
void create_generated_via (std::vector<db::Polygon> &bottom,
std::vector<db::Polygon> &cut,
std::vector<db::Polygon> &top,
const db::Vector &cutsize,
const db::Vector &cutspacing,
const db::Vector &be, const db::Vector &te,
const db::Vector &bo, const db::Vector &to,
const db::Point &o,
int rows, int columns,
const std::string &pattern);
/**
* @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;
LEFDEFLayerDelegate *mp_layer_delegate;
LEFDEFReaderState *mp_reader_state;
std::string m_cellname;
std::string m_fn;
std::string m_last_token;
@ -760,6 +1469,7 @@ private:
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;
const std::string &next ();
};

View File

@ -30,6 +30,9 @@
#include "dbLEFImporter.h"
#include "dbDEFImporter.h"
#include "dbLEFDEFImporter.h"
#include "dbLayoutUtils.h"
#include "dbTechnology.h"
#include "dbCellMapping.h"
namespace db
{
@ -102,19 +105,11 @@ public:
{
return "LEFDEF";
}
private:
tl::InputStream &m_stream;
db::LayerMap m_layer_map;
std::string correct_path (const std::string &fn)
{
if (! tl::is_absolute (fn)) {
return tl::combine_path (m_stream.absolute_path (), fn);
} else {
return fn;
}
}
const db::LayerMap &read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &options, bool import_lef)
{
const db::LEFDEFReaderOptions *lefdef_options = dynamic_cast<const db::LEFDEFReaderOptions *> (options.get_options (format ()));
@ -123,60 +118,71 @@ private:
lefdef_options = &default_options;
}
// Take the layer map and the "read all layers" flag from the reader options - hence we override the
db::LEFDEFLayerDelegate layers (lefdef_options);
layers.prepare (layout);
db::LEFDEFReaderState state (lefdef_options, layout, tl::dirname (m_stream.absolute_path ()));
layout.dbu (lefdef_options->dbu ());
if (import_lef) {
tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (tr ("Reading LEF file")));
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file")));
db::LEFImporter importer;
for (std::vector<std::string>::const_iterator l = lefdef_options->begin_lef_files (); l != lefdef_options->end_lef_files (); ++l) {
std::string lp = correct_path (*l);
std::string lp = correct_path (*l, layout, tl::dirname (m_stream.absolute_path ()));
tl::InputStream lef_stream (lp);
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
importer.read (lef_stream, layout, layers);
importer.read (lef_stream, layout, state);
}
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
importer.read (m_stream, layout, layers);
importer.read (m_stream, layout, state);
importer.finish_lef (layout);
} else {
tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (tr ("Reading DEF file")));
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading DEF file")));
DEFImporter importer;
for (std::vector<std::string>::const_iterator l = lefdef_options->begin_lef_files (); l != lefdef_options->end_lef_files (); ++l) {
std::string lp = correct_path (*l);
std::string lp = correct_path (*l, layout, tl::dirname (m_stream.absolute_path ()));
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp);
tl::InputStream lef_stream (lp);
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
importer.read_lef (lef_stream, layout, layers);
importer.read_lef (lef_stream, layout, state);
}
// Additionally read all LEF files next to the DEF file
std::string input_dir = tl::absolute_path (m_stream.absolute_path ());
if (tl::file_exists (input_dir)) {
if (lefdef_options->read_lef_with_def ()) {
std::vector<std::string> entries = tl::dir_entries (input_dir);
for (std::vector<std::string>::const_iterator e = entries.begin (); e != entries.end (); ++e) {
std::string input_dir = tl::absolute_path (m_stream.absolute_path ());
if (is_lef_format (*e)) {
if (tl::file_exists (input_dir)) {
std::string lp = tl::combine_path (input_dir, *e);
tl::InputStream lef_stream (lp);
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
importer.read_lef (lef_stream, layout, layers);
std::vector<std::string> entries = tl::dir_entries (input_dir, true, false, true);
for (std::vector<std::string>::const_iterator e = entries.begin (); e != entries.end (); ++e) {
if (is_lef_format (*e)) {
std::string lp = tl::combine_path (input_dir, *e);
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp);
tl::InputStream lef_stream (lp);
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
importer.read_lef (lef_stream, layout, state);
}
}
@ -185,17 +191,79 @@ private:
}
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
importer.read (m_stream, layout, layers);
importer.read (m_stream, layout, state);
// Resolve unresolved COMPONENT cells
std::map<std::string, db::cell_index_type> foreign_cells = state.foreign_cells ();
db::cell_index_type seen = std::numeric_limits<db::cell_index_type>::max ();
std::vector<db::Layout *> macro_layouts = lefdef_options->macro_layouts ();
for (std::vector<db::Layout *>::const_iterator m = macro_layouts.begin (); m != macro_layouts.end (); ++m) {
std::vector<db::cell_index_type> target_cells, source_cells;
// collect the cells to pull in
for (std::map<std::string, db::cell_index_type>::iterator f = foreign_cells.begin (); f != foreign_cells.end (); ++f) {
if (f->second != seen) {
std::pair<bool, db::cell_index_type> cp = (*m)->cell_by_name (f->first.c_str ());
if (cp.first) {
target_cells.push_back (f->second);
source_cells.push_back (cp.second);
layout.cell (f->second).set_ghost_cell (false);
f->second = seen;
}
}
}
db::CellMapping cm;
cm.create_multi_mapping_full (layout, target_cells, **m, source_cells);
layout.copy_tree_shapes (**m, cm);
}
}
layers.finish (layout);
state.finish (layout);
m_layer_map = layers.layer_map ();
m_layer_map = state.layer_map ();
return m_layer_map;
}
};
namespace {
struct MacroResolutionModeConverter
{
public:
MacroResolutionModeConverter ()
{
m_values.push_back ("default");
m_values.push_back ("always-lef");
m_values.push_back ("always-cellref");
}
std::string to_string (unsigned int v) const
{
return v < m_values.size () ? m_values[v] : std::string ();
}
void from_string (const std::string &s, unsigned int &v) const
{
v = 0;
for (unsigned int i = 0; i < (unsigned int) m_values.size (); ++i) {
if (m_values [i] == s) {
v = i;
}
}
}
private:
std::vector<std::string> m_values;
};
}
class LEFDEFFormatDeclaration
: public db::StreamFormatDeclaration
{
@ -248,11 +316,26 @@ class LEFDEFFormatDeclaration
tl::make_member (&LEFDEFReaderOptions::produce_regions, &LEFDEFReaderOptions::set_produce_regions, "produce-regions") +
tl::make_member (&LEFDEFReaderOptions::region_layer, &LEFDEFReaderOptions::set_region_layer, "region-layer") +
tl::make_member (&LEFDEFReaderOptions::produce_via_geometry, &LEFDEFReaderOptions::set_produce_via_geometry, "produce-via-geometry") +
tl::make_member (&LEFDEFReaderOptions::via_geometry_suffix, &LEFDEFReaderOptions::set_via_geometry_suffix, "via-geometry-suffix") +
tl::make_member (&LEFDEFReaderOptions::via_geometry_datatype, &LEFDEFReaderOptions::set_via_geometry_datatype, "via-geometry-datatype") +
// for backward compatibility
tl::make_member (&LEFDEFReaderOptions::set_via_geometry_suffix, "special-via_geometry-suffix") +
tl::make_member (&LEFDEFReaderOptions::set_via_geometry_datatype, "special-via_geometry-datatype") +
// new:
tl::make_member (&LEFDEFReaderOptions::via_geometry_suffix_str, &LEFDEFReaderOptions::set_via_geometry_suffix_str, "special-via_geometry-suffix-string") +
tl::make_member (&LEFDEFReaderOptions::via_geometry_datatype_str, &LEFDEFReaderOptions::set_via_geometry_datatype_str, "special-via_geometry-datatype-string") +
tl::make_member (&LEFDEFReaderOptions::produce_pins, &LEFDEFReaderOptions::set_produce_pins, "produce-pins") +
tl::make_member (&LEFDEFReaderOptions::pins_suffix, &LEFDEFReaderOptions::set_pins_suffix, "pins-suffix") +
tl::make_member (&LEFDEFReaderOptions::pins_datatype, &LEFDEFReaderOptions::set_pins_datatype, "pins-datatype") +
// for backward compatibility
tl::make_member (&LEFDEFReaderOptions::set_pins_suffix, "special-pins-suffix") +
tl::make_member (&LEFDEFReaderOptions::set_pins_datatype, "special-pins-datatype") +
// new:
tl::make_member (&LEFDEFReaderOptions::pins_suffix_str, &LEFDEFReaderOptions::set_pins_suffix_str, "special-pins-suffix-string") +
tl::make_member (&LEFDEFReaderOptions::pins_datatype_str, &LEFDEFReaderOptions::set_pins_datatype_str, "special-pins-datatype-string") +
tl::make_member (&LEFDEFReaderOptions::produce_lef_pins, &LEFDEFReaderOptions::set_produce_lef_pins, "produce-lef-pins") +
// for backward compatibility
tl::make_member (&LEFDEFReaderOptions::set_lef_pins_suffix, "special-lef_pins-suffix") +
tl::make_member (&LEFDEFReaderOptions::set_lef_pins_datatype, "special-lef_pins-datatype") +
// new:
tl::make_member (&LEFDEFReaderOptions::lef_pins_suffix_str, &LEFDEFReaderOptions::set_lef_pins_suffix_str, "special-lef_pins-suffix-string") +
tl::make_member (&LEFDEFReaderOptions::lef_pins_datatype_str, &LEFDEFReaderOptions::set_lef_pins_datatype_str, "special-lef_pins-datatype-string") +
tl::make_member (&LEFDEFReaderOptions::produce_obstructions, &LEFDEFReaderOptions::set_produce_obstructions, "produce-obstructions") +
tl::make_member (&LEFDEFReaderOptions::obstructions_suffix, &LEFDEFReaderOptions::set_obstructions_suffix, "obstructions-suffix") +
tl::make_member (&LEFDEFReaderOptions::obstructions_datatype, &LEFDEFReaderOptions::set_obstructions_datatype, "obstructions-datatype") +
@ -263,9 +346,25 @@ class LEFDEFFormatDeclaration
tl::make_member (&LEFDEFReaderOptions::labels_suffix, &LEFDEFReaderOptions::set_labels_suffix, "labels-suffix") +
tl::make_member (&LEFDEFReaderOptions::labels_datatype, &LEFDEFReaderOptions::set_labels_datatype, "labels-datatype") +
tl::make_member (&LEFDEFReaderOptions::produce_routing, &LEFDEFReaderOptions::set_produce_routing, "produce-routing") +
tl::make_member (&LEFDEFReaderOptions::routing_suffix, &LEFDEFReaderOptions::set_routing_suffix, "routing-suffix") +
tl::make_member (&LEFDEFReaderOptions::routing_datatype, &LEFDEFReaderOptions::set_routing_datatype, "routing-datatype") +
tl::make_member (&LEFDEFReaderOptions::begin_lef_files, &LEFDEFReaderOptions::end_lef_files, &LEFDEFReaderOptions::push_lef_file, "lef-files")
// for backward compatibility
tl::make_member (&LEFDEFReaderOptions::set_routing_suffix, "special-routing-suffix") +
tl::make_member (&LEFDEFReaderOptions::set_routing_datatype, "special-routing-datatype") +
// new:
tl::make_member (&LEFDEFReaderOptions::routing_suffix_str, &LEFDEFReaderOptions::set_routing_suffix_str, "special-routing-suffix-string") +
tl::make_member (&LEFDEFReaderOptions::routing_datatype_str, &LEFDEFReaderOptions::set_routing_datatype_str, "special-routing-datatype-string") +
tl::make_member (&LEFDEFReaderOptions::produce_special_routing, &LEFDEFReaderOptions::set_produce_special_routing, "produce-special-routing") +
// for backward compatibility
tl::make_member (&LEFDEFReaderOptions::set_special_routing_suffix, "special-routing-suffix") +
tl::make_member (&LEFDEFReaderOptions::set_special_routing_datatype, "special-routing-datatype") +
// new:
tl::make_member (&LEFDEFReaderOptions::special_routing_suffix_str, &LEFDEFReaderOptions::set_special_routing_suffix_str, "special-routing-suffix-string") +
tl::make_member (&LEFDEFReaderOptions::special_routing_datatype_str, &LEFDEFReaderOptions::set_special_routing_datatype_str, "special-routing-datatype-string") +
tl::make_member (&LEFDEFReaderOptions::via_cellname_prefix, &LEFDEFReaderOptions::set_via_cellname_prefix, "via-cellname-prefix") +
tl::make_member (&LEFDEFReaderOptions::begin_lef_files, &LEFDEFReaderOptions::end_lef_files, &LEFDEFReaderOptions::push_lef_file, "lef-files") +
tl::make_member (&LEFDEFReaderOptions::read_lef_with_def, &LEFDEFReaderOptions::set_read_lef_with_def, "read-lef-with-def") +
tl::make_member (&LEFDEFReaderOptions::macro_resolution_mode, &LEFDEFReaderOptions::set_macro_resolution_mode, "macro-resolution-mode", MacroResolutionModeConverter ()) +
tl::make_member (&LEFDEFReaderOptions::separate_groups, &LEFDEFReaderOptions::set_separate_groups, "separate-groups") +
tl::make_member (&LEFDEFReaderOptions::map_file, &LEFDEFReaderOptions::set_map_file, "map-file")
);
}
};

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,7 @@ namespace db
* @brief The LEF importer object
*/
class DB_PLUGIN_PUBLIC LEFImporter
: public LEFDEFImporter
: public LEFDEFImporter, public LEFDEFNumberOfMasks
{
public:
/**
@ -57,19 +57,6 @@ public:
*/
~LEFImporter ();
/**
* @brief Get the cell for a macro name
*
* Returns 0 if the name is not a valid macro name. Otherwise it returns the pointer
* to the corresponding db::Cell object.
*/
db::Cell *macro_by_name (const std::string &macro_name) const;
/**
* @brief Get the cell bbox for the given macro name
*/
db::Box macro_bbox_by_name (const std::string &macro_name) const;
/**
* @brief Get the width for a layer with the given name
*
@ -77,7 +64,7 @@ public:
* The nondefaultrule name gives the name of the nondefaultrule or an empty string if
* none is requested.
*/
double layer_width (const std::string &layer, const std::string &nondefaultrule, double def_width = 0.0) const;
std::pair<double, double> layer_width (const std::string &layer, const std::string &nondefaultrule, const std::pair<double, double> &def_width = std::make_pair (0.0, 0.0)) const;
/**
* @brief Get the extension for a layer with the given name
@ -86,6 +73,36 @@ public:
*/
double layer_ext (const std::string &layer, double def_ext = 0.0) const;
/**
* @brief Gets the minimum wire width in x and y direction for the given layer name
*/
std::pair<double, double> min_layer_width (const std::string &layer) const;
/**
* @brief Returns true if the given layer is a routing layer
*/
bool is_routing_layer (const std::string &layer) const
{
return m_routing_layers.find (layer) != m_routing_layers.end ();
}
/**
* @brief Returns true if the given layer is a cut layer
*/
bool is_cut_layer (const std::string &layer) const
{
return m_cut_layers.find (layer) != m_cut_layers.end ();
}
/**
* @brief Returns the number of masks for the given layer
*/
virtual unsigned int number_of_masks (const std::string &layer) const
{
std::map<std::string, unsigned int>::const_iterator nm = m_num_masks.find (layer);
return nm != m_num_masks.end () ? nm->second : 1;
}
/**
* @brief Gets a map of the vias defined in this LEF file
*
@ -96,19 +113,45 @@ public:
return m_vias;
}
/**
* @brief Gets the
*
* The map maps the macro name to the macro description.
*/
const std::map<std::string, MacroDesc> &macros () const
{
return m_macros;
}
/**
* @brief Finishes reading a LEF file
*
* This method will create all the macros, so they become visible.
* When reading a LEF as component for a DEF, this method will not be called.
*/
void finish_lef (db::Layout &layout);
protected:
void do_read (db::Layout &layout);
private:
std::map<std::string, std::map<std::string, double> > m_nondefault_widths;
std::map<std::string, double> m_default_widths;
std::map<std::string, std::map<std::string, std::pair<double, double> > > m_nondefault_widths;
std::map<std::string, std::pair<double, double> > m_default_widths;
std::map<std::string, double> m_default_ext;
std::map<std::string, db::Cell *> m_macros_by_name;
std::map<std::string, db::Box> m_macro_bboxes_by_name;
std::map<std::string, std::pair<double, double> > m_min_widths;
std::map<std::string, MacroDesc> m_macros;
std::map<std::string, ViaDesc> m_vias;
std::set<std::string> m_routing_layers, m_cut_layers;
std::map<std::string, unsigned int> m_num_masks;
std::vector <db::Trans> get_iteration (db::Layout &layout);
void read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose purpose, std::map<std::string, db::Box> *collect_bboxes = 0, properties_id_type prop_id = 0);
std::vector <db::Trans> get_iteration (double dbu);
void read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, LayerPurpose purpose, std::map<std::string, db::Box> *collect_bboxes = 0, properties_id_type prop_id = 0);
void read_nondefaultrule (Layout &layout);
void read_viadef (Layout &layout);
void read_viadef_by_rule (RuleBasedViaGenerator *vg, ViaDesc &desc, const std::string &n, double dbu);
void read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc &desc, const std::string &n, double dbu);
void read_layer (Layout &layout);
void read_macro (Layout &layout);
};
}

View File

@ -185,21 +185,21 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"This method has been introduced in version 0.26.4."
) +
gsi::method ("produce_cell_outlines", &db::LEFDEFReaderOptions::produce_cell_outlines,
"@brief Gets a value indicating whether to produce cell outlines.\n"
"@brief Gets a value indicating whether to produce cell outlines (diearea).\n"
"If set to true, cell outlines will be produced on the layer given by \\cell_outline_layer. "
) +
gsi::method ("produce_cell_outlines=", &db::LEFDEFReaderOptions::set_produce_cell_outlines, gsi::arg ("produce"),
"@brief Sets a value indicating whether to produce cell outlines.\n"
"@brief Sets a value indicating whether to produce cell outlines (diearea).\n"
"See \\produce_cell_outlines for details.\n"
) +
gsi::method ("cell_outline_layer", &db::LEFDEFReaderOptions::cell_outline_layer,
"@brief Gets the layer on which to produce the cell outline.\n"
"@brief Gets the layer on which to produce the cell outline (diearea).\n"
"This attribute is a string correspondig to the string representation of \\LayerInfo. "
"This string can be either a layer number, a layer/datatype pair, a name or a combination of both. See \\LayerInfo for details.\n"
"The setter for this attribute is \\cell_outline_layer=. See also \\produce_cell_outlines."
) +
gsi::method ("cell_outline_layer=", &db::LEFDEFReaderOptions::set_cell_outline_layer, gsi::arg ("spec"),
"@brief Sets the layer on which to produce the cell outline.\n"
"@brief Sets the layer on which to produce the cell outline (diearea).\n"
"See \\cell_outline_layer for details.\n"
) +
gsi::method ("produce_placement_blockages", &db::LEFDEFReaderOptions::produce_placement_blockages,
@ -220,6 +220,32 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"@brief Sets the layer on which to produce the placement blockage.\n"
"See \\placement_blockage_layer for details.\n"
) +
gsi::method ("produce_regions", &db::LEFDEFReaderOptions::produce_regions,
"@brief Gets a value indicating whether to produce regions.\n"
"If set to true, polygons will be produced representing the regions on the layer given by \\region_layer.\n"
"\n"
"The attribute has been introduced in version 0.27."
) +
gsi::method ("produce_regions=", &db::LEFDEFReaderOptions::set_produce_regions, gsi::arg ("produce"),
"@brief Sets a value indicating whether to produce regions.\n"
"See \\produce_regions for details.\n"
"\n"
"The attribute has been introduced in version 0.27."
) +
gsi::method ("region_layer", &db::LEFDEFReaderOptions::region_layer,
"@brief Gets the layer on which to produce the regions.\n"
"This attribute is a string correspondig to the string representation of \\LayerInfo. "
"This string can be either a layer number, a layer/datatype pair, a name or a combination of both. See \\LayerInfo for details."
"The setter for this attribute is \\region_layer=. See also \\produce_regions.\n"
"\n"
"The attribute has been introduced in version 0.27."
) +
gsi::method ("region_layer=", &db::LEFDEFReaderOptions::set_region_layer,
"@brief Sets the layer on which to produce the regions.\n"
"See \\region_layer for details.\n"
"\n"
"The attribute has been introduced in version 0.27."
) +
gsi::method ("produce_via_geometry", &db::LEFDEFReaderOptions::produce_via_geometry,
"@brief Sets a value indicating whether via geometries shall be produced.\n"
"\n"
@ -260,6 +286,70 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"@brief Sets the via geometry layer datatype value.\n"
"See \\produce_via_geometry for details about this property.\n"
) +
gsi::method ("clear_via_geometry_suffixes_per_mask", &db::LEFDEFReaderOptions::clear_via_geometry_suffixes_per_mask,
"@brief Clears the via geometry layer name suffix per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("clear_via_geometry_datatypes_per_mask", &db::LEFDEFReaderOptions::clear_via_geometry_datatypes_per_mask,
"@brief Clears the via geometry layer datatypes per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("via_geometry_suffix_per_mask", &db::LEFDEFReaderOptions::via_geometry_suffix_per_mask, gsi::arg ("mask"),
"@brief Gets the via geometry layer name suffix per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("set_via_geometry_suffix_per_mask", &db::LEFDEFReaderOptions::set_via_geometry_suffix_per_mask, gsi::arg ("mask"), gsi::arg ("suffix"),
"@brief Sets the via geometry layer name suffix per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("via_geometry_datatype", &db::LEFDEFReaderOptions::via_geometry_datatype_per_mask,
"@brief Gets the via geometry layer datatype value per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("set_via_geometry_datatype_per_mask", &db::LEFDEFReaderOptions::set_via_geometry_datatype_per_mask, gsi::arg ("mask"), gsi::arg ("datatype"),
"@brief Sets the via geometry layer datatype value.\n"
"See \\produce_via_geometry for details about this property.\n"
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("via_geometry_suffix_str", &db::LEFDEFReaderOptions::via_geometry_suffix_str,
"@hide"
) +
gsi::method ("via_geometry_suffix_str=", &db::LEFDEFReaderOptions::set_via_geometry_suffix_str, gsi::arg ("suffix"),
"@hide"
) +
gsi::method ("via_geometry_datatype_str", &db::LEFDEFReaderOptions::via_geometry_datatype_str,
"@hide"
) +
gsi::method ("via_geometry_datatype_str=", &db::LEFDEFReaderOptions::set_via_geometry_datatype_str, gsi::arg ("datatype"),
"@hide"
) +
gsi::method ("via_cellname_prefix", &db::LEFDEFReaderOptions::via_cellname_prefix,
"@brief Gets the via cellname prefix.\n"
"Vias are represented by cells. The cell name is formed by combining the via cell name prefix and the via name.\n"
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("via_cellname_prefix=", &db::LEFDEFReaderOptions::set_via_cellname_prefix, gsi::arg ("prefix"),
"@brief Sets the via cellname prefix.\n"
"See \\via_cellname_prefix for details about this property.\n"
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("produce_pins", &db::LEFDEFReaderOptions::produce_pins,
"@brief Gets a value indicating whether pin geometries shall be produced.\n"
"See \\produce_via_geometry for details about the layer production rules."
@ -284,6 +374,134 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"@brief Sets the pin geometry layer datatype value.\n"
"See \\produce_via_geometry for details about the layer production rules."
) +
gsi::method ("clear_pins_suffixes_per_mask", &db::LEFDEFReaderOptions::clear_pins_suffixes_per_mask,
"@brief Clears the pin layer name suffix per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("clear_pin_datatypes_per_mask", &db::LEFDEFReaderOptions::clear_pins_datatypes_per_mask,
"@brief Clears the pin layer datatypes per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("pins_suffix_per_mask", &db::LEFDEFReaderOptions::pins_suffix_per_mask, gsi::arg ("mask"),
"@brief Gets the pin geometry layer name suffix per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("set_pins_suffix_per_mask", &db::LEFDEFReaderOptions::set_pins_suffix_per_mask, gsi::arg ("mask"), gsi::arg ("suffix"),
"@brief Sets the pin geometry layer name suffix per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("pins_datatype", &db::LEFDEFReaderOptions::pins_datatype_per_mask,
"@brief Gets the pin geometry layer datatype value per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("set_pins_datatype_per_mask", &db::LEFDEFReaderOptions::set_pins_datatype_per_mask, gsi::arg ("mask"), gsi::arg ("datatype"),
"@brief Sets the pin geometry layer datatype value.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("pins_suffix_str", &db::LEFDEFReaderOptions::pins_suffix_str,
"@hide"
) +
gsi::method ("pins_suffix_str=", &db::LEFDEFReaderOptions::set_pins_suffix_str, gsi::arg ("suffix"),
"@hide"
) +
gsi::method ("pins_datatype_str", &db::LEFDEFReaderOptions::pins_datatype_str,
"@hide"
) +
gsi::method ("pins_datatype_str=", &db::LEFDEFReaderOptions::set_pins_datatype_str, gsi::arg ("datatype"),
"@hide"
) +
gsi::method ("produce_lef_pins", &db::LEFDEFReaderOptions::produce_lef_pins,
"@brief Gets a value indicating whether LEF pin geometries shall be produced.\n"
"See \\produce_via_geometry for details about the layer production rules."
) +
gsi::method ("produce_lef_pins=", &db::LEFDEFReaderOptions::set_produce_lef_pins, gsi::arg ("produce"),
"@brief Sets a value indicating whether LEF pin geometries shall be produced.\n"
"See \\produce_via_geometry for details about the layer production rules."
) +
gsi::method ("lef_pins_suffix", &db::LEFDEFReaderOptions::lef_pins_suffix,
"@brief Gets the LEF pin geometry layer name suffix.\n"
"See \\produce_via_geometry for details about the layer production rules."
) +
gsi::method ("lef_pins_suffix=", &db::LEFDEFReaderOptions::set_lef_pins_suffix, gsi::arg ("suffix"),
"@brief Sets the LEF pin geometry layer name suffix.\n"
"See \\produce_via_geometry for details about the layer production rules."
) +
gsi::method ("lef_pins_datatype", &db::LEFDEFReaderOptions::lef_pins_datatype,
"@brief Gets the LEF pin geometry layer datatype value.\n"
"See \\produce_via_geometry for details about the layer production rules."
) +
gsi::method ("lef_pins_datatype=", &db::LEFDEFReaderOptions::set_lef_pins_datatype, gsi::arg ("datatype"),
"@brief Sets the LEF pin geometry layer datatype value.\n"
"See \\produce_via_geometry for details about the layer production rules."
) +
gsi::method ("clear_lef_pins_suffixes_per_mask", &db::LEFDEFReaderOptions::clear_lef_pins_suffixes_per_mask,
"@brief Clears the LEF pin layer name suffix per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("clear_lef_pins_datatypes_per_mask", &db::LEFDEFReaderOptions::clear_lef_pins_datatypes_per_mask,
"@brief Clears the LEF pin layer datatypes per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("lef_pins_suffix_per_mask", &db::LEFDEFReaderOptions::lef_pins_suffix_per_mask, gsi::arg ("mask"),
"@brief Gets the LEF pin geometry layer name suffix per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("set_lef_pins_suffix_per_mask", &db::LEFDEFReaderOptions::set_lef_pins_suffix_per_mask, gsi::arg ("mask"), gsi::arg ("suffix"),
"@brief Sets the LEF pin geometry layer name suffix per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("lef_pins_datatype", &db::LEFDEFReaderOptions::lef_pins_datatype_per_mask,
"@brief Gets the LEF pin geometry layer datatype value per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("set_lef_pins_datatype_per_mask", &db::LEFDEFReaderOptions::set_lef_pins_datatype_per_mask, gsi::arg ("mask"), gsi::arg ("datatype"),
"@brief Sets the LEF pin geometry layer datatype value.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("lef_pins_suffix_str", &db::LEFDEFReaderOptions::lef_pins_suffix_str,
"@hide"
) +
gsi::method ("lef_pins_suffix_str=", &db::LEFDEFReaderOptions::set_lef_pins_suffix_str, gsi::arg ("suffix"),
"@hide"
) +
gsi::method ("lef_pins_datatype_str", &db::LEFDEFReaderOptions::lef_pins_datatype_str,
"@hide"
) +
gsi::method ("lef_pins_datatype_str=", &db::LEFDEFReaderOptions::set_lef_pins_datatype_str, gsi::arg ("datatype"),
"@hide"
) +
gsi::method ("produce_obstructions", &db::LEFDEFReaderOptions::produce_obstructions,
"@brief Gets a value indicating whether obstruction markers shall be produced.\n"
"See \\produce_via_geometry for details about the layer production rules."
@ -380,6 +598,218 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"@brief Sets the routing layer datatype value.\n"
"See \\produce_via_geometry for details about the layer production rules."
) +
gsi::method ("clear_routing_suffixes_per_mask", &db::LEFDEFReaderOptions::clear_routing_suffixes_per_mask,
"@brief Clears the routing layer name suffix per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("clear_routing_datatypes_per_mask", &db::LEFDEFReaderOptions::clear_routing_datatypes_per_mask,
"@brief Clears the routing layer datatypes per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("routing_suffix_per_mask", &db::LEFDEFReaderOptions::routing_suffix_per_mask, gsi::arg ("mask"),
"@brief Gets the routing geometry layer name suffix per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("set_routing_suffix_per_mask", &db::LEFDEFReaderOptions::set_routing_suffix_per_mask, gsi::arg ("mask"), gsi::arg ("suffix"),
"@brief Sets the routing geometry layer name suffix per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("routing_datatype", &db::LEFDEFReaderOptions::routing_datatype_per_mask,
"@brief Gets the routing geometry layer datatype value per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("set_routing_datatype_per_mask", &db::LEFDEFReaderOptions::set_routing_datatype_per_mask, gsi::arg ("mask"), gsi::arg ("datatype"),
"@brief Sets the routing geometry layer datatype value.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("routing_suffix_str", &db::LEFDEFReaderOptions::routing_suffix_str,
"@hide"
) +
gsi::method ("routing_suffix_str=", &db::LEFDEFReaderOptions::set_routing_suffix_str, gsi::arg ("suffix"),
"@hide"
) +
gsi::method ("routing_datatype_str", &db::LEFDEFReaderOptions::routing_datatype_str,
"@hide"
) +
gsi::method ("routing_datatype_str=", &db::LEFDEFReaderOptions::set_routing_datatype_str, gsi::arg ("datatype"),
"@hide"
) +
gsi::method ("produce_special_routing", &db::LEFDEFReaderOptions::produce_special_routing,
"@brief Gets a value indicating whether special routing geometry shall be produced.\n"
"See \\produce_via_geometry for details about the layer production rules.\n"
"\n"
"The differentiation between special and normal routing has been introduced in version 0.27."
) +
gsi::method ("produce_special_routing=", &db::LEFDEFReaderOptions::set_produce_special_routing, gsi::arg ("produce"),
"@brief Sets a value indicating whether special routing geometry shall be produced.\n"
"See \\produce_via_geometry for details about the layer production rules."
"\n"
"The differentiation between special and normal routing has been introduced in version 0.27."
) +
gsi::method ("special_routing_suffix", &db::LEFDEFReaderOptions::special_routing_suffix,
"@brief Gets the special routing layer name suffix.\n"
"See \\produce_via_geometry for details about the layer production rules."
"\n"
"The differentiation between special and normal routing has been introduced in version 0.27."
) +
gsi::method ("special_routing_suffix=", &db::LEFDEFReaderOptions::set_special_routing_suffix, gsi::arg ("suffix"),
"@brief Sets the special routing layer name suffix.\n"
"See \\produce_via_geometry for details about the layer production rules."
"\n"
"The differentiation between special and normal routing has been introduced in version 0.27."
) +
gsi::method ("special_routing_datatype", &db::LEFDEFReaderOptions::special_routing_datatype,
"@brief Gets the special routing layer datatype value.\n"
"See \\produce_via_geometry for details about the layer production rules."
"\n"
"The differentiation between special and normal routing has been introduced in version 0.27."
) +
gsi::method ("special_routing_datatype=", &db::LEFDEFReaderOptions::set_special_routing_datatype, gsi::arg ("datatype"),
"@brief Sets the special routing layer datatype value.\n"
"See \\produce_via_geometry for details about the layer production rules."
"\n"
"The differentiation between special and normal routing has been introduced in version 0.27."
) +
gsi::method ("clear_special_routing_suffixes_per_mask", &db::LEFDEFReaderOptions::clear_special_routing_suffixes_per_mask,
"@brief Clears the special routing layer name suffix per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("clear_special_routing_datatypes_per_mask", &db::LEFDEFReaderOptions::clear_special_routing_datatypes_per_mask,
"@brief Clears the special routing layer datatypes per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("special_routing_suffix_per_mask", &db::LEFDEFReaderOptions::special_routing_suffix_per_mask, gsi::arg ("mask"),
"@brief Gets the special routing geometry layer name suffix per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("set_special_routing_suffix_per_mask", &db::LEFDEFReaderOptions::set_special_routing_suffix_per_mask, gsi::arg ("mask"), gsi::arg ("suffix"),
"@brief Sets the special routing geometry layer name suffix per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("special_routing_datatype", &db::LEFDEFReaderOptions::special_routing_datatype_per_mask,
"@brief Gets the special routing geometry layer datatype value per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("set_special_routing_datatype_per_mask", &db::LEFDEFReaderOptions::set_special_routing_datatype_per_mask, gsi::arg ("mask"), gsi::arg ("datatype"),
"@brief Sets the special routing geometry layer datatype value.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("special_routing_suffix_str", &db::LEFDEFReaderOptions::special_routing_suffix_str,
"@hide"
) +
gsi::method ("special_routing_suffix_str=", &db::LEFDEFReaderOptions::set_special_routing_suffix_str, gsi::arg ("suffix"),
"@hide"
) +
gsi::method ("special_routing_datatype_str", &db::LEFDEFReaderOptions::special_routing_datatype_str,
"@hide"
) +
gsi::method ("special_routing_datatype_str=", &db::LEFDEFReaderOptions::set_special_routing_datatype_str, gsi::arg ("datatype"),
"@hide"
) +
gsi::method ("separate_groups", &db::LEFDEFReaderOptions::separate_groups,
"@brief Gets a value indicating whether to create separate parent cells for individual groups.\n"
"If this property is set to true, instances belonging to different groups are separated by putting them into "
"individual parent cells. These parent cells are named after the groups and are put into the master top cell.\n"
"If this property is set to false (the default), no such group parents will be formed."
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("separate_groups=", &db::LEFDEFReaderOptions::set_separate_groups, gsi::arg ("flag"),
"@brief Sets a value indicating whether to create separate parent cells for individual groups.\n"
"See \\seperate_groups for details about this property.\n"
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("map_file", &db::LEFDEFReaderOptions::map_file,
"@brief Gets the layer map file to use.\n"
"If a layer map file is given, the reader will pull the layer mapping from this file. The layer mapping rules "
"specified in the reader options are ignored in this case. These are the name suffix rules for vias, blockages, routing, "
"special routing, pins etc. and the corresponding datatype rules. The \\layer_map attribute will also be ignored. "
"\n"
"The layer map file path will be resolved relative to the technology base path if the LEF/DEF reader options are "
"used in the context of a technology.\n"
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("map_file=", &db::LEFDEFReaderOptions::set_map_file, gsi::arg ("file"),
"@brief Sets the layer map file to use.\n"
"See \\map_file for details about this property.\n"
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("macro_resolution_mode", &db::LEFDEFReaderOptions::macro_resolution_mode,
"@brief Gets the macro resolution mode.\n"
"This property describes the way LEF macros are turned into GDS cells. There "
"are three modes available:\n"
"\n"
"@ul\n"
" @li 0: produce LEF geometry unless a FOREIGN cell is specified (default) @/li\n"
" @li 1: produce LEF geometry always and ignore FOREIGN @/li\n"
" @li 2: Never produce LEF geometry @/li\n"
"@/ul\n"
"\n"
"If substitution layouts are specified with \\macro_layouts, these are used to provide "
"macro layouts in case no LEF geometry is taken.\n"
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("macro_resolution_mode=", &db::LEFDEFReaderOptions::set_macro_resolution_mode, gsi::arg ("mode"),
"@brief Sets the macro resolution mode.\n"
"See \\macro_resolution_mode for details about this property.\n"
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("macro_layouts", &db::LEFDEFReaderOptions::macro_layouts,
"@brief Gets the layout objects used for resolving LEF macros in the DEF reader.\n"
"The DEF reader can either use LEF geometry or use a separate source of layouts for the "
"LEF macros. The \\macro_resolution_mode controls whether to use LEF geometry. If LEF geometry is not "
"used, the DEF reader will look up macro cells from the \\macro_layouts and pull cell layouts from there.\n"
"\n"
"The LEF cells are looked up by name from the macro layouts in the order these are given in this array.\n"
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("macro_layouts=", &db::LEFDEFReaderOptions::set_macro_layouts,
"@brief Sets the layout objects used for resolving LEF macros in the DEF reader.\n"
"See \\macro_layouts for more details about this property.\n"
"\n"
"Layout objects specified in the array for this property are not owned by the \\LEFDEFReaderConfiguration object. "
"Be sure to keep some other reference to these Layout objects if you are storing away the LEF/DEF reader configuration object.\n"
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("lef_files", &db::LEFDEFReaderOptions::lef_files,
"@brief Gets the list technology LEF files to additionally import\n"
"Returns a list of path names for technology LEF files to read in addition to the primary file. "
@ -390,10 +820,39 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
gsi::method ("lef_files=", &db::LEFDEFReaderOptions::set_lef_files,
"@brief Sets the list technology LEF files to additionally import\n"
"See \\lef_files for details."
) +
gsi::method ("read_lef_with_def", &db::LEFDEFReaderOptions::read_lef_with_def,
"@brief Gets a value indicating whether to read all LEF files in the same directory than the DEF file.\n"
"If this property is set to true (the default), the DEF reader will automatically consume all LEF files "
"next to the DEF file in addition to the LEF files specified with \\lef_files. If set to false, only the "
"LEF files specified with \\lef_files will be read.\n"
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("read_lef_with_def=", &db::LEFDEFReaderOptions::set_read_lef_with_def, gsi::arg ("flag"),
"@brief Sets a value indicating whether to read all LEF files in the same directory than the DEF file.\n"
"See \\read_lef_with_def for details about this property.\n"
"\n"
"This property has been added in version 0.27.\n"
),
"@brief Detailed LEF/DEF reader options\n"
"This class is a aggregate belonging to the \\LoadLayoutOptions class. It provides options for the LEF/DEF reader. "
"These options have been placed into a separate class to account for their complexity."
"\n"
"This class specifically handles layer mapping. This is the process of generating layer names or GDS layer/datatypes "
"from LEF/DEF layers and purpose combinations. There are basically two ways: to use a map file or to use pattern-based production rules.\n"
"\n"
"To use a layer map file, set the \\map_file attribute to the name of the layer map file. The layer map "
"file lists the GDS layer and datatype numbers to generate for the geometry.\n"
"\n"
"The pattern-based approach will use the layer name and attach a purpose-dependent suffix to it. "
"Use the ..._suffix attributes to specify this suffix. For routing, the corresponding attribute is \\routing_suffix for example. "
"A purpose can also be mapped to a specific GDS datatype using the corresponding ..._datatype attributes.\n"
"The decorated or undecorated names are looked up in a layer mapping table in the next step. The layer mapping table "
"is specified using the \\layer_map attribute. This table can be used to map layer names to specific GDS layers "
"by using entries of the form 'NAME: layer-number'.\n"
"\n"
"If a layer map file is present, the pattern-based attributes are ignored.\n"
);
}

View File

@ -140,8 +140,7 @@ public:
}
}
db::LEFDEFLayerDelegate layers (&options);
layers.prepare (*layout);
db::LEFDEFReaderState state (&options, *layout);
layout->dbu (options.dbu ());
if (import_lef) {
@ -153,11 +152,11 @@ public:
for (std::vector<std::string>::const_iterator l = options.begin_lef_files (); l != options.end_lef_files (); ++l) {
tl::InputStream lef_stream (*l);
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l;
importer.read (lef_stream, *layout, layers);
importer.read (lef_stream, *layout, state);
}
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << data.file;
importer.read (stream, *layout, layers);
importer.read (stream, *layout, state);
} else {
@ -177,23 +176,23 @@ public:
if (fi.isAbsolute ()) {
tl::InputStream lef_stream (*l);
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l;
importer.read_lef (lef_stream, *layout, layers);
importer.read_lef (lef_stream, *layout, state);
} else {
std::string ex_l = tl::to_string (def_fi.absoluteDir ().absoluteFilePath (tl::to_qstring (*l)));
tl::InputStream lef_stream (ex_l);
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l;
importer.read_lef (lef_stream, *layout, layers);
importer.read_lef (lef_stream, *layout, state);
}
}
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << data.file;
importer.read (stream, *layout, layers);
importer.read (stream, *layout, state);
}
layers.finish (*layout);
state.finish (*layout);
lay::LayoutView *view = lay::LayoutView::current ();
if (! view || data.mode == 1) {

View File

@ -340,6 +340,26 @@ END_PROTECTED
// -----------------------------------------------------------------------------------------------
// LEFDEF technology components editor
static void
indicate_error (QWidget *le, const tl::Exception *ex)
{
// by the way, update the foreground color of the cell edit box as well (red, if not valid)
QPalette pl = le->palette ();
if (ex) {
pl.setColor (QPalette::Active, QPalette::Text, Qt::red);
pl.setColor (QPalette::Active, QPalette::Base, QColor (Qt::red).lighter (180));
le->setToolTip (tl::to_qstring (ex->msg ()));
} else {
QWidget *pw = dynamic_cast<QWidget *> (le->parent ());
tl_assert (pw != 0);
pl.setColor (QPalette::Active, QPalette::Text, pw->palette ().color (QPalette::Text));
pl.setColor (QPalette::Active, QPalette::Base, pw->palette ().color (QPalette::Base));
le->setToolTip (QString ());
}
le->setPalette (pl);
}
LEFDEFReaderOptionsEditor::LEFDEFReaderOptionsEditor (QWidget *parent)
: lay::StreamReaderOptionsPage (parent), mp_tech (0)
{
@ -353,19 +373,23 @@ LEFDEFReaderOptionsEditor::LEFDEFReaderOptionsEditor (QWidget *parent)
connect (produce_regions, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
connect (produce_via_geometry, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
connect (produce_pins, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
connect (produce_lef_pins, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
connect (produce_obstructions, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
connect (produce_blockages, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
connect (produce_routing, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
connect (produce_special_routing, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
connect (produce_labels, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
connect (add_lef_file, SIGNAL (clicked ()), this, SLOT (add_lef_file_clicked ()));
connect (del_lef_files, SIGNAL (clicked ()), this, SLOT (del_lef_files_clicked ()));
connect (move_lef_files_up, SIGNAL (clicked ()), this, SLOT (move_lef_files_up_clicked ()));
connect (move_lef_files_down, SIGNAL (clicked ()), this, SLOT (move_lef_files_down_clicked ()));
connect (browse_mapfile, SIGNAL (clicked ()), this, SLOT (browse_mapfile_clicked ()));
lay::activate_help_links (help_label);
lay::activate_help_links (help_label2);
}
void
void
LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, const db::Technology * /*tech*/)
{
db::LEFDEFReaderOptions *data = dynamic_cast<db::LEFDEFReaderOptions *> (options);
@ -373,6 +397,8 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con
return;
}
bool has_error = false;
data->set_read_all_layers (read_all_cbx->isChecked ());
data->set_layer_map (layer_map->get_layer_map ());
data->set_produce_net_names (produce_net_names->isChecked ());
@ -387,33 +413,88 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con
data->set_dbu (dbu_value);
// parse the net property name (may throw an exception)
{
try {
std::string np = tl::to_string (net_prop_name->text ());
tl::Extractor ex (np.c_str ());
tl::Variant v;
ex.read (v);
ex.expect_end ();
data->set_net_property_name (v);
indicate_error (net_prop_name, 0);
} catch (tl::Exception &ex) {
indicate_error (net_prop_name, &ex);
has_error = true;
}
// parse the inst property name (may throw an exception)
{
try {
std::string np = tl::to_string (inst_prop_name->text ());
tl::Extractor ex (np.c_str ());
tl::Variant v;
ex.read (v);
ex.expect_end ();
data->set_inst_property_name (v);
indicate_error (inst_prop_name, 0);
} catch (tl::Exception &ex) {
indicate_error (inst_prop_name, &ex);
has_error = true;
}
// parse the pin property name (may throw an exception)
{
try {
std::string np = tl::to_string (pin_prop_name->text ());
tl::Extractor ex (np.c_str ());
tl::Variant v;
ex.read (v);
ex.expect_end ();
data->set_pin_property_name (v);
indicate_error (pin_prop_name, 0);
} catch (tl::Exception &ex) {
indicate_error (pin_prop_name, &ex);
has_error = true;
}
// check the outline layer spec
try {
db::LayerProperties lp;
std::string s = tl::to_string (outline_layer->text ());
tl::Extractor ex (s.c_str ());
lp.read (ex);
ex.expect_end ();
indicate_error (outline_layer, 0);
} catch (tl::Exception &ex) {
indicate_error (outline_layer, &ex);
has_error = true;
}
// check the region layer spec
try {
db::LayerProperties lp;
std::string s = tl::to_string (region_layer->text ());
tl::Extractor ex (s.c_str ());
lp.read (ex);
ex.expect_end ();
indicate_error (region_layer, 0);
} catch (tl::Exception &ex) {
indicate_error (region_layer, &ex);
has_error = true;
}
// check the blockage layer spec
try {
db::LayerProperties lp;
std::string s = tl::to_string (placement_blockage_layer->text ());
tl::Extractor ex (s.c_str ());
lp.read (ex);
ex.expect_end ();
indicate_error (placement_blockage_layer, 0);
} catch (tl::Exception &ex) {
indicate_error (placement_blockage_layer, &ex);
has_error = true;
}
if (has_error) {
throw tl::Exception (tl::to_string (tr ("Some values are not correct - see highlighted entry fields")));
}
data->set_produce_cell_outlines (produce_outlines->isChecked ());
@ -423,11 +504,15 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con
data->set_produce_placement_blockages (produce_placement_blockages->isChecked ());
data->set_placement_blockage_layer (tl::to_string (placement_blockage_layer->text ()));
data->set_produce_via_geometry (produce_via_geometry->isChecked ());
data->set_via_geometry_suffix (tl::to_string (suffix_via_geometry->text ()));
data->set_via_geometry_datatype (datatype_via_geometry->text ().toInt ());
data->set_via_geometry_suffix_str (tl::to_string (suffix_via_geometry->text ()));
data->set_via_geometry_datatype_str (tl::to_string (datatype_via_geometry->text ()));
data->set_via_cellname_prefix (tl::to_string (prefix_via_cellname->text ()));
data->set_produce_pins (produce_pins->isChecked ());
data->set_pins_suffix (tl::to_string (suffix_pins->text ()));
data->set_pins_datatype (datatype_pins->text ().toInt ());
data->set_pins_suffix_str (tl::to_string (suffix_pins->text ()));
data->set_pins_datatype_str (tl::to_string (datatype_pins->text ()));
data->set_produce_lef_pins (produce_lef_pins->isChecked ());
data->set_lef_pins_suffix_str (tl::to_string (suffix_lef_pins->text ()));
data->set_lef_pins_datatype_str (tl::to_string (datatype_lef_pins->text ()));
data->set_produce_obstructions (produce_obstructions->isChecked ());
data->set_obstructions_suffix (tl::to_string (suffix_obstructions->text ()));
data->set_obstructions_datatype (datatype_obstructions->text ().toInt ());
@ -435,11 +520,18 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con
data->set_blockages_suffix (tl::to_string (suffix_blockages->text ()));
data->set_blockages_datatype (datatype_blockages->text ().toInt ());
data->set_produce_routing (produce_routing->isChecked ());
data->set_routing_suffix (tl::to_string (suffix_routing->text ()));
data->set_routing_datatype (datatype_routing->text ().toInt ());
data->set_routing_suffix_str (tl::to_string (suffix_routing->text ()));
data->set_routing_datatype_str (tl::to_string (datatype_routing->text ()));
data->set_produce_special_routing (produce_special_routing->isChecked ());
data->set_special_routing_suffix_str (tl::to_string (suffix_special_routing->text ()));
data->set_special_routing_datatype_str (tl::to_string (datatype_special_routing->text ()));
data->set_produce_labels (produce_labels->isChecked ());
data->set_labels_suffix (tl::to_string (suffix_labels->text ()));
data->set_labels_datatype (datatype_labels->text ().toInt ());
data->set_separate_groups (separate_groups->isChecked ());
data->set_read_lef_with_def (read_lef_with_def->isChecked ());
data->set_map_file (tl::to_string (mapfile_path->text ()));
data->set_macro_resolution_mode (produce_lef_geo->isChecked () ? 0 : 2);
data->clear_lef_files ();
for (int i = 0; i < lef_files->count (); ++i) {
@ -475,11 +567,15 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options
produce_placement_blockages->setChecked (data->produce_placement_blockages ());
placement_blockage_layer->setText (tl::to_qstring (data->placement_blockage_layer ()));
produce_via_geometry->setChecked (data->produce_via_geometry ());
suffix_via_geometry->setText (tl::to_qstring (data->via_geometry_suffix ()));
datatype_via_geometry->setText (QString::number (data->via_geometry_datatype ()));
suffix_via_geometry->setText (tl::to_qstring (data->via_geometry_suffix_str ()));
datatype_via_geometry->setText (tl::to_qstring (data->via_geometry_datatype_str ()));
prefix_via_cellname->setText (tl::to_qstring (data->via_cellname_prefix ()));
produce_pins->setChecked (data->produce_pins ());
suffix_pins->setText (tl::to_qstring (data->pins_suffix ()));
datatype_pins->setText (QString::number (data->pins_datatype ()));
suffix_pins->setText (tl::to_qstring (data->pins_suffix_str ()));
datatype_pins->setText (tl::to_qstring (data->pins_datatype_str ()));
produce_lef_pins->setChecked (data->produce_lef_pins ());
suffix_lef_pins->setText (tl::to_qstring (data->lef_pins_suffix_str ()));
datatype_lef_pins->setText (tl::to_qstring (data->lef_pins_datatype_str ()));
produce_obstructions->setChecked (data->produce_obstructions ());
suffix_obstructions->setText (tl::to_qstring (data->obstructions_suffix ()));
datatype_obstructions->setText (QString::number (data->obstructions_datatype ()));
@ -487,11 +583,19 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options
suffix_blockages->setText (tl::to_qstring (data->blockages_suffix ()));
datatype_blockages->setText (QString::number (data->blockages_datatype ()));
produce_routing->setChecked (data->produce_routing ());
suffix_routing->setText (tl::to_qstring (data->routing_suffix ()));
datatype_routing->setText (QString::number (data->routing_datatype ()));
suffix_routing->setText (tl::to_qstring (data->routing_suffix_str ()));
datatype_routing->setText (tl::to_qstring (data->routing_datatype_str ()));
produce_special_routing->setChecked (data->produce_special_routing ());
suffix_special_routing->setText (tl::to_qstring (data->special_routing_suffix_str ()));
datatype_special_routing->setText (tl::to_qstring (data->special_routing_datatype_str ()));
produce_labels->setChecked (data->produce_labels ());
suffix_labels->setText (tl::to_qstring (data->labels_suffix ()));
datatype_labels->setText (QString::number (data->labels_datatype ()));
separate_groups->setChecked (data->separate_groups ());
read_lef_with_def->setChecked (data->read_lef_with_def ());
mapfile_path->setText (tl::to_qstring (data->map_file ()));
layer_map_mode->setCurrentIndex (data->map_file ().empty () ? 1 : 0);
produce_lef_geo->setChecked (data->macro_resolution_mode () == 0);
checkbox_changed ();
@ -519,25 +623,51 @@ LEFDEFReaderOptionsEditor::checkbox_changed ()
placement_blockage_layer->setEnabled (produce_placement_blockages->isChecked ());
suffix_via_geometry->setEnabled (produce_via_geometry->isChecked ());
suffix_pins->setEnabled (produce_pins->isChecked ());
suffix_lef_pins->setEnabled (produce_lef_pins->isChecked ());
suffix_obstructions->setEnabled (produce_obstructions->isChecked ());
suffix_blockages->setEnabled (produce_blockages->isChecked ());
suffix_routing->setEnabled (produce_routing->isChecked ());
suffix_special_routing->setEnabled (produce_special_routing->isChecked ());
suffix_labels->setEnabled (produce_labels->isChecked ());
datatype_via_geometry->setEnabled (produce_via_geometry->isChecked ());
datatype_pins->setEnabled (produce_pins->isChecked ());
datatype_lef_pins->setEnabled (produce_lef_pins->isChecked ());
datatype_obstructions->setEnabled (produce_obstructions->isChecked ());
datatype_blockages->setEnabled (produce_blockages->isChecked ());
datatype_routing->setEnabled (produce_routing->isChecked ());
datatype_special_routing->setEnabled (produce_special_routing->isChecked ());
datatype_labels->setEnabled (produce_labels->isChecked ());
}
void
LEFDEFReaderOptionsEditor::browse_mapfile_clicked ()
{
std::string title, filters;
title = tl::to_string (QObject::tr ("Select Layer Map File"));
filters = tl::to_string (QObject::tr ("LEF/DEF layer map files (*.map);;All files (*)"));
QString file = QFileDialog::getOpenFileName (this, tl::to_qstring (title), QString (), tl::to_qstring (filters));
if (! file.isNull ()) {
if (mp_tech) {
mapfile_path->setText (tl::to_qstring (mp_tech->correct_path (tl::to_string (file))));
} else {
mapfile_path->setText (file);
}
}
}
void
LEFDEFReaderOptionsEditor::add_lef_file_clicked ()
{
std::string title, filters;
title = tl::to_string (QObject::tr ("Add LEF Files"));
filters = tl::to_string (QObject::tr ("LEF files (*.lef *.LEF *.lef.gz *.LEF.gz);;All files (*)"));
QStringList files = QFileDialog::getOpenFileNames (this, tl::to_qstring (title), QString (), tl::to_qstring (filters));
std::string dir;
if (mp_tech) {
dir = mp_tech->base_path ();
}
QStringList files = QFileDialog::getOpenFileNames (this, tl::to_qstring (title), tl::to_qstring (dir), tl::to_qstring (filters));
for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) {
if (mp_tech) {
lef_files->addItem (tl::to_qstring (mp_tech->correct_path (tl::to_string (*f))));

View File

@ -98,6 +98,7 @@ private slots:
void del_lef_files_clicked ();
void move_lef_files_up_clicked ();
void move_lef_files_down_clicked ();
void browse_mapfile_clicked ();
private:
tl::weak_ptr<db::Technology> mp_tech;

View File

@ -1,267 +0,0 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 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 "dbLayoutDiff.h"
#include "dbWriter.h"
#include "dbDEFImporter.h"
#include "dbLEFImporter.h"
#include "tlUnitTest.h"
#include <cstdlib>
static db::LEFDEFReaderOptions default_options ()
{
db::LEFDEFReaderOptions tc;
tc.set_via_geometry_datatype (0);
tc.set_via_geometry_suffix ("");
tc.set_pins_datatype (2);
tc.set_pins_suffix (".PIN");
tc.set_obstructions_datatype (3);
tc.set_obstructions_suffix (".OBS");
tc.set_routing_datatype (0);
tc.set_routing_suffix ("");
tc.set_labels_datatype (1);
tc.set_labels_suffix (".LABEL");
tc.set_blockages_datatype (4);
tc.set_blockages_suffix (".BLK");
return tc;
}
static void run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &tc, bool priv = true)
{
db::LEFDEFLayerDelegate ld (&tc);
db::Manager m (false);
db::Layout layout (&m), layout2 (&m), layout_au (&m);
tl::Extractor ex (filename);
ld.prepare (layout);
db::DEFImporter imp;
while (! ex.at_end ()) {
if (ex.test ("def:")) {
std::string fn (priv ? tl::testsrc_private () : tl::testsrc ());
fn += "/testdata/lefdef/";
fn += lef_dir;
fn += "/";
std::string f;
ex.read_word_or_quoted (f);
fn += f;
tl::InputStream stream (fn);
imp.read (stream, layout, ld);
} else if (ex.test ("lef:")) {
std::string fn (priv ? tl::testsrc_private () : tl::testsrc ());
fn += "/testdata/lefdef/";
fn += lef_dir;
fn += "/";
std::string f;
ex.read_word_or_quoted (f);
fn += f;
tl::InputStream stream (fn);
imp.read_lef (stream, layout, ld);
} else {
break;
}
if (! ex.test("+")) {
break;
}
}
ld.finish (layout);
// normalize the layout by writing to OASIS and reading from ..
std::string tmp_file = _this->tmp_file ("tmp.oas");
{
tl::OutputStream stream (tmp_file);
db::SaveLayoutOptions options;
options.set_format ("OASIS");
db::Writer writer (options);
writer.write (layout, stream);
}
{
tl::InputStream stream (tmp_file);
db::Reader reader (stream);
reader.read (layout2);
}
if (au) {
std::string fn (priv ? tl::testsrc_private () : tl::testsrc ());
fn += "/testdata/lefdef/";
fn += lef_dir;
fn += "/";
fn += au;
try {
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (layout_au);
} catch (...) {
_this->raise (tl::sprintf ("Compare failed - see %s vs %s (not existing or not readable)\n", tmp_file, fn));
throw;
}
bool equal = db::compare_layouts (layout2, layout_au, db::layout_diff::f_verbose | db::layout_diff::f_flatten_array_insts, 0);
if (! equal) {
_this->raise (tl::sprintf ("Compare failed - see %s vs %s\n", tmp_file, fn));
}
} else {
bool equal = db::compare_layouts (layout2, layout_au, db::layout_diff::f_verbose | db::layout_diff::f_flatten_array_insts, 0);
if (! equal) {
_this->raise (tl::sprintf ("Compare failed - see %s vs empty file\n", tmp_file));
}
}
}
TEST(1)
{
run_test (_this, "lef1", "lef:in.lef", 0, default_options ());
}
TEST(2)
{
run_test (_this, "lef2", "lef:in.lef", "au.oas.gz", default_options ());
}
TEST(3)
{
run_test (_this, "lef3", "lef:in.lef", "au.oas.gz", default_options ());
}
TEST(4)
{
run_test (_this, "lef4", "lef:in.lef", 0, default_options ());
}
TEST(5)
{
run_test (_this, "lef5", "lef:in.lef", 0, default_options ());
}
TEST(6)
{
run_test (_this, "lef6", "lef:in.lef", 0, default_options ());
}
TEST(7)
{
run_test (_this, "lef7", "lef:in_tech.lef+lef:in.lef", "au.oas.gz", default_options ());
}
TEST(10)
{
run_test (_this, "def1", "lef:in.lef+def:in.def", "au.oas.gz", default_options ());
}
TEST(11)
{
run_test (_this, "def2", "lef:0.lef+lef:1.lef+def:in.def.gz", "au.oas.gz", default_options ());
}
TEST(12)
{
run_test (_this, "def3", "lef:in.lef+def:in.def", "au.oas.gz", default_options ());
}
TEST(13)
{
run_test (_this, "def4", "lef:in.lef+def:in.def", "au.oas.gz", default_options ());
}
TEST(14)
{
run_test (_this, "def5", "lef:in.lef+def:in.def", "au.oas.gz", default_options ());
}
TEST(15)
{
run_test (_this, "def6", "lef:cells.lef+lef:tech.lef+def:in.def.gz", "au.oas.gz", default_options ());
}
TEST(16)
{
run_test (_this, "def7", "lef:cells.lef+lef:tech.lef+def:in.def.gz", "au.oas.gz", default_options ());
}
TEST(17)
{
run_test (_this, "def8", "lef:tech.lef+def:in.def", "au.oas.gz", default_options ());
}
TEST(18)
{
run_test (_this, "def9", "lef:tech.lef+lef:cells_modified.lef+def:in.def", "au.oas.gz", default_options ());
}
TEST(19)
{
run_test (_this, "def10", "def:in.def", "au.oas.gz", default_options ());
}
TEST(20)
{
run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", default_options (), false);
}
TEST(21)
{
db::LEFDEFReaderOptions opt = default_options ();
opt.set_produce_pin_names (true);
opt.set_pin_property_name (2);
run_test (_this, "issue-489", "lef:in.lef+def:in.def", "au.oas", opt, false);
}
TEST(22)
{
db::LEFDEFReaderOptions opt = default_options ();
opt.set_produce_pin_names (true);
opt.set_pin_property_name (3);
run_test (_this, "issue-489b", "lef:in_tech.lef+lef:in.lef", "au.oas.gz", opt, false);
}
TEST(23)
{
run_test (_this, "issue-517", "def:in.def", "au.oas.gz", default_options (), false);
}

View File

@ -0,0 +1,596 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 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 "dbLayoutDiff.h"
#include "dbWriter.h"
#include "dbDEFImporter.h"
#include "dbLEFImporter.h"
#include "tlUnitTest.h"
#include "dbTestSupport.h"
#include <cstdlib>
static db::LEFDEFReaderOptions default_options ()
{
db::LEFDEFReaderOptions tc;
tc.set_via_geometry_datatype (0);
tc.set_via_geometry_suffix ("");
tc.set_pins_datatype (2);
tc.set_pins_suffix (".PIN");
tc.set_obstructions_datatype (3);
tc.set_obstructions_suffix (".OBS");
tc.set_routing_datatype (0);
tc.set_routing_suffix ("");
tc.set_labels_datatype (1);
tc.set_labels_suffix (".LABEL");
tc.set_blockages_datatype (4);
tc.set_blockages_suffix (".BLK");
return tc;
}
static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &options, bool priv = true)
{
std::string fn_path (priv ? tl::testsrc_private () : tl::testsrc ());
fn_path += "/testdata/lefdef/";
fn_path += lef_dir;
fn_path += "/";
db::Manager m (false);
db::Layout layout (&m), layout2 (&m), layout_au (&m);
tl::Extractor ex (filename);
db::LEFDEFReaderState ld (&options, layout, fn_path);
db::DEFImporter imp;
bool any_def = false;
bool any_lef = false;
while (! ex.at_end ()) {
if (ex.test ("map:")) {
std::string fn = fn_path, f;
ex.read_word_or_quoted (f);
fn += f;
ld.read_map_file (fn, layout);
} else if (ex.test ("def:")) {
std::string fn = fn_path, f;
ex.read_word_or_quoted (f);
fn += f;
tl::InputStream stream (fn);
imp.read (stream, layout, ld);
any_def = true;
} else if (ex.test ("lef:")) {
std::string fn = fn_path, f;
ex.read_word_or_quoted (f);
fn += f;
tl::InputStream stream (fn);
imp.read_lef (stream, layout, ld);
any_lef = true;
} else if (ex.test ("gds:")) {
std::string fn = fn_path, f;
ex.read_word_or_quoted (f);
fn += f;
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (layout, db::LoadLayoutOptions ());
} else if (ex.test("read:")) {
std::string fn = fn_path, f;
ex.read_word_or_quoted (f);
fn += f;
tl::InputStream stream (fn);
db::Reader reader (stream);
db::LoadLayoutOptions lo;
lo.set_options (options);
reader.read (layout, lo);
any_def = true;
} else {
break;
}
if (! ex.test("+")) {
break;
}
}
if (! any_def && any_lef) {
imp.finish_lef (layout);
}
ld.finish (layout);
// normalize the layout by writing to OASIS and reading from ..
// generate a "unique" name ...
unsigned int hash = 0;
if (au) {
for (const char *cp = au; *cp; ++cp) {
hash = (hash << 4) ^ (hash >> 4) ^ ((unsigned int) *cp);
}
}
std::string tmp_file = _this->tmp_file (tl::sprintf ("tmp_%x.oas", hash));
{
tl::OutputStream stream (tmp_file);
db::SaveLayoutOptions options;
options.set_format ("OASIS");
options.set_option_by_name ("oasis_permissive", tl::Variant (true));
db::Writer writer (options);
writer.write (layout, stream);
}
{
tl::InputStream stream (tmp_file);
db::Reader reader (stream);
reader.read (layout2);
}
if (au) {
std::string fn (priv ? tl::testsrc_private () : tl::testsrc ());
fn += "/testdata/lefdef/";
fn += lef_dir;
fn += "/";
fn += au;
try {
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (layout_au);
} catch (...) {
_this->raise (tl::sprintf ("Compare failed - see %s vs %s (not existing or not readable)\n", tmp_file, fn));
throw;
}
bool equal = db::compare_layouts (layout2, layout_au, db::layout_diff::f_verbose | db::layout_diff::f_flatten_array_insts, 0);
if (! equal) {
_this->raise (tl::sprintf ("Compare failed - see %s vs %s\n", tmp_file, fn));
}
} else {
bool equal = db::compare_layouts (layout2, layout_au, db::layout_diff::f_verbose | db::layout_diff::f_flatten_array_insts, 0);
if (! equal) {
_this->raise (tl::sprintf ("Compare failed - see %s vs empty file\n", tmp_file));
}
}
return ld.layer_map ();
}
TEST(1)
{
run_test (_this, "lef1", "lef:in.lef", 0, default_options ());
}
TEST(2)
{
// Also tests ability of plugin to properly read LEF
run_test (_this, "lef2", "read:in.lef", "au.oas.gz", default_options ());
}
TEST(3)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_cell_outline_layer ("OUTLINE (2/0)");
run_test (_this, "lef3", "lef:in.lef", "au.oas.gz", options);
}
TEST(4)
{
run_test (_this, "lef4", "lef:in.lef", 0, default_options ());
}
TEST(5)
{
run_test (_this, "lef5", "lef:in.lef", 0, default_options ());
}
TEST(6)
{
run_test (_this, "lef6", "lef:in.lef", 0, default_options ());
}
TEST(7)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_cell_outline_layer ("OUTLINE (8/0)");
run_test (_this, "lef7", "lef:in_tech.lef+lef:in.lef", "au.oas.gz", options);
}
TEST(10)
{
run_test (_this, "def1", "lef:in.lef+def:in.def", "au.oas.gz", default_options ());
}
TEST(11)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_cell_outline_layer ("OUTLINE (10/0)");
run_test (_this, "def2", "lef:0.lef+lef:1.lef+def:in.def.gz", "au.oas.gz", options);
}
TEST(12)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_cell_outline_layer ("OUTLINE (13/0)");
run_test (_this, "def3", "lef:in.lef+def:in.def", "au.oas.gz", options);
}
TEST(13)
{
run_test (_this, "def4", "lef:in.lef+def:in.def", "au.oas.gz", default_options ());
}
TEST(14)
{
run_test (_this, "def5", "lef:in.lef+def:in.def", "au.oas.gz", default_options ());
}
TEST(15)
{
run_test (_this, "def6", "lef:cells.lef+lef:tech.lef+def:in.def.gz", "au-new.oas.gz", default_options ());
}
TEST(16)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_placement_blockage_layer ("PLACEMENT_BLK (11/0)");
run_test (_this, "def7", "lef:cells.lef+lef:tech.lef+def:in.def.gz", "au-new.oas.gz", options);
options.set_placement_blockage_layer ("PLACEMENT_BLK (60/0)");
run_test (_this, "def7", "map:in.map+lef:cells.lef+lef:tech.lef+def:in.def.gz", "au_with_map_file-new.oas.gz", options);
}
TEST(17)
{
run_test (_this, "def8", "lef:tech.lef+def:in.def", "au.oas.gz", default_options ());
}
TEST(18)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_separate_groups (true);
run_test (_this, "def9", "lef:tech.lef+lef:cells_modified.lef+def:in.def", "au-new.oas.gz", options);
run_test (_this, "def9", "lef:tech.lef+lef:cells_modified.lef+def:in.def", "au_nogroups-new.oas.gz", default_options ());
}
TEST(19)
{
db::LEFDEFReaderOptions opt = default_options ();
opt.set_cell_outline_layer ("OUTLINE (2/0)");
run_test (_this, "def10", "def:in.def", "au.oas.gz", opt);
}
TEST(20)
{
db::LEFDEFReaderOptions opt = default_options ();
opt.set_cell_outline_layer ("OUTLINE (12/0)");
run_test (_this, "def11", "lef:test.lef+def:test.def", "au.oas.gz", opt);
}
TEST(21)
{
db::LEFDEFReaderOptions opt = default_options ();
opt.set_cell_outline_layer ("OUTLINE (20/0)");
run_test (_this, "def12", "lef:test.lef+def:test.def", "au-new.oas.gz", opt);
}
TEST(22)
{
db::LEFDEFReaderOptions opt = default_options ();
run_test (_this, "def13", "map:test.map+lef:test.lef_5.8+def:top.def.gz", "au.oas.gz", opt);
}
TEST(100)
{
run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", default_options (), false);
}
TEST(101)
{
db::LEFDEFReaderOptions opt = default_options ();
opt.set_produce_pin_names (true);
opt.set_pin_property_name (2);
opt.set_cell_outline_layer ("OUTLINE (13/0)");
run_test (_this, "issue-489", "lef:in.lef+def:in.def", "au.oas", opt, false);
}
TEST(102)
{
db::LEFDEFReaderOptions opt = default_options ();
opt.set_produce_pin_names (true);
opt.set_pin_property_name (3);
opt.set_cell_outline_layer ("OUTLINE (8/0)");
run_test (_this, "issue-489b", "lef:in_tech.lef+lef:in.lef", "au.oas.gz", opt, false);
}
TEST(103)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_cell_outline_layer ("OUTLINE (4/0)");
run_test (_this, "issue-517", "def:in.def", "au.oas.gz", options, false);
}
TEST(104_doxy_vias)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_cell_outline_layer ("OUTLINE (4/0)");
run_test (_this, "doxy_vias", "def:test.def", "au.oas.gz", options, false);
}
TEST(105_specialnets_geo)
{
run_test (_this, "specialnets_geo", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
db::LEFDEFReaderOptions options = default_options ();
options.set_produce_special_routing (false);
run_test (_this, "specialnets_geo", "lef:test.lef+def:test.def", "au_no_spnet.oas.gz", options, false);
options.set_produce_special_routing (true);
options.set_special_routing_datatype (10);
options.set_special_routing_suffix (".SPNET");
options.set_via_geometry_datatype (11);
options.set_via_geometry_suffix (".VIA");
run_test (_this, "specialnets_geo", "lef:test.lef+def:test.def", "au_spnet_mapped.oas.gz", options, false);
}
TEST(106_wrongdirection)
{
run_test (_this, "wrongdirection", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
}
TEST(107_specialwidths)
{
run_test (_this, "specialwidths", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
}
TEST(108_scanchain)
{
run_test (_this, "scanchain", "def:test.def", "au.oas.gz", default_options (), false);
}
TEST(109_foreigncell)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_cell_outline_layer ("OUTLINE (43/0)");
run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef+def:in.def", "au.oas.gz", options, false);
run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in2.lef+def:in.def", "au_default.oas.gz", options, false);
options.set_macro_resolution_mode (1);
run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in2.lef+def:in.def", "au_ignore_foreign.oas.gz", options, false);
options.set_macro_resolution_mode (2);
run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef+def:in.def", "au_always_foreign.oas.gz", options, false);
}
TEST(110_lefpins)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_produce_lef_pins (false);
options.set_cell_outline_layer ("OUTLINE (8/0)");
run_test (_this, "lefpins", "lef:in_tech.lef+lef:in.lef+def:in.def", "au_no_lefpins.oas.gz", options, false);
options.set_produce_lef_pins (true);
options.set_lef_pins_datatype (10);
options.set_lef_pins_suffix (".LEFPIN");
run_test (_this, "lefpins", "lef:in_tech.lef+lef:in.lef+def:in.def", "au_lefpins_mapped.oas.gz", options, false);
}
TEST(111_mapfile)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_map_file ("test.map");
run_test (_this, "mapfile", "read:in.def", "au.oas.gz", options, false);
}
TEST(112_via_properties)
{
db::LEFDEFReaderOptions options = default_options ();
db::LayerMap lm = db::LayerMap::from_string_file_format ("metal1: 1\nvia1: 2\nmetal2: 3");
options.set_layer_map (lm);
db::LayerMap lm_read = run_test (_this, "via_properties", "lef:in.lef+def:in.def", "au.oas.gz", options, false);
EXPECT_EQ (lm_read.to_string (),
"layer_map('OUTLINE : OUTLINE (4/0)';'metal1.VIA : metal1 (1/0)';'metal2.VIA : metal2 (3/0)';'via1.VIA : via1 (2/0)')"
)
}
TEST(113_masks_1)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_routing_suffix ("");
options.set_routing_datatype_per_mask (1, 100);
options.set_routing_datatype_per_mask (2, 200);
options.set_special_routing_suffix ("");
options.set_special_routing_datatype_per_mask (1, 101);
options.set_special_routing_datatype_per_mask (2, 201);
options.set_via_geometry_suffix ("");
options.set_via_geometry_datatype_per_mask (1, 102);
options.set_via_geometry_datatype_per_mask (2, 202);
options.set_pins_suffix ("");
options.set_pins_datatype_per_mask (1, 110);
options.set_pins_datatype_per_mask (2, 210);
options.set_cell_outline_layer ("OUTLINE (4/0)");
db::LayerMap lm = db::LayerMap::from_string_file_format ("M1: 3\nM0PO: 1\nVIA0: 2");
options.set_layer_map (lm);
db::LayerMap lm_read = run_test (_this, "masks-1", "lef:in_tech.lef+def:in.def", "au.oas.gz", options, false);
EXPECT_EQ (lm_read.to_string_file_format (),
"OUTLINE : OUTLINE (4/0)\n"
"'M0PO.SPNET:1' : M0PO (1/101)\n"
"'M1.SPNET:2' : M1 (3/201)\n"
"'M1.SPNET:1' : M1 (3/101)\n"
"'M0PO.VIA:2' : M0PO (1/202)\n"
"'M1.VIA:1' : M1 (3/102)\n"
"'VIA0.VIA:1' : VIA0 (2/102)\n"
"'M0PO.SPNET:2' : M0PO (1/201)\n"
"M0PO.PIN : M0PO (1/2)\n"
"M0PO.LABEL : M0PO.LABEL (1/1)\n"
"'M0PO.PIN:2' : M0PO (1/210)\n"
"'M1.PIN:1' : M1 (3/110)\n"
"M1.LABEL : M1.LABEL (3/1)\n"
"'M1.NET:1' : M1 (3/100)\n"
"'M1.NET:2' : M1 (3/200)\n"
"'M0PO.VIA:1' : M0PO (1/102)\n"
"'M1.VIA:2' : M1 (3/202)\n"
"'VIA0.VIA:2' : VIA0 (2/202)\n"
"'M0PO.NET:1' : M0PO (1/100)\n"
)
options = default_options ();
lm_read = run_test (_this, "masks-1", "map:in.map+lef:in_tech.lef+def:in.def", "au_map.oas.gz", options, false);
EXPECT_EQ (lm_read.to_string_file_format (),
"OUTLINE : OUTLINE (4/0)\n"
"'M0PO.NET:1' : 'M0PO.NET:1' (1/100)\n"
"'M0PO.NET:2' : 'M0PO.NET:2' (1/200)\n"
"M0PO.PIN : M0PO.PIN (1/2)\n"
"'M0PO.PIN:1' : 'M0PO.PIN:1' (1/110)\n"
"'M0PO.PIN:2' : 'M0PO.PIN:2' (1/210)\n"
"'M0PO.SPNET:1' : 'M0PO.SPNET:1' (1/101)\n"
"'M0PO.SPNET:2' : 'M0PO.SPNET:2' (1/201)\n"
"'M0PO.VIA:1' : 'M0PO.VIA:1' (1/102)\n"
"'M0PO.VIA:2' : 'M0PO.VIA:2' (1/202)\n"
"M0PO.LABEL : M0PO.LABEL (1/1)\n"
"'M1.NET:1' : 'M1.NET:1' (3/100)\n"
"'M1.NET:2' : 'M1.NET:2' (3/200)\n"
"M1.PIN : M1.PIN (3/2)\n"
"'M1.PIN:1' : 'M1.PIN:1' (3/110)\n"
"'M1.PIN:2' : 'M1.PIN:2' (3/210)\n"
"'M1.SPNET:1' : 'M1.SPNET:1' (3/101)\n"
"'M1.SPNET:2' : 'M1.SPNET:2' (3/201)\n"
"'M1.VIA:1' : 'M1.VIA:1' (3/102)\n"
"'M1.VIA:2' : 'M1.VIA:2' (3/202)\n"
"M1.LABEL : M1.LABEL (3/1)\n"
"'VIA0.NET:1' : 'VIA0.NET:1' (2/100)\n"
"'VIA0.NET:2' : 'VIA0.NET:2' (2/200)\n"
"VIA0.PIN : VIA0.PIN (2/2)\n"
"'VIA0.PIN:1' : 'VIA0.PIN:1' (2/110)\n"
"'VIA0.PIN:2' : 'VIA0.PIN:2' (2/210)\n"
"'VIA0.SPNET:1' : 'VIA0.SPNET:1' (2/101)\n"
"'VIA0.SPNET:2' : 'VIA0.SPNET:2' (2/201)\n"
"'VIA0.VIA:1' : 'VIA0.VIA:1' (2/102)\n"
"'VIA0.VIA:2' : 'VIA0.VIA:2' (2/202)\n"
"VIA0.LABEL : VIA0.LABEL (2/1)\n"
)
}
TEST(114_lef_skips_end_library)
{
db::LEFDEFReaderOptions opt = default_options ();
opt.set_produce_pin_names (true);
opt.set_pin_property_name (2);
opt.set_cell_outline_layer ("OUTLINE (13/0)");
run_test (_this, "lef-skips-end-library", "lef:in.lef+def:in.def", "au.oas", opt, false);
}
TEST(115_componentmaskshift)
{
db::LEFDEFReaderOptions options = default_options ();
options.set_map_file ("in.map");
run_test (_this, "masks-2", "lef:in_tech.lef+lef:in.lef+def:in.def", "au.oas.gz", options, false);
}
TEST(200_lefdef_plugin)
{
db::Layout ly;
std::string fn_path (tl::testsrc ());
fn_path += "/testdata/lefdef/masks-1/";
db::LEFDEFReaderOptions lefdef_opt = default_options ();
lefdef_opt.set_map_file ("in.map");
db::LoadLayoutOptions opt;
opt.set_options (lefdef_opt);
{
tl::InputStream is (fn_path + "in.def");
db::Reader reader (is);
reader.read (ly, opt);
}
db::compare_layouts (_this, ly, fn_path + "au_plugin_def.oas.gz", db::WriteOAS);
}
TEST(201_lefdef_plugin_explicit_lef)
{
db::Layout ly;
std::string fn_path (tl::testsrc ());
fn_path += "/testdata/lefdef/masks-1/";
db::LEFDEFReaderOptions lefdef_opt = default_options ();
lefdef_opt.set_map_file ("in.map");
std::vector<std::string> lf;
lf.push_back ("hidden/in_tech.lef");
lefdef_opt.set_lef_files (lf);
lefdef_opt.set_read_lef_with_def (false);
db::LoadLayoutOptions opt;
opt.set_options (lefdef_opt);
{
tl::InputStream is (fn_path + "in.def");
db::Reader reader (is);
reader.read (ly, opt);
}
db::compare_layouts (_this, ly, fn_path + "au_plugin_alt_lef.oas.gz", db::WriteOAS);
}

View File

@ -0,0 +1,327 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 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 "dbLEFDEFImporter.h"
#include "tlUnitTest.h"
#include <cstdlib>
TEST(1)
{
db::LEFDEFReaderOptions options;
EXPECT_EQ (options.max_mask_number (), (unsigned int) 0);
options.set_dbu (1.5);
EXPECT_EQ (options.dbu (), 1.5);
options.set_produce_net_names (true);
EXPECT_EQ (options.produce_net_names (), true);
options.set_produce_net_names (false);
EXPECT_EQ (options.produce_net_names (), false);
options.set_net_property_name (tl::Variant (12));
EXPECT_EQ (options.net_property_name ().to_string (), "12");
options.set_produce_inst_names (true);
EXPECT_EQ (options.produce_inst_names (), true);
options.set_produce_inst_names (false);
EXPECT_EQ (options.produce_inst_names (), false);
options.set_inst_property_name (tl::Variant (12));
EXPECT_EQ (options.inst_property_name ().to_string (), "12");
options.set_produce_pin_names (true);
EXPECT_EQ (options.produce_pin_names (), true);
options.set_produce_pin_names (false);
EXPECT_EQ (options.produce_pin_names (), false);
options.set_pin_property_name (tl::Variant (12));
EXPECT_EQ (options.pin_property_name ().to_string (), "12");
options.set_produce_cell_outlines (true);
EXPECT_EQ (options.produce_cell_outlines (), true);
options.set_produce_cell_outlines (false);
EXPECT_EQ (options.produce_cell_outlines (), false);
options.set_cell_outline_layer ("OL");
EXPECT_EQ (options.cell_outline_layer (), "OL");
options.set_produce_placement_blockages (true);
EXPECT_EQ (options.produce_placement_blockages (), true);
options.set_produce_placement_blockages (false);
EXPECT_EQ (options.produce_placement_blockages (), false);
options.set_placement_blockage_layer ("B");
EXPECT_EQ (options.placement_blockage_layer (), "B");
options.set_produce_regions (true);
EXPECT_EQ (options.produce_regions (), true);
options.set_produce_regions (false);
EXPECT_EQ (options.produce_regions (), false);
options.set_region_layer ("R");
EXPECT_EQ (options.region_layer (), "R");
options.set_via_cellname_prefix ("VIACELL");
EXPECT_EQ (options.via_cellname_prefix (), "VIACELL");
options.set_produce_via_geometry (true);
EXPECT_EQ (options.produce_via_geometry (), true);
options.set_produce_via_geometry (false);
EXPECT_EQ (options.produce_via_geometry (), false);
options.set_via_geometry_suffix ("VIAG");
EXPECT_EQ (options.via_geometry_suffix (), "VIAG");
options.set_via_geometry_datatype (17);
EXPECT_EQ (options.via_geometry_datatype (), 17);
options.set_via_geometry_suffix_str ("VIAG, 2: VIAGM2, 1: VIAGM1");
EXPECT_EQ (options.via_geometry_suffix_str (), "VIAG,1:VIAGM1,2:VIAGM2");
EXPECT_EQ (options.via_geometry_suffix_per_mask (0), "VIAG");
EXPECT_EQ (options.via_geometry_suffix_per_mask (1), "VIAGM1");
EXPECT_EQ (options.via_geometry_suffix_per_mask (2), "VIAGM2");
EXPECT_EQ (options.via_geometry_suffix_per_mask (3), "VIAG");
options.set_via_geometry_suffix_per_mask (2, "AB");
EXPECT_EQ (options.via_geometry_suffix_per_mask (2), "AB");
EXPECT_EQ (options.max_mask_number (), (unsigned int) 2);
options.set_via_geometry_datatype_str ("17, 2:217, 1: 117");
EXPECT_EQ (options.via_geometry_datatype_str (), "17,1:117,2:217");
EXPECT_EQ (options.via_geometry_datatype_per_mask (0), 17);
EXPECT_EQ (options.via_geometry_datatype_per_mask (1), 117);
EXPECT_EQ (options.via_geometry_datatype_per_mask (2), 217);
EXPECT_EQ (options.via_geometry_datatype_per_mask (3), 17);
options.set_via_geometry_datatype_per_mask (2, 42);
EXPECT_EQ (options.via_geometry_datatype_per_mask (2), 42);
options.clear_via_geometry_suffixes_per_mask ();
EXPECT_EQ (options.via_geometry_suffix_str (), "VIAG");
options.clear_via_geometry_datatypes_per_mask ();
EXPECT_EQ (options.via_geometry_datatype_str (), "17");
options.set_produce_pins (true);
EXPECT_EQ (options.produce_pins (), true);
options.set_produce_pins (false);
EXPECT_EQ (options.produce_pins (), false);
options.set_pins_suffix ("PIN");
EXPECT_EQ (options.pins_suffix (), "PIN");
options.set_pins_datatype (42);
EXPECT_EQ (options.pins_datatype (), 42);
options.set_pins_suffix_str ("PIN, 2: PINM2, 1: PINM1");
EXPECT_EQ (options.pins_suffix_str (), "PIN,1:PINM1,2:PINM2");
EXPECT_EQ (options.pins_suffix_per_mask (0), "PIN");
EXPECT_EQ (options.pins_suffix_per_mask (1), "PINM1");
EXPECT_EQ (options.pins_suffix_per_mask (2), "PINM2");
EXPECT_EQ (options.pins_suffix_per_mask (3), "PIN");
options.set_pins_suffix_per_mask (2, "AB");
EXPECT_EQ (options.pins_suffix_per_mask (2), "AB");
options.set_pins_datatype_str ("42, 2:242, 1: 142");
EXPECT_EQ (options.pins_datatype_str (), "42,1:142,2:242");
EXPECT_EQ (options.pins_datatype_per_mask (0), 42);
EXPECT_EQ (options.pins_datatype_per_mask (1), 142);
EXPECT_EQ (options.pins_datatype_per_mask (2), 242);
EXPECT_EQ (options.pins_datatype_per_mask (3), 42);
options.set_pins_datatype_per_mask (2, 42);
EXPECT_EQ (options.pins_datatype_per_mask (2), 42);
options.clear_pins_suffixes_per_mask ();
EXPECT_EQ (options.pins_suffix_str (), "PIN");
options.clear_pins_datatypes_per_mask ();
EXPECT_EQ (options.pins_datatype_str (), "42");
options.set_produce_lef_pins (true);
EXPECT_EQ (options.produce_lef_pins (), true);
options.set_produce_lef_pins (false);
EXPECT_EQ (options.produce_lef_pins (), false);
options.set_lef_pins_suffix ("LEFPIN");
EXPECT_EQ (options.lef_pins_suffix (), "LEFPIN");
options.set_lef_pins_datatype (41);
EXPECT_EQ (options.lef_pins_datatype (), 41);
options.set_lef_pins_suffix_str ("LEFPIN, 2: LEFPINM2, 1: LEFPINM1");
EXPECT_EQ (options.lef_pins_suffix_str (), "LEFPIN,1:LEFPINM1,2:LEFPINM2");
EXPECT_EQ (options.lef_pins_suffix_per_mask (0), "LEFPIN");
EXPECT_EQ (options.lef_pins_suffix_per_mask (1), "LEFPINM1");
EXPECT_EQ (options.lef_pins_suffix_per_mask (2), "LEFPINM2");
EXPECT_EQ (options.lef_pins_suffix_per_mask (3), "LEFPIN");
options.set_lef_pins_suffix_per_mask (2, "AB");
EXPECT_EQ (options.lef_pins_suffix_per_mask (2), "AB");
options.set_lef_pins_datatype_str ("41, 2:241, 1: 141");
EXPECT_EQ (options.lef_pins_datatype_str (), "41,1:141,2:241");
EXPECT_EQ (options.lef_pins_datatype_per_mask (0), 41);
EXPECT_EQ (options.lef_pins_datatype_per_mask (1), 141);
EXPECT_EQ (options.lef_pins_datatype_per_mask (2), 241);
EXPECT_EQ (options.lef_pins_datatype_per_mask (3), 41);
options.set_lef_pins_datatype_per_mask (2, 41);
EXPECT_EQ (options.lef_pins_datatype_per_mask (2), 41);
options.clear_lef_pins_suffixes_per_mask ();
EXPECT_EQ (options.lef_pins_suffix_str (), "LEFPIN");
options.clear_lef_pins_datatypes_per_mask ();
EXPECT_EQ (options.lef_pins_datatype_str (), "41");
options.set_produce_obstructions (true);
EXPECT_EQ (options.produce_obstructions (), true);
options.set_produce_obstructions (false);
EXPECT_EQ (options.produce_obstructions (), false);
options.set_obstructions_suffix ("OBS");
EXPECT_EQ (options.obstructions_suffix (), "OBS");
options.set_obstructions_datatype (31);
EXPECT_EQ (options.obstructions_datatype (), 31);
options.set_produce_blockages (true);
EXPECT_EQ (options.produce_blockages (), true);
options.set_produce_blockages (false);
EXPECT_EQ (options.produce_blockages (), false);
options.set_blockages_suffix ("BLK");
EXPECT_EQ (options.blockages_suffix (), "BLK");
options.set_blockages_datatype (41);
EXPECT_EQ (options.blockages_datatype (), 41);
options.set_produce_labels (true);
EXPECT_EQ (options.produce_labels (), true);
options.set_produce_labels (false);
EXPECT_EQ (options.produce_labels (), false);
options.set_labels_suffix ("LBL");
EXPECT_EQ (options.labels_suffix (), "LBL");
options.set_labels_datatype (51);
EXPECT_EQ (options.labels_datatype (), 51);
options.set_produce_routing (true);
EXPECT_EQ (options.produce_routing (), true);
options.set_produce_routing (false);
EXPECT_EQ (options.produce_routing (), false);
options.set_routing_suffix ("ROUTING");
EXPECT_EQ (options.routing_suffix (), "ROUTING");
options.set_routing_datatype (40);
EXPECT_EQ (options.routing_datatype (), 40);
options.set_routing_suffix_str ("ROUTING, 2: ROUTINGM2, 1: ROUTINGM1");
EXPECT_EQ (options.routing_suffix_str (), "ROUTING,1:ROUTINGM1,2:ROUTINGM2");
EXPECT_EQ (options.routing_suffix_per_mask (0), "ROUTING");
EXPECT_EQ (options.routing_suffix_per_mask (1), "ROUTINGM1");
EXPECT_EQ (options.routing_suffix_per_mask (2), "ROUTINGM2");
EXPECT_EQ (options.routing_suffix_per_mask (3), "ROUTING");
options.set_routing_suffix_per_mask (2, "AB");
EXPECT_EQ (options.routing_suffix_per_mask (2), "AB");
options.set_routing_datatype_str ("40, 2:240, 1: 140");
EXPECT_EQ (options.routing_datatype_str (), "40,1:140,2:240");
EXPECT_EQ (options.routing_datatype_per_mask (0), 40);
EXPECT_EQ (options.routing_datatype_per_mask (1), 140);
EXPECT_EQ (options.routing_datatype_per_mask (2), 240);
EXPECT_EQ (options.routing_datatype_per_mask (3), 40);
options.set_routing_datatype_per_mask (2, 40);
EXPECT_EQ (options.routing_datatype_per_mask (2), 40);
options.clear_routing_suffixes_per_mask ();
EXPECT_EQ (options.routing_suffix_str (), "ROUTING");
options.clear_routing_datatypes_per_mask ();
EXPECT_EQ (options.routing_datatype_str (), "40");
options.set_produce_special_routing (true);
EXPECT_EQ (options.produce_special_routing (), true);
options.set_produce_special_routing (false);
EXPECT_EQ (options.produce_special_routing (), false);
options.set_special_routing_suffix ("SPECIALROUTING");
EXPECT_EQ (options.special_routing_suffix (), "SPECIALROUTING");
options.set_special_routing_datatype (44);
EXPECT_EQ (options.special_routing_datatype (), 44);
options.set_special_routing_suffix_str ("SPECIALROUTING, 2: SPECIALROUTINGM2, 1: SPECIALROUTINGM1");
EXPECT_EQ (options.special_routing_suffix_str (), "SPECIALROUTING,1:SPECIALROUTINGM1,2:SPECIALROUTINGM2");
EXPECT_EQ (options.special_routing_suffix_per_mask (0), "SPECIALROUTING");
EXPECT_EQ (options.special_routing_suffix_per_mask (1), "SPECIALROUTINGM1");
EXPECT_EQ (options.special_routing_suffix_per_mask (2), "SPECIALROUTINGM2");
EXPECT_EQ (options.special_routing_suffix_per_mask (3), "SPECIALROUTING");
options.set_special_routing_suffix_per_mask (2, "AB");
EXPECT_EQ (options.special_routing_suffix_per_mask (2), "AB");
options.set_special_routing_datatype_str ("44, 2:244, 1: 144");
EXPECT_EQ (options.special_routing_datatype_str (), "44,1:144,2:244");
EXPECT_EQ (options.special_routing_datatype_per_mask (0), 44);
EXPECT_EQ (options.special_routing_datatype_per_mask (1), 144);
EXPECT_EQ (options.special_routing_datatype_per_mask (2), 244);
EXPECT_EQ (options.special_routing_datatype_per_mask (3), 44);
options.set_special_routing_datatype_per_mask (2, 44);
EXPECT_EQ (options.special_routing_datatype_per_mask (2), 44);
options.clear_special_routing_suffixes_per_mask ();
EXPECT_EQ (options.special_routing_suffix_str (), "SPECIALROUTING");
options.clear_special_routing_datatypes_per_mask ();
EXPECT_EQ (options.special_routing_datatype_str (), "44");
EXPECT_EQ (options.begin_lef_files () == options.end_lef_files (), true);
options.push_lef_file ("ABC.lef");
EXPECT_EQ (options.begin_lef_files () == options.end_lef_files (), false);
EXPECT_EQ (options.lef_files ().size (), size_t (1));
EXPECT_EQ (*options.begin_lef_files (), "ABC.lef");
std::vector<std::string> lf = options.lef_files ();
options.clear_lef_files ();
EXPECT_EQ (options.begin_lef_files () == options.end_lef_files (), true);
EXPECT_EQ (options.lef_files ().size (), size_t (0));
options.set_lef_files (lf);
EXPECT_EQ (options.lef_files ().size (), size_t (1));
EXPECT_EQ (*options.begin_lef_files (), "ABC.lef");
EXPECT_EQ (options.read_lef_with_def (), true);
options.set_read_lef_with_def (false);
EXPECT_EQ (options.read_lef_with_def (), false);
options.set_map_file ("ABC.map");
EXPECT_EQ (options.map_file (), "ABC.map");
options.set_macro_resolution_mode (2);
EXPECT_EQ (options.macro_resolution_mode (), (unsigned int) 2);
}

View File

@ -6,7 +6,8 @@ TARGET = lefdef_tests
include($$PWD/../../../../lib_ut.pri)
SOURCES = \
dbLEFDEFImport.cc
dbLEFDEFImportTests.cc \
dbLEFDEFReaderOptionsTests.cc
INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common

View File

@ -111,7 +111,7 @@ MAGReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
m_tech.clear ();
{
tl::SelfTimer timer (tl::verbosity () >= 21, "Reading MAGIC file tree");
tl::SelfTimer timer (tl::verbosity () >= 11, "Reading MAGIC file tree");
// This is the seed
do_read (layout, top_cell, m_stream);

View File

@ -689,8 +689,6 @@ static const char magic_bytes[] = { "%SEMI-OASIS\015\012" };
void
OASISReader::do_read (db::Layout &layout)
{
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("File read: ")) + m_stream.source ());
unsigned char r;
char *mb;

View File

@ -2754,7 +2754,7 @@ OASISWriter::write (const db::Path &path, db::properties_id_type prop_id, const
if (hw * 2 != w) {
std::string msg = tl::to_string (tr ("Paths with odd width cannot be written to OASIS files (cell ")) + mp_layout->cell_name (mp_cell->cell_index ()) + tl::to_string (tr (", position ")) + tl::to_string (start.x ()) + ", " + tl::to_string (start.y ()) + " DBU)";
if (m_options.permissive) {
tl::warn << msg << " - " << tl::to_string (tr ("path diameter is rounded"));
tl::warn << msg << " - " << tl::sprintf (tl::to_string (tr ("path width is rounded from %d to %d DBU")), w, hw * 2);
} else {
throw tl::Exception (msg);
}

View File

@ -502,7 +502,7 @@ CommandLineOptions::parse (int argc, char *argv[])
ex.read_word (n, "_-");
std::map<std::string, ArgBase *>::const_iterator a = arg_by_long_option.find (n);
if (a == arg_by_long_option.end ()) {
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unknown command line option --%1 (use -h for help)")), n));
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unknown command line option --%s (use -h for help)")), n));
}
arg = a->second;
@ -512,14 +512,14 @@ CommandLineOptions::parse (int argc, char *argv[])
ex.read_word (n);
std::map<std::string, ArgBase *>::const_iterator a = arg_by_short_option.find (n);
if (a == arg_by_short_option.end ()) {
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unknown command line option --%1 (use -h for help)")), n));
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unknown command line option -%s (use -h for help)")), n));
}
arg = a->second;
} else {
if (next_plain_arg == plain_args.end ()) {
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unknown command line component %1 - no further plain argument expected (use -h for help)")), arg_as_utf8));
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Unknown command line component %s - no further plain argument expected (use -h for help)")), arg_as_utf8));
}
arg = *next_plain_arg;
@ -558,7 +558,10 @@ CommandLineOptions::parse (int argc, char *argv[])
if (ex.test ("=")) {
arg->take_value (ex);
} else {
arg->mark_present (arg->option ().inverted);
arg->mark_present ();
}
if (arg->option ().inverted) {
arg->invert_present ();
}
}

View File

@ -137,7 +137,15 @@ public:
/**
* @brief Marks an option to be present (for boolean options)
*/
virtual void mark_present (bool)
virtual void mark_present ()
{
// .. nothing yet ..
}
/**
* @brief Inverts the presence of an option (for boolean options)
*/
virtual void invert_present ()
{
// .. nothing yet ..
}
@ -231,29 +239,30 @@ inline void extract (tl::Extractor &ex, std::vector<T> &t, bool repeated_hint, b
* @brief A helper to mark "presence"
*/
template <class T>
inline void mark_presence (T &, bool)
inline void mark_presence (T &)
{
// .. the default implementation does nothing ..
}
inline void mark_presence (bool &t, bool invert)
inline void mark_presence (bool &t)
{
t = !invert;
t = true;
}
template <class C, class T>
inline void mark_presence_setter (C *, void (C::*) (T), bool)
/**
* @brief A helper to invert "presence"
*/
template <class T>
inline void invert_presence (T &)
{
// .. the default implementation does nothing ..
}
template <class C>
inline void mark_presence_setter (C *c, void (C::*ptr) (bool), bool invert)
inline void invert_presence (bool &t)
{
(c->*ptr) (!invert);
t = !t;
}
/**
* @brief A helper template to extract the actual type from (T) or (const T &)
*/
@ -303,9 +312,14 @@ public:
extract (ex, *mp_value, option ().repeated);
}
virtual void mark_present (bool inverted)
virtual void mark_present ()
{
mark_presence (*mp_value, inverted);
mark_presence (*mp_value);
}
virtual void invert_present ()
{
invert_presence (*mp_value);
}
virtual ArgBase *clone () const
@ -330,23 +344,30 @@ class arg_method_setter
: public ArgBase
{
public:
typedef typename type_without_const_ref<T>::inner_type inner_type;
arg_method_setter (const std::string &option, C *object, void (C::*setter)(T), const std::string &brief_doc, const std::string &long_doc)
: ArgBase (option, brief_doc, long_doc), mp_object (object), mp_setter (setter)
: ArgBase (option, brief_doc, long_doc), m_value (), mp_object (object), mp_setter (setter)
{
// .. nothing yet ..
}
virtual void take_value (tl::Extractor &ex)
{
typedef typename type_without_const_ref<T>::inner_type inner_type;
inner_type t = inner_type ();
extract (ex, t, option ().repeated);
(mp_object->*mp_setter) (t);
extract (ex, m_value, option ().repeated);
(mp_object->*mp_setter) (m_value);
}
virtual void mark_present (bool inverted)
virtual void mark_present ()
{
mark_presence_setter (mp_object, mp_setter, inverted);
mark_presence (m_value);
(mp_object->*mp_setter) (m_value);
}
virtual void invert_present ()
{
invert_presence (m_value);
(mp_object->*mp_setter) (m_value);
}
virtual ArgBase *clone () const
@ -360,6 +381,7 @@ public:
}
private:
inner_type m_value;
C *mp_object;
void (C::*mp_setter)(T);
};

View File

@ -1822,12 +1822,12 @@ make_member (void (Parent::*setter) (const Value &), const std::string &name)
* @brief Utility: create a XMLMember object
*/
template <class Value, class Parent>
XMLMember<Value, Parent, XMLMemberAccReadAdaptor <Value, Parent>, XMLMemberDummyWriteAdaptor <Value, Parent>, XMLStdConverter <Value> >
XMLMember<Value, Parent, XMLMemberDummyReadAdaptor <Value, Parent>, XMLMemberAccWriteAdaptor <Value, Parent>, XMLStdConverter <Value> >
make_member (void (Parent::*setter) (Value), const std::string &name)
{
return XMLMember<Value, Parent, XMLMemberAccReadAdaptor <Value, Parent>, XMLMemberDummyWriteAdaptor <Value, Parent>, XMLStdConverter <Value> > (
XMLMemberAccReadAdaptor <Value, Parent> (setter),
XMLMemberDummyWriteAdaptor <Value, Parent> (), name);
return XMLMember<Value, Parent, XMLMemberDummyReadAdaptor <Value, Parent>, XMLMemberAccWriteAdaptor <Value, Parent>, XMLStdConverter <Value> > (
XMLMemberDummyReadAdaptor <Value, Parent> (),
XMLMemberAccWriteAdaptor <Value, Parent> (setter), name);
}
/**

View File

@ -75,6 +75,26 @@ TEST(1)
EXPECT_EQ (b, 0);
EXPECT_EQ (c, false);
b = 0;
c = true;
{
const char *argv[] = { "x", "u", "-cc=false" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "u");
EXPECT_EQ (b, 0);
EXPECT_EQ (c, true);
b = 0;
c = true;
{
const char *argv[] = { "x", "u", "-cc=true" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);
}
EXPECT_EQ (a, "u");
EXPECT_EQ (b, 0);
EXPECT_EQ (c, false);
{
const char *argv[] = { "x", "u", "-c", "-cc" };
cmd.parse (sizeof (argv) / sizeof (argv[0]), (char **) argv);

View File

@ -193,7 +193,7 @@ const char *ANSI_GREEN = "\033[32m";
const char *ANSI_RESET = "\033[0m";
TestConsole::TestConsole (FILE *file)
: m_file (file), m_col (0), m_max_col (250), m_columns (50), m_rows (0), m_file_is_tty (false)
: m_file (file), m_col (0), m_max_col (400), m_columns (50), m_rows (0), m_file_is_tty (false)
{
ms_instance = this;

BIN
testdata/lefdef/doxy_vias/au.oas.gz vendored Normal file

Binary file not shown.

28
testdata/lefdef/doxy_vias/test.def vendored Normal file
View File

@ -0,0 +1,28 @@
VERSION 5.8 ;
DIVIDERCHAR "/" ;
BUSBITCHARS "[]" ;
DESIGN chip_top ;
UNITS DISTANCE MICRONS 1000 ;
DIEAREA ( 30000 3000 ) ( 10000000 4000 ) ;
VIAS 1 ;
- VIA1_dummy
+ RECT M1 ( -200 -140 ) ( 200 140 )
+ RECT VIA1 ( -100 -100 ) ( 100 100 )
+ RECT M2 ( -300 -120 ) ( 300 120 ) ;
END VIAS
SPECIALNETS 1 ;
- dummy
+ ROUTED M1 150 + SHAPE IOWIRE ( 40000 3600 ) VIA1_dummy DO 16000 BY 1 STEP 700 0
;
END SPECIALNETS
SCANCHAINS 77 ;
- chain1_clock1
+ PARTITION clock1
+ START block1/bsr_reg_0 Q
+ FLOATING
block1/pgm_cgm_en_reg_reg ( IN SD ) ( OUT QZ )
block1/start_reset_dd_reg ( IN SD ) ( OUT QZ )
+ STOP block1/start_reset_d_reg SD ;
END SCANCHAINS
END DESIGN

BIN
testdata/lefdef/foreigncell/au.oas.gz vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
testdata/lefdef/foreigncell/foreign.gds vendored Normal file

Binary file not shown.

17
testdata/lefdef/foreigncell/in.def vendored Normal file
View File

@ -0,0 +1,17 @@
VERSION 5.8 ;
DIVIDERCHAR "/" ;
BUSBITCHARS "[]" ;
DESIGN foreigncells ;
UNITS DISTANCE MICRONS 1000 ;
DIEAREA ( 0 0 ) ( 1000 2000 ) ;
COMPONENTS 3 ;
- macro1 macro1 + PLACED ( 0 0 ) N ;
- macro2 macro2 + PLACED ( 0 500 ) E ;
- macro3 macro3 + PLACED ( 0 1000 ) N ;
END COMPONENTS
END DESIGN

21
testdata/lefdef/foreigncell/in.lef vendored Normal file
View File

@ -0,0 +1,21 @@
MACRO macro1
CLASS CORE ;
FOREIGN foreign1 0.13 0.5 W ;
ORIGIN 0.035 0.235 ;
SIZE 0.07 BY 0.47 ;
END macro1
MACRO macro2
CLASS CORE ;
FOREIGN foreign2 -0.15 0.25 ;
ORIGIN 0.235 0.035 ;
SIZE 0.47 BY 0.07 ;
END macro2
MACRO macro3
CLASS CORE ;
FOREIGN macro3 -1.0 1.0 ;
ORIGIN 0.0 0.0 ;
SIZE 1.0 BY 0.4 ;
END macro3

44
testdata/lefdef/foreigncell/in2.lef vendored Normal file
View File

@ -0,0 +1,44 @@
MACRO macro1
CLASS CORE ;
ORIGIN 0.035 0.235 ;
SIZE 0.07 BY 0.47 ;
PIN Z
PORT
LAYER M1 ;
RECT -0.02 0 0.02 0.2 ;
RECT -0.03 -0.2 0.01 -0.1 ;
VIA 0.0 0.2 square ;
VIA 0.01 -0.2 square ;
END
END Z
END macro1
MACRO macro2
CLASS CORE ;
FOREIGN foreign2 -0.15 0.25 ;
ORIGIN 0.235 0.035 ;
SIZE 0.47 BY 0.07 ;
PIN Z
PORT
LAYER M1 ;
RECT 0 -0.02 -0.2 0.02 ;
RECT 0.2 -0.03 0.1 0.01 ;
VIA -0.2 0.0 square ;
VIA 0.2 0.01 square ;
END
END Z
END macro2
MACRO macro3
CLASS CORE ;
FOREIGN macro3 -1.0 1.0 ;
ORIGIN 0.0 0.0 ;
SIZE 1.0 BY 1.0 ;
PIN Z
PORT
LAYER M1 ;
RECT 0.2 0.2 0.3 0.5 ;
END
END Z
END macro3

36
testdata/lefdef/foreigncell/in_tech.lef vendored Normal file
View File

@ -0,0 +1,36 @@
LAYER OD
TYPE IMPLANT ;
END OD
LAYER VTS_N
TYPE IMPLANT ;
END VTS_N
LAYER VTS_P
TYPE IMPLANT ;
END VTS_P
LAYER M0OD
TYPE IMPLANT ;
END M0OD
LAYER M0PO
TYPE MASTERSLICE ;
END M0PO
LAYER VIA0
TYPE CUT ;
END VIA0
LAYER M1
TYPE MASTERSLICE ;
END M1
LAYER VIA1
TYPE CUT ;
END VIA1
LAYER M2
TYPE MASTERSLICE ;
END M2
VIA square
LAYER M0PO ;
RECT -0.006 -0.006 0.006 0.006 ;
LAYER VIA0 ;
RECT -0.006 -0.006 0.006 0.006 ;
LAYER M1 ;
RECT -0.006 -0.006 0.006 0.006 ;
END square

View File

@ -1,6 +1,5 @@
MACRO dummy
CLASS CORE ;
FOREIGN dummy 0.000 0.000 ;
ORIGIN 0.000 0.000 ;
SIZE 0.384 BY 0.480 ;
SYMMETRY X Y ;

Binary file not shown.

View File

@ -0,0 +1,34 @@
VERSION 5.7 ;
DIVIDERCHAR "/" ;
BUSBITCHARS "[]" ;
DESIGN test ;
UNITS DISTANCE MICRONS 2000 ;
DIEAREA ( 0 0 ) ( 37520 7840 ) ;
PINS 12 ;
- VDD + NET VDD + SPECIAL + DIRECTION INOUT + USE POWER
+ LAYER M2 ( -320 0 ) ( 320 37520 )
+ FIXED ( 37520 3920 ) W ;
- VSS + NET VSS + SPECIAL + DIRECTION INOUT + USE GROUND
+ PORT
+ LAYER M2 ( -18760 0 ) ( 18760 640 )
+ FIXED ( 18760 -320 ) N
+ PORT
+ LAYER M2 ( -18760 0 ) ( 18760 640 )
+ FIXED ( 18760 8160 ) S
;
END PINS
SPECIALNETS 4 ;
- VSS ( * VSS )
+ ROUTED M2 640 + SHAPE FOLLOWPIN ( 0 0 ) ( 37520 * )
NEW M2 640 + SHAPE FOLLOWPIN ( 0 7840 ) ( 37520 * )
+ USE GROUND
;
- VDD ( * VDD )
+ ROUTED M2 640 + SHAPE FOLLOWPIN ( 0 3920 ) ( 37520 * )
+ USE POWER
;
END SPECIALNETS
END DESIGN

View File

@ -0,0 +1,67 @@
VERSION 5.7 ;
BUSBITCHARS "[]" ;
DIVIDERCHAR "/" ;
UNITS
DATABASE MICRONS 1000 ;
END UNITS
MANUFACTURINGGRID 0.002 ;
USEMINSPACING OBS OFF ;
END LIBRARY
LAYER overlap
TYPE OVERLAP ;
END overlap
LAYER contact
TYPE CUT ;
END contact
END LIBRARY
LAYER metal1
TYPE ROUTING ;
DIRECTION HORIZONTAL ;
END metal1
LAYER via1
TYPE CUT ;
END via1
LAYER metal2
TYPE ROUTING ;
DIRECTION VERTICAL ;
END metal2
LAYER via2
TYPE CUT ;
END via2
LAYER metal3
TYPE ROUTING ;
DIRECTION HORIZONTAL ;
END metal3
LAYER via3
TYPE CUT ;
END via3
LAYER metal4
TYPE ROUTING ;
DIRECTION VERTICAL ;
END metal4
END LIBRARY
LAYER via4
TYPE CUT ;
END via4
LAYER metal5
TYPE ROUTING ;
DIRECTION HORIZONTAL ;
END metal5
END LIBRARY

Binary file not shown.

Binary file not shown.

15
testdata/lefdef/lefpins/in.def vendored Normal file
View File

@ -0,0 +1,15 @@
VERSION 5.8 ;
DIVIDERCHAR "/" ;
BUSBITCHARS "[]" ;
DESIGN foreigncells ;
UNITS DISTANCE MICRONS 1000 ;
DIEAREA ( 0 0 ) ( 1000 2000 ) ;
COMPONENTS 3 ;
- macro1 macro1 + PLACED ( 0 0 ) N ;
END COMPONENTS
END DESIGN

15
testdata/lefdef/lefpins/in.lef vendored Normal file
View File

@ -0,0 +1,15 @@
MACRO macro1
CLASS CORE ;
ORIGIN 0.000 0.000 ;
SIZE 0.384 BY 0.480 ;
PIN Z
PORT
LAYER M1 ;
RECT 0.306 0.357 0.318 0.403 ;
RECT 0.318 0.115 0.352 0.403 ;
VIA 0.336 0.167 square ;
VIA 0.336 0.351 square ;
END
END Z
END macro1

36
testdata/lefdef/lefpins/in_tech.lef vendored Normal file
View File

@ -0,0 +1,36 @@
LAYER OD
TYPE IMPLANT ;
END OD
LAYER VTS_N
TYPE IMPLANT ;
END VTS_N
LAYER VTS_P
TYPE IMPLANT ;
END VTS_P
LAYER M0OD
TYPE IMPLANT ;
END M0OD
LAYER M0PO
TYPE MASTERSLICE ;
END M0PO
LAYER VIA0
TYPE CUT ;
END VIA0
LAYER M1
TYPE MASTERSLICE ;
END M1
LAYER VIA1
TYPE CUT ;
END VIA1
LAYER M2
TYPE MASTERSLICE ;
END M2
VIA square
LAYER M0PO ;
RECT -0.006 -0.006 0.006 0.006 ;
LAYER VIA0 ;
RECT -0.006 -0.006 0.006 0.006 ;
LAYER M1 ;
RECT -0.006 -0.006 0.006 0.006 ;
END square

BIN
testdata/lefdef/mapfile/au.oas.gz vendored Normal file

Binary file not shown.

32
testdata/lefdef/mapfile/in.def vendored Normal file
View File

@ -0,0 +1,32 @@
VERSION 5.8 ;
DIVIDERCHAR "/" ;
BUSBITCHARS "[]" ;
DESIGN mapfile ;
UNITS DISTANCE MICRONS 1000 ;
DIEAREA ( 0 0 ) ( 1000 2000 ) ;
COMPONENTS 3 ;
- macro1 macro1 + PLACED ( 0 0 ) N ;
END COMPONENTS
SPECIALNETS 1 ;
- VDD ( * VDD )
+ ROUTED M1 50 + SHAPE STRIPE ( 500 0 ) ( 500 500 25 ) square ( 0 500 )
+ USE POWER ;
END SPECIALNETS
PINS 1 ;
- VDD + NET VDD + SPECIAL + DIRECTION INOUT + USE POWER
+ LAYER M1 ( 0 0 ) ( 50 70 )
;
END PINS
NETS 1 ;
- TOP
+ ROUTED M1 ( 100 700 ) ( 500 * ) ;
END NETS
END DESIGN

19
testdata/lefdef/mapfile/in.lef vendored Normal file
View File

@ -0,0 +1,19 @@
MACRO macro1
CLASS CORE ;
ORIGIN 0.035 0.235 ;
SIZE 0.07 BY 0.47 ;
PIN Z
PORT
LAYER M1 ;
RECT -0.02 0 0.02 0.2 ;
RECT -0.03 -0.2 0.01 -0.1 ;
VIA 0.0 0.2 square ;
VIA 0.01 -0.2 square ;
END
END Z
OBS
LAYER M1 ;
RECT -0.035 -0.235 0.035 0.235 ;
END
END macro1

27
testdata/lefdef/mapfile/in_tech.lef vendored Normal file
View File

@ -0,0 +1,27 @@
LAYER M0PO
TYPE MASTERSLICE ;
WIDTH 0.02 ;
END M0PO
LAYER VIA0
TYPE CUT ;
END VIA0
LAYER M1
TYPE MASTERSLICE ;
WIDTH 0.025 ;
END M1
LAYER VIA1
TYPE CUT ;
END VIA1
LAYER M2
TYPE MASTERSLICE ;
WIDTH 0.03 ;
END M2
VIA square
LAYER M0PO ;
RECT -0.006 -0.006 0.006 0.006 ;
LAYER VIA0 ;
RECT -0.006 -0.006 0.006 0.006 ;
LAYER M1 ;
RECT -0.006 -0.006 0.006 0.006 ;
END square

18
testdata/lefdef/mapfile/test.map vendored Normal file
View File

@ -0,0 +1,18 @@
DIEAREA ALL 100 0
M0PO LEFPIN,LEFOBS,PIN,NET,SPNET,VIA 10 0
VIA0 LEFPIN,LEFOBS,VIA,PIN,NET,SPNET 11 0
M1 LEFPIN 12 0
M1 LEFOBS 12 1
M1 PIN 12 2
M1 NET 12 3
M1 SPNET 12 4
M1 VIA 12 5
M1 FILLOPC 12 100
M1 FILLOPC:MASK:1 12 101
M1 FILLOPC:MASK:2 12 102
M1 BLOCKAGEFILL 12 150
M1 BLOCKAGE 12 151
M1 FILL 12 152
NAME M1/PIN 12 10
VIA1 LEFPIN,LEFOBS,VIA,PIN,NET,SPNET 13 0
M2 LEFPIN,LEFOBS,PIN,NET,SPNET,VIA 14 0

BIN
testdata/lefdef/masks-1/au.oas.gz vendored Normal file

Binary file not shown.

BIN
testdata/lefdef/masks-1/au_map.oas.gz vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,32 @@
LAYER M0PO
TYPE MASTERSLICE ;
WIDTH 0.02 ;
MASKS 2 ;
END M0PO
LAYER VIA0
TYPE CUT ;
MASKS 2 ;
END VIA0
LAYER M1
TYPE MASTERSLICE ;
WIDTH 0.024 ;
MASKS 2 ;
END M1
LAYER VIA1
TYPE CUT ;
MASKS 2 ;
END VIA1
LAYER M2
TYPE MASTERSLICE ;
WIDTH 0.03 ;
MASKS 2 ;
END M2
VIA square
LAYER M0PO ;
RECT -0.08 -0.08 0.08 0.08 ;
LAYER VIA0 ;
RECT -0.08 -0.08 0.08 0.08 ;
LAYER M1 ;
RECT -0.08 -0.08 0.08 0.08 ;
END square

32
testdata/lefdef/masks-1/in.def vendored Normal file
View File

@ -0,0 +1,32 @@
VERSION 5.8 ;
DIVIDERCHAR "/" ;
BUSBITCHARS "[]" ;
DESIGN mapfile ;
UNITS DISTANCE MICRONS 1000 ;
DIEAREA ( 0 0 ) ( 1000 3000 ) ;
SPECIALNETS 1 ;
- VDD ( * VDD )
+ ROUTED + MASK 1 + RECT M0PO ( 0 1000 ) ( 500 1500 )
+ ROUTED + MASK 2 + POLYGON M1 ( 0 1600 ) ( 0 2100 ) ( 500 2100 ) ( 500 1600 )
+ ROUTED M1 50 + SHAPE STRIPE ( 500 0 ) MASK 1 ( 500 500 30 ) MASK 112 square ( 0 500 )
+ USE POWER ;
END SPECIALNETS
PINS 1 ;
- VDD + NET VDD + SPECIAL + DIRECTION INOUT + USE POWER
+ LAYER M1 MASK 1 ( 0 0 ) ( 50 70 )
+ LAYER M0PO ( 0 100 ) ( 50 170 )
+ LAYER M0PO MASK 2 ( 100 100 ) ( 150 170 )
;
END PINS
NETS 1 ;
- TOP
+ ROUTED M1 ( 100 700 ) MASK 1 ( 500 * ) MASK 2 ( 1000 * ) MASK 221 square ( * 800 ) ;
END NETS
END DESIGN

31
testdata/lefdef/masks-1/in.map vendored Normal file
View File

@ -0,0 +1,31 @@
DIEAREA ALL 4 0
NAME M0PO 1 1
M0PO PIN 1 2
M0PO NET:MASK:1 1 100
M0PO NET:MASK:2 1 200
M0PO SPNET:MASK:1 1 101
M0PO SPNET:MASK:2 1 201
M0PO VIA:MASK:1 1 102
M0PO VIA:MASK:2 1 202
M0PO PIN:MASK:1 1 110
M0PO PIN:MASK:2 1 210
NAME VIA0 2 1
VIA0 PIN 2 2
VIA0 NET:MASK:1 2 100
VIA0 NET:MASK:2 2 200
VIA0 SPNET:MASK:1 2 101
VIA0 SPNET:MASK:2 2 201
VIA0 VIA:MASK:1 2 102
VIA0 VIA:MASK:2 2 202
VIA0 PIN:MASK:1 2 110
VIA0 PIN:MASK:2 2 210
NAME M1 3 1
M1 PIN 3 2
M1 NET:MASK:1 3 100
M1 NET:MASK:2 3 200
M1 SPNET:MASK:1 3 101
M1 SPNET:MASK:2 3 201
M1 VIA:MASK:1 3 102
M1 VIA:MASK:2 3 202
M1 PIN:MASK:1 3 110
M1 PIN:MASK:2 3 210

32
testdata/lefdef/masks-1/in_tech.lef vendored Normal file
View File

@ -0,0 +1,32 @@
LAYER M0PO
TYPE MASTERSLICE ;
WIDTH 0.02 ;
MASK 2 ;
END M0PO
LAYER VIA0
TYPE CUT ;
MASK 2 ;
END VIA0
LAYER M1
TYPE MASTERSLICE ;
WIDTH 0.024 ;
MASK 2 ;
END M1
LAYER VIA1
TYPE CUT ;
MASK 2 ;
END VIA1
LAYER M2
TYPE MASTERSLICE ;
WIDTH 0.03 ;
MASK 2 ;
END M2
VIA square
LAYER M0PO ;
RECT -0.06 -0.06 0.06 0.06 ;
LAYER VIA0 ;
RECT -0.06 -0.06 0.06 0.06 ;
LAYER M1 ;
RECT -0.06 -0.06 0.06 0.06 ;
END square

BIN
testdata/lefdef/masks-2/au.oas.gz vendored Normal file

Binary file not shown.

44
testdata/lefdef/masks-2/in.def vendored Normal file
View File

@ -0,0 +1,44 @@
VERSION 5.8 ;
DIVIDERCHAR "/" ;
BUSBITCHARS "[]" ;
DESIGN mapfile ;
UNITS DISTANCE MICRONS 1000 ;
DIEAREA ( 0 0 ) ( 3000 3000 ) ;
COMPONENTMASKSHIFT M2 M1 M0PO ;
COMPONENTS 3 ;
- comp1 mask_macro
+ PLACED ( 0 0 ) N ;
- comp1 mask_macro
+ MASKSHIFT 2
+ PLACED ( 1000 0 ) N ;
- comp1 mask_macro
+ MASKSHIFT 221
+ PLACED ( 2000 0 ) N ;
- comp1 nomask_macro
+ PLACED ( 0 1000 ) N ;
- comp1 nomask_macro
+ MASKSHIFT 2
+ PLACED ( 1000 1000 ) N ;
- comp1 nomask_macro
+ MASKSHIFT 221
+ PLACED ( 2000 1000 ) N ;
- comp1 fixedmask_macro
+ PLACED ( 0 2000 ) N ;
- comp1 fixedmask_macro
+ MASKSHIFT 2
+ PLACED ( 1000 2000 ) N ;
- comp1 fixedmask_macro
+ MASKSHIFT 221
+ PLACED ( 2000 2000 ) N ;
END COMPONENTS ;
END DESIGN

56
testdata/lefdef/masks-2/in.lef vendored Normal file
View File

@ -0,0 +1,56 @@
MACRO nomask_macro
CLASS CORE ;
ORIGIN 0.3 0.3 ;
SIZE 0.6 BY 0.6 ;
PIN Z
PORT
LAYER M0PO ;
RECT -0.07 -0.03 0.07 0.03 ;
LAYER M1 ;
RECT 0.07 -0.03 0.13 0.03 ;
LAYER M2 ;
RECT -0.13 -0.03 -0.07 0.03 ;
VIA 0.0 0.2 square_nomask ;
VIA 0.0 -0.2 square_nomask ;
END
END Z
END nomask_macro
MACRO mask_macro
CLASS CORE ;
ORIGIN 0.3 0.3 ;
SIZE 0.6 BY 0.6 ;
PIN Z
PORT
LAYER M0PO ;
RECT MASK 2 -0.07 -0.03 0.07 0.03 ;
LAYER M1 ;
RECT MASK 2 0.07 -0.03 0.13 0.03 ;
LAYER M2 ;
RECT MASK 1 -0.13 -0.03 -0.07 0.03 ;
VIA MASK 200 0.0 0.2 square ;
VIA 0.0 -0.2 square ;
END
END Z
END mask_macro
MACRO fixedmask_macro
CLASS CORE ;
FIXEDMASK ;
ORIGIN 0.3 0.3 ;
SIZE 0.6 BY 0.6 ;
PIN Z
PORT
LAYER M0PO ;
RECT MASK 2 -0.07 -0.03 0.07 0.03 ;
LAYER M1 ;
RECT MASK 2 0.07 -0.03 0.13 0.03 ;
LAYER M2 ;
RECT MASK 1 -0.13 -0.03 -0.07 0.03 ;
VIA MASK 200 0.0 0.2 square ;
VIA 0.0 -0.2 square ;
END
END Z
END fixedmask_macro

56
testdata/lefdef/masks-2/in.map vendored Normal file
View File

@ -0,0 +1,56 @@
DIEAREA ALL 4 0
NAME M0PO 1 1
M0PO LEFPIN,PIN 1 2
M0PO VIA 1 3
M0PO NET:MASK:1 1 100
M0PO NET:MASK:2 1 200
M0PO SPNET:MASK:1 1 101
M0PO SPNET:MASK:2 1 201
M0PO VIA:MASK:1 1 102
M0PO VIA:MASK:2 1 202
M0PO LEFPIN,PIN:MASK:1 1 110
M0PO LEFPIN,PIN:MASK:2 1 210
NAME VIA0 2 1
VIA0 LEFPIN,PIN 2 2
VIA0 VIA 2 3
VIA0 NET:MASK:1 2 100
VIA0 NET:MASK:2 2 200
VIA0 SPNET:MASK:1 2 101
VIA0 SPNET:MASK:2 2 201
VIA0 VIA:MASK:1 2 102
VIA0 VIA:MASK:2 2 202
VIA0 LEFPIN,PIN:MASK:1 2 110
VIA0 LEFPIN,PIN:MASK:2 2 210
NAME M1 3 1
M1 PIN,LEFPIN 3 2
M1 VIA 3 3
M1 NET:MASK:1 3 100
M1 NET:MASK:2 3 200
M1 SPNET:MASK:1 3 101
M1 SPNET:MASK:2 3 201
M1 VIA:MASK:1 3 102
M1 VIA:MASK:2 3 202
M1 PIN,LEFPIN:MASK:1 3 110
M1 PIN,LEFPIN:MASK:2 3 210
NAME VIA1 4 1
VIA1 PIN,LEFPIN 4 2
VIA1 VIA 4 3
VIA1 NET:MASK:1 4 100
VIA1 NET:MASK:2 4 200
VIA1 SPNET:MASK:1 4 101
VIA1 SPNET:MASK:2 4 201
VIA1 VIA:MASK:1 4 102
VIA1 VIA:MASK:2 4 202
VIA1 PIN,LEFPIN:MASK:1 4 110
VIA1 PIN,LEFPIN:MASK:2 4 210
NAME M2 5 1
M2 PIN,LEFPIN 5 2
M2 VIA 5 3
M2 NET:MASK:1 5 100
M2 NET:MASK:2 5 200
M2 SPNET:MASK:1 5 101
M2 SPNET:MASK:2 5 201
M2 VIA:MASK:1 5 102
M2 VIA:MASK:2 5 202
M2 PIN,LEFPIN:MASK:1 5 110
M2 PIN,LEFPIN:MASK:2 5 210

41
testdata/lefdef/masks-2/in_tech.lef vendored Normal file
View File

@ -0,0 +1,41 @@
LAYER M0PO
TYPE MASTERSLICE ;
WIDTH 0.02 ;
MASK 2 ;
END M0PO
LAYER VIA0
TYPE CUT ;
MASK 2 ;
END VIA0
LAYER M1
TYPE MASTERSLICE ;
WIDTH 0.024 ;
MASK 2 ;
END M1
LAYER VIA1
TYPE CUT ;
MASK 2 ;
END VIA1
LAYER M2
TYPE MASTERSLICE ;
WIDTH 0.03 ;
MASK 2 ;
END M2
VIA square
LAYER M0PO ;
RECT MASK 2 -0.06 -0.06 0.06 0.06 ;
LAYER VIA0 ;
RECT -0.06 -0.06 0.06 0.06 ;
LAYER M1 ;
RECT MASK 1 -0.06 -0.06 0.06 0.06 ;
END square
VIA square_nomask
LAYER M0PO ;
RECT -0.06 -0.06 0.06 0.06 ;
LAYER VIA0 ;
RECT -0.06 -0.06 0.06 0.06 ;
LAYER M1 ;
RECT -0.06 -0.06 0.06 0.06 ;
END square_nomask

BIN
testdata/lefdef/scanchain/au.oas.gz vendored Normal file

Binary file not shown.

32
testdata/lefdef/scanchain/test.def vendored Normal file
View File

@ -0,0 +1,32 @@
VERSION 5.8 ;
DIVIDERCHAR "/" ;
BUSBITCHARS "[]" ;
DESIGN chip_top ;
UNITS DISTANCE MICRONS 1000 ;
DIEAREA ( 0 0 ) ( 8729280 8199360 ) ;
SCANCHAINS 9992 ;
- chain1
+ PARTITION part/Y_45_45_0.720000
+ START whereever/anchor_buf_8 Y
+ FLOATING
dumdidum/_reg_1_reg_2_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_2_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_7_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_8_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_5_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_9_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_6_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_4_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_7_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_1_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_3_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_1_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_0_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_4_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_0_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_6_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_3_ ( IN SI ) ( OUT Q )
dumdidum/_reg_1_reg_5_ ( IN SI ) ( OUT Q )
+ STOP somewhere/LOCKUP D ;
END SCANCHAINS
END DESIGN

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,29 @@
VERSION 5.8 ;
DIVIDERCHAR "/" ;
BUSBITCHARS "[]" ;
DESIGN chip_top ;
UNITS DISTANCE MICRONS 1000 ;
DIEAREA ( 0 0 ) ( 300 300 ) ;
STYLES 2 ;
- STYLE 1 ( 30 10 ) ( 10 30 ) ( -10 30 ) ( -30 10 ) ( -30 -10 ) ( -10 -30 ) ( 10 -30 ) ( 30 -10 ) ;
END STYLES
VIAS 1 ;
- VIA1_dummy
+ RECT M1 ( -20 -15 ) ( 20 15 )
+ RECT VIA1 ( -10 -10 ) ( 10 10 )
+ RECT M2 ( -25 -25 ) ( 25 25 ) ;
END VIAS
SPECIALNETS 1 ;
- dummy
+ ROUTED + RECT M2 ( 350 0 ) ( 250 100 )
+ POLYGON M1 ( 300 0 ) ( 300 50 ) ( 350 50 ) ( 400 100 ) ( 400 0 )
+ ROUTED + POLYGON M2 ( 300 150 ) ( 300 200 ) ( 350 200 ) ( 400 250 ) ( 400 150 )
+ RECT M1 ( 0 0 ) ( 100 200 )
+ ROUTED M1 30 + MASK 2 ( 0 0 15 ) ( 100 0 0 ) VIA1_dummy ( 100 100 10 )
+ ROUTED M2 50 + SHAPE RING + STYLE 1 ( 0 100 ) ( 100 200 ) ( 200 200 )
+ ROUTED + MASK 2 + RECT M2 ( 250 0 ) ( 150 100 )
+ ROUTED + SHAPE RING + MASK 1 + VIA VIA1_dummy E ( 200 200 )
;
END SPECIALNETS
END DESIGN

View File

@ -0,0 +1,24 @@
VERSION 5.8 ;
BUSBITCHARS "[]" ;
DIVIDERCHAR "/" ;
UNITS
DATABASE MICRONS 1000 ;
END UNITS
MANUFACTURINGGRID 0.001 ;
LAYER M1
TYPE ROUTING ;
END M1
LAYER VIA1
TYPE CUT ;
END VIA1
LAYER M2
TYPE ROUTING ;
WIDTH 0.05 ;
END M2
END LIBRARY

Some files were not shown because too many files have changed in this diff Show More