mirror of https://github.com/KLayout/klayout.git
Merge pull request #2413 from KLayout/feature/issue-2374
Feature/issue 2374
This commit is contained in:
commit
6d9fcd529a
|
|
@ -112,6 +112,7 @@ GenericReaderOptions::GenericReaderOptions ()
|
|||
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 ();
|
||||
m_lefdef_skip_duplicate_macros = load_options.get_option_by_name ("lefdef_config.skip_duplicate_macros").to_bool ();
|
||||
|
||||
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) {
|
||||
|
|
@ -653,9 +654,9 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
|
|||
"\n"
|
||||
"The following values are accepted for this option:\n"
|
||||
"\n"
|
||||
"* 0: produce LEF geometry unless a FOREIGN cell is specified (the default)\n"
|
||||
"* 0: produce LEF geometry unless a FOREIGN cell is specified\n"
|
||||
"* 1: produce LEF geometry always and ignore FOREIGN\n"
|
||||
"* 2: Never produce LEF geometry and assume FOREIGN always\n"
|
||||
"* 2: Never produce LEF geometry and assume FOREIGN always (the default)\n"
|
||||
"\n"
|
||||
"In case of FOREIGN macros in mode 0 or always in mode 2, the '--" + m_long_prefix + "lefdef-lef-layouts' option is available to specify "
|
||||
"external layout files for providing the LEF macro layouts.\n"
|
||||
|
|
@ -686,6 +687,15 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
|
|||
"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"
|
||||
)
|
||||
<< tl::arg (group +
|
||||
"#--" + m_long_prefix + "lefdef-skip-duplicate-macros", &m_lefdef_skip_duplicate_macros, "Skip duplicate LEF macros",
|
||||
"This option applies when reading DEF files.\n"
|
||||
"\n"
|
||||
"If this option is present, having the same macro in different LEF files is a warning rather than being an error. "
|
||||
"In that case, the first occurance is used. Use this option with care, as it may render invalid layouts when "
|
||||
"the versions of the macro are defined differently. It is intended for cases, when macros with the same name are guaranteed "
|
||||
"to be identical. KLayout does not check, if that is actually the case."
|
||||
)
|
||||
;
|
||||
|
||||
}
|
||||
|
|
@ -814,6 +824,7 @@ GenericReaderOptions::configure (db::LoadLayoutOptions &load_options)
|
|||
load_options.set_option_by_name ("lefdef_config.macro_resolution_mode", m_lefdef_macro_resolution_mode);
|
||||
load_options.set_option_by_name ("lefdef_config.macro_resolution_mode", m_lefdef_macro_resolution_mode);
|
||||
load_options.set_option_by_name ("lefdef_config.paths_relative_to_cwd", true);
|
||||
load_options.set_option_by_name ("lefdef_config.skip_duplicate_macros", m_lefdef_skip_duplicate_macros);
|
||||
|
||||
tl::Variant lef_layout_files = tl::Variant::empty_list ();
|
||||
for (std::vector<std::string>::const_iterator l = m_lefdef_lef_layout_files.begin (); l != m_lefdef_lef_layout_files.end (); ++l) {
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ private:
|
|||
std::vector<std::string> m_lefdef_map_files;
|
||||
int m_lefdef_macro_resolution_mode;
|
||||
std::vector<std::string> m_lefdef_lef_layout_files;
|
||||
bool m_lefdef_skip_duplicate_macros;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -597,6 +597,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions ()
|
|||
m_special_routing_datatype (0),
|
||||
m_separate_groups (false),
|
||||
m_joined_paths (false),
|
||||
m_skip_duplicate_macros (false),
|
||||
m_macro_resolution_mode (0),
|
||||
m_read_lef_with_def (true),
|
||||
m_paths_relative_to_cwd (false),
|
||||
|
|
@ -682,6 +683,7 @@ LEFDEFReaderOptions &LEFDEFReaderOptions::operator= (const LEFDEFReaderOptions &
|
|||
m_macro_layout_files = d.m_macro_layout_files;
|
||||
m_read_lef_with_def = d.m_read_lef_with_def;
|
||||
m_paths_relative_to_cwd = d.m_paths_relative_to_cwd;
|
||||
m_skip_duplicate_macros = d.m_skip_duplicate_macros;
|
||||
set_macro_layouts (d.macro_layouts ());
|
||||
}
|
||||
return *this;
|
||||
|
|
@ -1070,6 +1072,9 @@ LEFDEFReaderState::ensure_lef_importer (int warn_level)
|
|||
{
|
||||
if (! mp_lef_importer.get ()) {
|
||||
mp_lef_importer.reset (new db::LEFImporter (warn_level));
|
||||
if (mp_tech_comp) {
|
||||
mp_lef_importer->set_skip_duplicate_macros (mp_tech_comp->skip_duplicate_macros ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -896,6 +896,16 @@ public:
|
|||
m_map_files = f;
|
||||
}
|
||||
|
||||
bool skip_duplicate_macros () const
|
||||
{
|
||||
return m_skip_duplicate_macros;
|
||||
}
|
||||
|
||||
void set_skip_duplicate_macros (bool v)
|
||||
{
|
||||
m_skip_duplicate_macros = v;
|
||||
}
|
||||
|
||||
std::string single_map_file () const
|
||||
{
|
||||
return m_map_files.empty () ? std::string () : m_map_files.front ();
|
||||
|
|
@ -1055,6 +1065,7 @@ private:
|
|||
bool m_separate_groups;
|
||||
bool m_joined_paths;
|
||||
std::vector<std::string> m_map_files;
|
||||
bool m_skip_duplicate_macros;
|
||||
unsigned int m_macro_resolution_mode;
|
||||
bool m_read_lef_with_def;
|
||||
std::vector<std::string> m_lef_files;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ namespace db
|
|||
// LEFImporter implementation
|
||||
|
||||
LEFImporter::LEFImporter (int warn_level)
|
||||
: LEFDEFImporter (warn_level)
|
||||
: LEFDEFImporter (warn_level),
|
||||
m_skip_duplicate_macros (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -884,15 +885,20 @@ void
|
|||
LEFImporter::read_macro (Layout &layout)
|
||||
{
|
||||
std::string mn = get ();
|
||||
|
||||
if (m_macros.find (mn) != m_macros.end ()) {
|
||||
error (tl::to_string (tr ("Duplicate MACRO name: ")) + mn);
|
||||
}
|
||||
|
||||
set_cellname (mn);
|
||||
|
||||
GeometryBasedLayoutGenerator *mg = new GeometryBasedLayoutGenerator ();
|
||||
reader_state ()->register_macro_cell (mn, mg);
|
||||
GeometryBasedLayoutGenerator *mg = 0;
|
||||
|
||||
if (m_macros.find (mn) != m_macros.end ()) {
|
||||
if (m_skip_duplicate_macros) {
|
||||
warn (tl::to_string (tr ("Skipping duplicate MACRO: : ")) + mn + tl::to_string (tr (" (skip option is enabled by user)")));
|
||||
} else {
|
||||
error (tl::to_string (tr ("Duplicate MACRO name: ")) + mn);
|
||||
}
|
||||
} else {
|
||||
mg = new GeometryBasedLayoutGenerator ();
|
||||
reader_state ()->register_macro_cell (mn, mg);
|
||||
}
|
||||
|
||||
db::Trans foreign_trans;
|
||||
std::string foreign_name;
|
||||
|
|
@ -965,7 +971,7 @@ LEFImporter::read_macro (Layout &layout)
|
|||
read_geometries (mg, layout.dbu (), LEFPins, &boxes_for_labels, prop_id);
|
||||
|
||||
for (std::map <std::string, db::Box>::const_iterator b = boxes_for_labels.begin (); b != boxes_for_labels.end (); ++b) {
|
||||
if (! b->second.empty ()) {
|
||||
if (mg && ! b->second.empty ()) {
|
||||
mg->add_text (b->first, LEFLabel, db::Text (label.c_str (), db::Trans (b->second.center () - db::Point ())), 0, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -1052,7 +1058,9 @@ LEFImporter::read_macro (Layout &layout)
|
|||
|
||||
} else if (test ("FIXEDMASK")) {
|
||||
|
||||
mg->set_fixedmask (true);
|
||||
if (mg) {
|
||||
mg->set_fixedmask (true);
|
||||
}
|
||||
expect (";");
|
||||
|
||||
} else {
|
||||
|
|
@ -1075,8 +1083,10 @@ LEFImporter::read_macro (Layout &layout)
|
|||
|
||||
}
|
||||
|
||||
mg->add_box (std::string (), Outline, db::Box (-origin, -origin + size), 0, 0);
|
||||
mg->subtract_overlap_from_outline (m_overlap_layers);
|
||||
if (mg) {
|
||||
mg->add_box (std::string (), Outline, db::Box (-origin, -origin + size), 0, 0);
|
||||
mg->subtract_overlap_from_outline (m_overlap_layers);
|
||||
}
|
||||
|
||||
MacroDesc macro_desc;
|
||||
macro_desc.foreign_name = foreign_name;
|
||||
|
|
|
|||
|
|
@ -147,6 +147,31 @@ public:
|
|||
*/
|
||||
void finish_lef (db::Layout &layout);
|
||||
|
||||
/**
|
||||
* @brief Sets a flag indicating whether to skip duplicate macros
|
||||
*
|
||||
* With this flag set to true, macros are ignored when there already
|
||||
* is a macro with the same name. Use this option with caution, as
|
||||
* skipping is only permitted if both macros are identical. The
|
||||
* LEF reader does not check this condition.
|
||||
*
|
||||
* The default is "false" (raise an error on duplicate macros).
|
||||
*/
|
||||
void set_skip_duplicate_macros (bool f)
|
||||
{
|
||||
m_skip_duplicate_macros = f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a flag indicating whether to skip duplicate macros
|
||||
*
|
||||
* See set_skip_duplicate_macros for an explanation of this flag.
|
||||
*/
|
||||
bool skip_duplicate_macros () const
|
||||
{
|
||||
return m_skip_duplicate_macros;
|
||||
}
|
||||
|
||||
protected:
|
||||
void do_read (db::Layout &layout);
|
||||
|
||||
|
|
@ -159,6 +184,7 @@ private:
|
|||
std::map<std::string, ViaDesc> m_vias;
|
||||
std::set<std::string> m_routing_layers, m_cut_layers, m_overlap_layers;
|
||||
std::map<std::string, unsigned int> m_num_masks;
|
||||
bool m_skip_duplicate_macros;
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -967,6 +967,24 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
|
|||
"\n"
|
||||
"This property has been added in version 0.27. The ability to supply multiple files has been added in version 0.30.6.\n"
|
||||
) +
|
||||
gsi::method ("skip_duplicate_macros", &db::LEFDEFReaderOptions::skip_duplicate_macros,
|
||||
"@brief Gets a value indicating wether to skip duplicate LEF Macro definitions.\n"
|
||||
"If this property is 'true', having the same macro in different LEF files is a warning rather than being an error. "
|
||||
"In that case, the first occurance is used. Use this option with care, as it may render invalid layouts when "
|
||||
"the versions of the macro are defined differently. It is intended for cases, when macros with the same name are guaranteed "
|
||||
"to be identical. KLayout does not check, if that is actually the case."
|
||||
"\n"
|
||||
"The default is 'false' (duplicate macro names are an error).\n"
|
||||
"\n"
|
||||
"This property has been added in version 0.30.x.\n"
|
||||
) +
|
||||
gsi::method ("skip_duplicate_macros=", &db::LEFDEFReaderOptions::set_skip_duplicate_macros, gsi::arg ("skip_duplicate_macros"),
|
||||
"@brief Sets a value indicating wether to skip duplicate LEF Macro definitions.\n"
|
||||
"\n"
|
||||
"See \\skip_duplicate_macros for a description of this property.\n"
|
||||
"\n"
|
||||
"This property has been added in version 0.30.11.\n"
|
||||
) +
|
||||
gsi::method ("macro_resolution_mode", &db::LEFDEFReaderOptions::macro_resolution_mode,
|
||||
"@brief Gets the macro resolution mode (LEF macros into DEF).\n"
|
||||
"This property describes the way LEF macros are turned into layout cells when reading DEF. There "
|
||||
|
|
|
|||
|
|
@ -1199,3 +1199,54 @@ TEST(216_line_extensions)
|
|||
run_test (_this, "issue-2075", "map:test.map+lef:test.lef+def:test.def", "au.oas", default_options (), false);
|
||||
}
|
||||
|
||||
// issue-2374 (skip duplicate LEF macro option)
|
||||
TEST(217_skip_duplicate_macro)
|
||||
{
|
||||
std::string fn_path (tl::testdata ());
|
||||
fn_path += "/lefdef/issue-2374/";
|
||||
|
||||
db::LEFDEFReaderOptions lefdef_opt = default_options ();
|
||||
lefdef_opt.set_single_map_file ("tech.map");
|
||||
std::vector<std::string> lf;
|
||||
lf.push_back ("tech.lef");
|
||||
lf.push_back ("lib1.lef"); // macros a,b
|
||||
lf.push_back ("lib2.lef"); // macros b,c
|
||||
lefdef_opt.set_lef_files (lf);
|
||||
lefdef_opt.set_read_lef_with_def (false);
|
||||
|
||||
db::Layout ly;
|
||||
|
||||
try {
|
||||
|
||||
db::LoadLayoutOptions opt;
|
||||
opt.set_options (lefdef_opt);
|
||||
EXPECT_EQ (lefdef_opt.skip_duplicate_macros (), false);
|
||||
|
||||
tl::InputStream is (fn_path + "top.def");
|
||||
db::Reader reader (is);
|
||||
reader.read (ly, opt);
|
||||
|
||||
// must throw an exception because of duplicate macros
|
||||
EXPECT_EQ (1, 0);
|
||||
|
||||
} catch (...) { }
|
||||
|
||||
ly = db::Layout ();
|
||||
|
||||
{
|
||||
|
||||
db::LEFDEFReaderOptions lo = lefdef_opt;
|
||||
lo.set_skip_duplicate_macros (true);
|
||||
EXPECT_EQ (lo.skip_duplicate_macros (), true);
|
||||
db::LoadLayoutOptions opt;
|
||||
opt.set_options (lo);
|
||||
|
||||
tl::InputStream is (fn_path + "top.def");
|
||||
db::Reader reader (is);
|
||||
reader.read (ly, opt);
|
||||
|
||||
}
|
||||
|
||||
db::compare_layouts (_this, ly, fn_path + "au.oas", db::WriteOAS);
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,20 @@
|
|||
VERSION 5.8 ;
|
||||
|
||||
MACRO a
|
||||
ORIGIN 0 0 ;
|
||||
SIZE 600 BY 600 ;
|
||||
OBS
|
||||
LAYER M1 ;
|
||||
RECT 10 10 590 590 ;
|
||||
END
|
||||
END a
|
||||
|
||||
MACRO b
|
||||
ORIGIN -600 0 ;
|
||||
SIZE 400 BY 500 ;
|
||||
OBS
|
||||
LAYER M1 ;
|
||||
RECT 610 10 990 490 ;
|
||||
END
|
||||
END b
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
VERSION 5.8 ;
|
||||
|
||||
MACRO b
|
||||
ORIGIN -600 0 ;
|
||||
SIZE 400 BY 500 ;
|
||||
OBS
|
||||
LAYER M1 ;
|
||||
RECT 610 10 990 590 ;
|
||||
END
|
||||
END b
|
||||
|
||||
MACRO c
|
||||
ORIGIN -500 -500 ;
|
||||
SIZE 500 BY 500 ;
|
||||
OBS
|
||||
LAYER M1 ;
|
||||
POLYGON 510 610 610 610 610 510 990 510 990 990 510 990 ;
|
||||
LAYER overlap ;
|
||||
RECT 500 700 1000 1000 ;
|
||||
POLYGON 500 600 600 600 600 500 1000 500 1000 700 500 700 ;
|
||||
END
|
||||
END c
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
VERSION 5.8 ;
|
||||
|
||||
LAYER M1
|
||||
TYPE ROUTING ;
|
||||
DIRECTION HORIZONTAL ;
|
||||
WIDTH 0.1 ;
|
||||
PITCH 0.1 ;
|
||||
END M1
|
||||
|
||||
LAYER overlap
|
||||
TYPE OVERLAP ;
|
||||
END overlap
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
DIEAREA ALL 1 0
|
||||
#BOUNDARY DIEAREA 1 0
|
||||
BOUNDARY MACRO 1 0
|
||||
#M1 LEFOBS 2 0
|
||||
M1 LEFOBS 3 0
|
||||
M1 BLOCKAGE 3 0
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
VERSION 5.8 ;
|
||||
DESIGN top ;
|
||||
UNITS DISTANCE MICRONS 1000 ;
|
||||
DIEAREA ( 0 0 ) ( 1000000 1000000 ) ;
|
||||
COMPONENTS 3 ;
|
||||
- a a + PLACED ( 0 0 ) N ;
|
||||
- b b + PLACED ( 600000 0 ) N ;
|
||||
- c c + PLACED ( 500000 500000 ) N ;
|
||||
END COMPONENTS
|
||||
END DESIGN
|
||||
|
|
@ -392,6 +392,10 @@ class DBReaders_TestClass < TestBase
|
|||
conf.read_lef_with_def = false
|
||||
assert_equal(conf.read_lef_with_def, false)
|
||||
|
||||
assert_equal(conf.skip_duplicate_macros, false)
|
||||
conf.skip_duplicate_macros = true
|
||||
assert_equal(conf.skip_duplicate_macros, true)
|
||||
|
||||
end
|
||||
|
||||
# MAG Options
|
||||
|
|
|
|||
Loading…
Reference in New Issue