mirror of https://github.com/KLayout/klayout.git
Merge pull request #620 from KLayout/lefdef-enhancments
Lefdef enhancments
This commit is contained in:
commit
12ac7c1036
51
TODO
51
TODO
|
|
@ -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
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace db
|
|||
*
|
||||
* This implementation will create new layers if required.
|
||||
*/
|
||||
class DirectLayerMapping
|
||||
class DB_PUBLIC DirectLayerMapping
|
||||
: public ImportLayerMapping
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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", ©_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", ©_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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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", ©_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", ©_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"
|
||||
|
|
|
|||
|
|
@ -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:");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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> > ®ions, 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
|
|
@ -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 ¯o_desc, const LEFDEFNumberOfMasks *nm);
|
||||
|
||||
/**
|
||||
* @brief Gets the macro generator for a given macro name or 0 if there is no such generator
|
||||
*/
|
||||
LEFDEFLayoutGenerator *macro_generator (const std::string &mn);
|
||||
|
||||
/**
|
||||
* @brief Get the technology component pointer
|
||||
*/
|
||||
|
|
@ -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 ();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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 ¯o_name) const;
|
||||
|
||||
/**
|
||||
* @brief Get the cell bbox for the given macro name
|
||||
*/
|
||||
db::Box macro_bbox_by_name (const std::string ¯o_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> ¯os () 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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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))));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
|
@ -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
|
||||
|
|
@ -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.
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
Binary file not shown.
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Binary file not shown.
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Binary file not shown.
|
|
@ -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.
|
|
@ -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
|
||||
|
|
@ -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
Loading…
Reference in New Issue