mirror of https://github.com/KLayout/klayout.git
Refining solution
- Properly handling copy constructor and initialization - Simplify code - Added test
This commit is contained in:
parent
592d65f9f6
commit
a654c707b3
|
|
@ -597,6 +597,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions ()
|
||||||
m_special_routing_datatype (0),
|
m_special_routing_datatype (0),
|
||||||
m_separate_groups (false),
|
m_separate_groups (false),
|
||||||
m_joined_paths (false),
|
m_joined_paths (false),
|
||||||
|
m_skip_duplicate_macros (false),
|
||||||
m_macro_resolution_mode (0),
|
m_macro_resolution_mode (0),
|
||||||
m_read_lef_with_def (true),
|
m_read_lef_with_def (true),
|
||||||
m_paths_relative_to_cwd (false),
|
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_macro_layout_files = d.m_macro_layout_files;
|
||||||
m_read_lef_with_def = d.m_read_lef_with_def;
|
m_read_lef_with_def = d.m_read_lef_with_def;
|
||||||
m_paths_relative_to_cwd = d.m_paths_relative_to_cwd;
|
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 ());
|
set_macro_layouts (d.macro_layouts ());
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -1069,7 +1071,10 @@ void
|
||||||
LEFDEFReaderState::ensure_lef_importer (int warn_level)
|
LEFDEFReaderState::ensure_lef_importer (int warn_level)
|
||||||
{
|
{
|
||||||
if (! mp_lef_importer.get ()) {
|
if (! mp_lef_importer.get ()) {
|
||||||
mp_lef_importer.reset (new db::LEFImporter (warn_level, true));
|
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 ());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
|
||||||
|
|
||||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file")));
|
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file")));
|
||||||
|
|
||||||
db::LEFImporter importer (warn_level (), effective_options.skip_duplicate_macros ());
|
db::LEFImporter importer (warn_level ());
|
||||||
|
|
||||||
for (std::vector<std::string>::const_iterator l = effective_options.begin_lef_files (); l != effective_options.end_lef_files (); ++l) {
|
for (std::vector<std::string>::const_iterator l = effective_options.begin_lef_files (); l != effective_options.end_lef_files (); ++l) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,9 @@ namespace db
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
// LEFImporter implementation
|
// LEFImporter implementation
|
||||||
|
|
||||||
LEFImporter::LEFImporter (int warn_level, bool skip_duplicate_macros)
|
LEFImporter::LEFImporter (int warn_level)
|
||||||
: LEFDEFImporter (warn_level),
|
: LEFDEFImporter (warn_level),
|
||||||
m_skip_duplicate_macros (skip_duplicate_macros)
|
m_skip_duplicate_macros (false)
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
@ -885,67 +885,21 @@ void
|
||||||
LEFImporter::read_macro (Layout &layout)
|
LEFImporter::read_macro (Layout &layout)
|
||||||
{
|
{
|
||||||
std::string mn = get ();
|
std::string mn = get ();
|
||||||
|
set_cellname (mn);
|
||||||
|
|
||||||
|
GeometryBasedLayoutGenerator *mg = 0;
|
||||||
|
|
||||||
if (m_macros.find (mn) != m_macros.end ()) {
|
if (m_macros.find (mn) != m_macros.end ()) {
|
||||||
if (m_skip_duplicate_macros) {
|
if (m_skip_duplicate_macros) {
|
||||||
// 1. Change error to warning
|
warn (tl::to_string (tr ("Skipping duplicate MACRO: : ")) + mn + tl::to_string (tr (" (skip option is enabled by user)")));
|
||||||
warn (tl::to_string (tr ("Duplicate MACRO name: ")) + mn + tl::to_string (tr (" (Skipping duplicate)")));
|
|
||||||
|
|
||||||
// Safe LEF block skipping
|
|
||||||
while (! at_end ()) {
|
|
||||||
|
|
||||||
if (test ("END")) {
|
|
||||||
expect (mn);
|
|
||||||
break;
|
|
||||||
} else if (test ("PIN")) {
|
|
||||||
std::string pn = get (); // PIN always has a pin-name -> skip it
|
|
||||||
//tl::info << tl::to_string (tr ("Found PIN : ")) + pn;
|
|
||||||
while (! at_end ()) {
|
|
||||||
if (test ("PORT")) {
|
|
||||||
//tl::info << tl::to_string (tr ("Found PORT within ")) + pn;
|
|
||||||
while (! at_end ()) {
|
|
||||||
if (test ("END")) {
|
|
||||||
//tl::info << tl::to_string (tr ("Found PORT END within ")) + pn;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
skip_entry ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (test ("END")) {
|
|
||||||
std::string pn = get (); // PIN always has a pin-name -> skip it
|
|
||||||
//tl::info << tl::to_string (tr ("Found PIN END : ")) + pn;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
skip_entry ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (test ("OBS")) {
|
|
||||||
//tl::info << tl::to_string (tr ("Found OBS"));
|
|
||||||
while (! at_end ()) {
|
|
||||||
if (test ("END")) {
|
|
||||||
//tl::info << tl::to_string (tr ("Found END OBS"));
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
skip_entry ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
skip_entry ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tl::info << tl::to_string (tr ("Successfully skipped duplicate MACRO: ")) + mn;
|
|
||||||
|
|
||||||
return; // Exit early so we don't register or process this duplicate
|
|
||||||
} else {
|
} else {
|
||||||
error (tl::to_string (tr ("Duplicate MACRO name: ")) + mn);
|
error (tl::to_string (tr ("Duplicate MACRO name: ")) + mn);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
mg = new GeometryBasedLayoutGenerator ();
|
||||||
|
reader_state ()->register_macro_cell (mn, mg);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_cellname (mn);
|
|
||||||
|
|
||||||
GeometryBasedLayoutGenerator *mg = new GeometryBasedLayoutGenerator ();
|
|
||||||
reader_state ()->register_macro_cell (mn, mg);
|
|
||||||
|
|
||||||
db::Trans foreign_trans;
|
db::Trans foreign_trans;
|
||||||
std::string foreign_name;
|
std::string foreign_name;
|
||||||
|
|
||||||
|
|
@ -1017,7 +971,7 @@ LEFImporter::read_macro (Layout &layout)
|
||||||
read_geometries (mg, layout.dbu (), LEFPins, &boxes_for_labels, prop_id);
|
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) {
|
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);
|
mg->add_text (b->first, LEFLabel, db::Text (label.c_str (), db::Trans (b->second.center () - db::Point ())), 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1104,7 +1058,9 @@ LEFImporter::read_macro (Layout &layout)
|
||||||
|
|
||||||
} else if (test ("FIXEDMASK")) {
|
} else if (test ("FIXEDMASK")) {
|
||||||
|
|
||||||
mg->set_fixedmask (true);
|
if (mg) {
|
||||||
|
mg->set_fixedmask (true);
|
||||||
|
}
|
||||||
expect (";");
|
expect (";");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1127,8 +1083,10 @@ LEFImporter::read_macro (Layout &layout)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mg->add_box (std::string (), Outline, db::Box (-origin, -origin + size), 0, 0);
|
if (mg) {
|
||||||
mg->subtract_overlap_from_outline (m_overlap_layers);
|
mg->add_box (std::string (), Outline, db::Box (-origin, -origin + size), 0, 0);
|
||||||
|
mg->subtract_overlap_from_outline (m_overlap_layers);
|
||||||
|
}
|
||||||
|
|
||||||
MacroDesc macro_desc;
|
MacroDesc macro_desc;
|
||||||
macro_desc.foreign_name = foreign_name;
|
macro_desc.foreign_name = foreign_name;
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Default constructor
|
* @brief Default constructor
|
||||||
*/
|
*/
|
||||||
LEFImporter (int warn_level, bool skip_duplicate_macros);
|
LEFImporter (int warn_level);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destructor
|
* @brief Destructor
|
||||||
|
|
@ -147,6 +147,31 @@ public:
|
||||||
*/
|
*/
|
||||||
void finish_lef (db::Layout &layout);
|
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:
|
protected:
|
||||||
void do_read (db::Layout &layout);
|
void do_read (db::Layout &layout);
|
||||||
|
|
||||||
|
|
@ -159,6 +184,7 @@ private:
|
||||||
std::map<std::string, ViaDesc> m_vias;
|
std::map<std::string, ViaDesc> m_vias;
|
||||||
std::set<std::string> m_routing_layers, m_cut_layers, m_overlap_layers;
|
std::set<std::string> m_routing_layers, m_cut_layers, m_overlap_layers;
|
||||||
std::map<std::string, unsigned int> m_num_masks;
|
std::map<std::string, unsigned int> m_num_masks;
|
||||||
|
bool m_skip_duplicate_macros;
|
||||||
|
|
||||||
std::vector <db::Trans> get_iteration (double dbu);
|
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_geometries (GeometryBasedLayoutGenerator *lg, double dbu, LayerPurpose purpose, std::map<std::string, db::Box> *collect_bboxes = 0, properties_id_type prop_id = 0);
|
||||||
|
|
@ -169,8 +195,6 @@ private:
|
||||||
void read_layer (Layout &layout);
|
void read_layer (Layout &layout);
|
||||||
void read_macro (Layout &layout);
|
void read_macro (Layout &layout);
|
||||||
void skip_entry ();
|
void skip_entry ();
|
||||||
|
|
||||||
bool m_skip_duplicate_macros;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
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
|
||||||
Loading…
Reference in New Issue