mirror of https://github.com/KLayout/klayout.git
Bugfixing multi-DEF reader with LEF cache, adding a testcase. Making unknown vias an error.
This commit is contained in:
parent
a07d742bee
commit
e27e24ff4f
|
|
@ -1947,48 +1947,52 @@ LEFDEFReaderState::finish (db::Layout &layout)
|
||||||
void
|
void
|
||||||
LEFDEFReaderState::register_via_cell (const std::string &vn, const std::string &nondefaultrule, LEFDEFLayoutGenerator *generator)
|
LEFDEFReaderState::register_via_cell (const std::string &vn, const std::string &nondefaultrule, LEFDEFLayoutGenerator *generator)
|
||||||
{
|
{
|
||||||
if (m_via_generators.find (std::make_pair (vn, nondefaultrule)) != m_via_generators.end ()) {
|
// inserts at the end of the range
|
||||||
delete m_via_generators [std::make_pair (vn, nondefaultrule)];
|
m_via_generators.insert (std::make_pair (std::make_pair (vn, nondefaultrule), generator));
|
||||||
}
|
|
||||||
m_via_generators [std::make_pair (vn, nondefaultrule)] = generator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LEFDEFLayoutGenerator *
|
LEFDEFLayoutGenerator *
|
||||||
LEFDEFReaderState::via_generator (const std::string &vn, const std::string &nondefaultrule)
|
LEFDEFReaderState::via_generator (const std::string &vn, const std::string &nondefaultrule)
|
||||||
{
|
{
|
||||||
std::map<std::pair<std::string, std::string>, LEFDEFLayoutGenerator *>::const_iterator g = m_via_generators.find (std::make_pair (vn, nondefaultrule));
|
return via_generator_and_rule (vn, nondefaultrule).first;
|
||||||
if (g == m_via_generators.end () && ! nondefaultrule.empty ()) {
|
}
|
||||||
// default rule is fallback
|
|
||||||
g = m_via_generators.find (std::make_pair (vn, std::string ()));
|
std::pair<LEFDEFLayoutGenerator *, std::string>
|
||||||
|
LEFDEFReaderState::via_generator_and_rule (const std::string &vn, const std::string &nondefaultrule)
|
||||||
|
{
|
||||||
|
auto key = std::make_pair (vn, nondefaultrule);
|
||||||
|
|
||||||
|
auto g = m_via_generators.upper_bound (key);
|
||||||
|
if (g != m_via_generators.begin ()) {
|
||||||
|
--g;
|
||||||
}
|
}
|
||||||
if (g != m_via_generators.end ()) {
|
|
||||||
return g->second;
|
if (g == m_via_generators.end () || g->first != key) {
|
||||||
|
if (nondefaultrule.empty ()) {
|
||||||
|
return std::pair<LEFDEFLayoutGenerator *, std::string> (0, std::string ());
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
// default rule is fallback
|
||||||
|
return via_generator_and_rule (vn, std::string ());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return std::make_pair (g->second, nondefaultrule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Cell *
|
db::Cell *
|
||||||
LEFDEFReaderState::via_cell (const std::string &vn, const std::string &nondefaultrule, db::Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm)
|
LEFDEFReaderState::via_cell (const std::string &vn, const std::string &nondefaultrule, db::Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm)
|
||||||
{
|
{
|
||||||
ViaKey vk (vn, nondefaultrule, mask_bottom, mask_cut, mask_top);
|
auto gr = via_generator_and_rule (vn, nondefaultrule);
|
||||||
|
LEFDEFLayoutGenerator *vg = gr.first;
|
||||||
|
|
||||||
std::map<std::pair<std::string, std::string>, LEFDEFLayoutGenerator *>::const_iterator g = m_via_generators.find (std::make_pair (vn, nondefaultrule));
|
ViaKey vk (vn, gr.second, mask_bottom, mask_cut, mask_top);
|
||||||
|
|
||||||
if (g == m_via_generators.end () && ! vk.nondefaultrule.empty ()) {
|
|
||||||
// default rule is fallback
|
|
||||||
g = m_via_generators.find (std::make_pair (vn, std::string ()));
|
|
||||||
vk.nondefaultrule.clear ();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<ViaKey, db::Cell *>::const_iterator i = m_via_cells.find (vk);
|
std::map<ViaKey, db::Cell *>::const_iterator i = m_via_cells.find (vk);
|
||||||
if (i == m_via_cells.end ()) {
|
if (i == m_via_cells.end ()) {
|
||||||
|
|
||||||
db::Cell *cell = 0;
|
db::Cell *cell = 0;
|
||||||
|
|
||||||
if (g != m_via_generators.end ()) {
|
if (vg) {
|
||||||
|
|
||||||
LEFDEFLayoutGenerator *vg = g->second;
|
|
||||||
|
|
||||||
std::string n = vn;
|
std::string n = vn;
|
||||||
|
|
||||||
|
|
@ -2017,6 +2021,14 @@ LEFDEFReaderState::via_cell (const std::string &vn, const std::string &nondefaul
|
||||||
|
|
||||||
vg->create_cell (*this, layout, *cell, 0, masks, nm);
|
vg->create_cell (*this, layout, *cell, 0, masks, nm);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
std::string details;
|
||||||
|
if (! nondefaultrule.empty () && nondefaultrule != vk.nondefaultrule) {
|
||||||
|
details = tl::sprintf (tl::to_string (tr (" (trying with NONDEFAULTRULE '%s' and without)")), nondefaultrule);
|
||||||
|
}
|
||||||
|
error (tl::sprintf (tl::to_string (tr ("Could not find a via specification with name '%s'")) + details, vn));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_via_cells[vk] = cell;
|
m_via_cells[vk] = cell;
|
||||||
|
|
|
||||||
|
|
@ -1526,7 +1526,7 @@ private:
|
||||||
std::map<std::string, int> m_default_number;
|
std::map<std::string, int> m_default_number;
|
||||||
const LEFDEFReaderOptions *mp_tech_comp;
|
const LEFDEFReaderOptions *mp_tech_comp;
|
||||||
std::map<ViaKey, db::Cell *> m_via_cells;
|
std::map<ViaKey, db::Cell *> m_via_cells;
|
||||||
std::map<std::pair<std::string, std::string>, LEFDEFLayoutGenerator *> m_via_generators;
|
std::multimap<std::pair<std::string, std::string>, LEFDEFLayoutGenerator *> m_via_generators;
|
||||||
std::map<MacroKey, std::pair<db::Cell *, db::Trans> > m_macro_cells;
|
std::map<MacroKey, std::pair<db::Cell *, db::Trans> > m_macro_cells;
|
||||||
std::map<std::string, LEFDEFLayoutGenerator *> m_macro_generators;
|
std::map<std::string, LEFDEFLayoutGenerator *> m_macro_generators;
|
||||||
std::map<std::string, db::cell_index_type> m_foreign_cells;
|
std::map<std::string, db::cell_index_type> m_foreign_cells;
|
||||||
|
|
@ -1538,6 +1538,7 @@ private:
|
||||||
std::set<unsigned int> open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
|
std::set<unsigned int> open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
|
||||||
db::cell_index_type foreign_cell(Layout &layout, const std::string &name);
|
db::cell_index_type foreign_cell(Layout &layout, const std::string &name);
|
||||||
void read_single_map_file (const std::string &path, std::map<std::pair<std::string, LayerDetailsKey>, std::vector<db::LayerProperties> > &layer_map);
|
void read_single_map_file (const std::string &path, std::map<std::pair<std::string, LayerDetailsKey>, std::vector<db::LayerProperties> > &layer_map);
|
||||||
|
std::pair<LEFDEFLayoutGenerator *, std::string> via_generator_and_rule (const std::string &vn, const std::string &nondefaultrule);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include "dbWriter.h"
|
#include "dbWriter.h"
|
||||||
#include "dbDEFImporter.h"
|
#include "dbDEFImporter.h"
|
||||||
#include "dbLEFImporter.h"
|
#include "dbLEFImporter.h"
|
||||||
|
#include "dbCommonReader.h"
|
||||||
|
|
||||||
#include "tlUnitTest.h"
|
#include "tlUnitTest.h"
|
||||||
#include "dbTestSupport.h"
|
#include "dbTestSupport.h"
|
||||||
|
|
@ -1102,3 +1103,35 @@ TEST(214_issue1877)
|
||||||
db::compare_layouts (_this, ly, fn_path + "au.oas", db::WriteOAS);
|
db::compare_layouts (_this, ly, fn_path + "au.oas", db::WriteOAS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// multi-DEF reader support (issue-2014)
|
||||||
|
TEST(215_multiDEF)
|
||||||
|
{
|
||||||
|
std::string fn_path (tl::testdata ());
|
||||||
|
fn_path += "/lefdef/multi_def/";
|
||||||
|
|
||||||
|
db::Layout ly;
|
||||||
|
|
||||||
|
db::LoadLayoutOptions opt;
|
||||||
|
// anything else will not make much sense
|
||||||
|
opt.get_options<db::CommonReaderOptions> ().cell_conflict_resolution = db::CellConflictResolution::RenameCell;
|
||||||
|
|
||||||
|
// Test "set_option_by_name"
|
||||||
|
opt.set_option_by_name ("lefdef_config.lef_context_enabled", true);
|
||||||
|
opt.set_option_by_name ("lefdef_config.map_file", "layers.map");
|
||||||
|
opt.set_option_by_name ("lefdef_config.read_lef_with_def", true);
|
||||||
|
|
||||||
|
const char *files[] = {
|
||||||
|
"main.def",
|
||||||
|
"comp_a.def",
|
||||||
|
"comp_b.def",
|
||||||
|
"comp_c.def"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const char **fn = files; fn != files + sizeof (files) / sizeof (files[0]); ++fn) {
|
||||||
|
tl::InputStream is (fn_path + *fn);
|
||||||
|
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 ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
DESIGN comp_a ;
|
||||||
|
UNITS DISTANCE MICRONS 1000 ;
|
||||||
|
DIEAREA ( 0 0 ) ( 10000 2000 ) ;
|
||||||
|
|
||||||
|
VIAS 2 ;
|
||||||
|
- via1 + VIARULE M1M2_PR + CUTSIZE 150 150 + LAYERS met1 via met2 + CUTSPACING 170 170 + ENCLOSURE 85 165 55 85 + ROWCOL 2 2 ;
|
||||||
|
- via2 + VIARULE M2M3_PR + CUTSIZE 200 200 + LAYERS met2 via2 met3 + CUTSPACING 200 200 + ENCLOSURE 40 85 65 65 + ROWCOL 3 3 ;
|
||||||
|
END VIAS
|
||||||
|
SPECIALNETS 2 ;
|
||||||
|
- VGND ( PIN VGND ) ( * VNB ) ( * VGND ) + USE GROUND
|
||||||
|
+ ROUTED met1 480 + SHAPE FOLLOWPIN ( 0 1000 ) ( 2000 1000 )
|
||||||
|
NEW met1 0 + SHAPE STRIPE ( 2000 1000 ) via1
|
||||||
|
+ ROUTED met2 480 + SHAPE FOLLOWPIN ( 2000 1000 ) ( 4000 1000 )
|
||||||
|
NEW met2 0 + SHAPE STRIPE ( 4000 1000 ) via2 ;
|
||||||
|
END SPECIALNETS
|
||||||
|
END DESIGN
|
||||||
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
VERSION 5.7 ;
|
||||||
|
NOWIREEXTENSIONATPIN ON ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
MACRO comp_a
|
||||||
|
CLASS BLOCK ;
|
||||||
|
FOREIGN comp_a ;
|
||||||
|
ORIGIN 0.000 0.000 ;
|
||||||
|
SIZE 10000.000 BY 2000.000 ;
|
||||||
|
END comp_a
|
||||||
|
END LIBRARY
|
||||||
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
VERSION 5.8 ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
DESIGN comp_b ;
|
||||||
|
UNITS DISTANCE MICRONS 1000 ;
|
||||||
|
DIEAREA ( 0 0 ) ( 10000 2000 ) ;
|
||||||
|
|
||||||
|
VIAS 2 ;
|
||||||
|
- via1 + VIARULE M1M2_PR + CUTSIZE 150 150 + LAYERS met1 via met2 + CUTSPACING 170 170 + ENCLOSURE 85 165 55 85 + ROWCOL 2 1 ;
|
||||||
|
- via2 + VIARULE M2M3_PR + CUTSIZE 200 200 + LAYERS met2 via2 met3 + CUTSPACING 200 200 + ENCLOSURE 40 85 65 65 + ROWCOL 3 2 ;
|
||||||
|
END VIAS
|
||||||
|
SPECIALNETS 2 ;
|
||||||
|
- VGND ( PIN VGND ) ( * VNB ) ( * VGND ) + USE GROUND
|
||||||
|
+ ROUTED met1 480 + SHAPE FOLLOWPIN ( 0 1000 ) ( 2000 1000 )
|
||||||
|
NEW met1 0 + SHAPE STRIPE ( 2000 1000 ) via1
|
||||||
|
+ ROUTED met2 480 + SHAPE FOLLOWPIN ( 2000 1000 ) ( 4000 1000 )
|
||||||
|
NEW met2 0 + SHAPE STRIPE ( 4000 1000 ) via2 ;
|
||||||
|
END SPECIALNETS
|
||||||
|
END DESIGN
|
||||||
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
VERSION 5.7 ;
|
||||||
|
NOWIREEXTENSIONATPIN ON ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
MACRO comp_b
|
||||||
|
CLASS BLOCK ;
|
||||||
|
FOREIGN comp_b ;
|
||||||
|
ORIGIN 0.000 0.000 ;
|
||||||
|
SIZE 10000.000 BY 2000.000 ;
|
||||||
|
END comp_b
|
||||||
|
END LIBRARY
|
||||||
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
VERSION 5.8 ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
DESIGN comp_c ;
|
||||||
|
UNITS DISTANCE MICRONS 1000 ;
|
||||||
|
DIEAREA ( 0 0 ) ( 10000 2000 ) ;
|
||||||
|
|
||||||
|
SPECIALNETS 2 ;
|
||||||
|
- VGND ( PIN VGND ) ( * VNB ) ( * VGND ) + USE GROUND
|
||||||
|
+ ROUTED met1 480 + SHAPE FOLLOWPIN ( 0 1000 ) ( 2000 1000 )
|
||||||
|
NEW met1 0 + SHAPE STRIPE ( 2000 1000 ) via1
|
||||||
|
+ ROUTED met2 480 + SHAPE FOLLOWPIN ( 2000 1000 ) ( 4000 1000 )
|
||||||
|
NEW met2 0 + SHAPE STRIPE ( 4000 1000 ) via2 ;
|
||||||
|
END SPECIALNETS
|
||||||
|
END DESIGN
|
||||||
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
VERSION 5.7 ;
|
||||||
|
NOWIREEXTENSIONATPIN ON ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
MACRO comp_c
|
||||||
|
CLASS BLOCK ;
|
||||||
|
FOREIGN comp_c ;
|
||||||
|
ORIGIN 0.000 0.000 ;
|
||||||
|
SIZE 10000.000 BY 2000.000 ;
|
||||||
|
END comp_c
|
||||||
|
END LIBRARY
|
||||||
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
met1 VIA,LEFPIN,PIN,SPNET,NET 1 0
|
||||||
|
via VIA,LEFPIN,PIN,SPNET,NET 2 0
|
||||||
|
met2 VIA,LEFPIN,PIN,SPNET,NET 3 0
|
||||||
|
via2 VIA,LEFPIN,PIN,SPNET,NET 4 0
|
||||||
|
met3 VIA,LEFPIN,PIN,SPNET,NET 5 0
|
||||||
|
|
||||||
|
DIEAREA ALL 100 0
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
VERSION 5.8 ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
DESIGN caravel ;
|
||||||
|
UNITS DISTANCE MICRONS 1000 ;
|
||||||
|
DIEAREA ( 0 0 ) ( 10000 10000 ) ;
|
||||||
|
COMPONENTS 4 ;
|
||||||
|
- comp_a comp_a + PLACED ( 0 0 ) N ;
|
||||||
|
- comp_b comp_b + PLACED ( 0 2000 ) N ;
|
||||||
|
- comp_c comp_c + PLACED ( 0 4000 ) N ;
|
||||||
|
#- comp_d comp_d + PLACED ( 0 4000 ) N ;
|
||||||
|
END COMPONENTS
|
||||||
|
END DESIGN
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,89 @@
|
||||||
|
|
||||||
|
VERSION 5.7 ;
|
||||||
|
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
USEMINSPACING OBS OFF ;
|
||||||
|
|
||||||
|
UNITS
|
||||||
|
DATABASE MICRONS 1000 ;
|
||||||
|
END UNITS
|
||||||
|
|
||||||
|
MANUFACTURINGGRID 0.005 ;
|
||||||
|
|
||||||
|
LAYER met1
|
||||||
|
TYPE ROUTING ;
|
||||||
|
DIRECTION HORIZONTAL ;
|
||||||
|
PITCH 0.34 ;
|
||||||
|
OFFSET 0.17 ;
|
||||||
|
WIDTH 0.14 ;
|
||||||
|
END met1
|
||||||
|
|
||||||
|
LAYER via
|
||||||
|
TYPE CUT ;
|
||||||
|
WIDTH 0.15 ;
|
||||||
|
SPACING 0.17 ;
|
||||||
|
END via
|
||||||
|
|
||||||
|
LAYER met2
|
||||||
|
TYPE ROUTING ;
|
||||||
|
DIRECTION VERTICAL ;
|
||||||
|
PITCH 0.46 ;
|
||||||
|
OFFSET 0.23 ;
|
||||||
|
WIDTH 0.14 ;
|
||||||
|
END met2
|
||||||
|
|
||||||
|
LAYER via2
|
||||||
|
TYPE CUT ;
|
||||||
|
WIDTH 0.2 ;
|
||||||
|
SPACING 0.2 ;
|
||||||
|
END via2
|
||||||
|
|
||||||
|
LAYER met3
|
||||||
|
TYPE ROUTING ;
|
||||||
|
DIRECTION HORIZONTAL ;
|
||||||
|
PITCH 0.68 ;
|
||||||
|
OFFSET 0.34 ;
|
||||||
|
WIDTH 0.3 ;
|
||||||
|
END met3
|
||||||
|
|
||||||
|
VIA via1 DEFAULT
|
||||||
|
LAYER via ;
|
||||||
|
RECT -0.075 -0.075 0.075 0.075 ;
|
||||||
|
LAYER met1 ;
|
||||||
|
RECT -0.16 -0.24 0.16 0.24 ;
|
||||||
|
LAYER met2 ;
|
||||||
|
RECT -0.13 -0.24 0.13 0.24 ;
|
||||||
|
END via1
|
||||||
|
|
||||||
|
VIARULE M1M2_PR GENERATE
|
||||||
|
LAYER met1 ;
|
||||||
|
ENCLOSURE 0.085 0.055 ;
|
||||||
|
LAYER met2 ;
|
||||||
|
ENCLOSURE 0.055 0.085 ;
|
||||||
|
LAYER via ;
|
||||||
|
RECT -0.075 -0.075 0.075 0.075 ;
|
||||||
|
SPACING 0.32 BY 0.32 ;
|
||||||
|
END M1M2_PR
|
||||||
|
|
||||||
|
VIA via2 DEFAULT
|
||||||
|
LAYER via2 ;
|
||||||
|
RECT -0.1 -0.1 0.1 0.1 ;
|
||||||
|
LAYER met2 ;
|
||||||
|
RECT -0.14 -0.24 0.14 0.24 ;
|
||||||
|
LAYER met3 ;
|
||||||
|
RECT -0.165 -0.165 0.165 0.165 ;
|
||||||
|
END via2
|
||||||
|
|
||||||
|
VIARULE M2M3_PR GENERATE
|
||||||
|
LAYER met2 ;
|
||||||
|
ENCLOSURE 0.04 0.085 ;
|
||||||
|
LAYER met3 ;
|
||||||
|
ENCLOSURE 0.065 0.065 ;
|
||||||
|
LAYER via2 ;
|
||||||
|
RECT -0.1 -0.1 0.1 0.1 ;
|
||||||
|
SPACING 0.4 BY 0.4 ;
|
||||||
|
END M2M3_PR
|
||||||
|
|
||||||
|
END LIBRARY
|
||||||
|
|
||||||
Loading…
Reference in New Issue