mirror of https://github.com/KLayout/klayout.git
WIP: provide a LEF reader mode where all macros are read. For DEF only those macros which are used are read.
This commit is contained in:
parent
dcc99060fc
commit
af7d8bba89
|
|
@ -64,6 +64,12 @@ DEFImporter::read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFReader
|
||||||
m_lef_importer.read (stream, layout, state);
|
m_lef_importer.read (stream, layout, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFImporter::finish_lef (db::Layout &layout)
|
||||||
|
{
|
||||||
|
m_lef_importer.finish_lef (layout);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DEFImporter::read_polygon (db::Polygon &poly, double scale)
|
DEFImporter::read_polygon (db::Polygon &poly, double scale)
|
||||||
{
|
{
|
||||||
|
|
@ -1274,6 +1280,11 @@ DEFImporter::read_components (db::Layout &layout, std::list<std::pair<std::strin
|
||||||
bool is_placed = false;
|
bool is_placed = false;
|
||||||
std::string maskshift;
|
std::string maskshift;
|
||||||
|
|
||||||
|
std::map<std::string, MacroDesc>::const_iterator m = m_lef_importer.macros ().find (model);
|
||||||
|
if (m == m_lef_importer.macros ().end ()) {
|
||||||
|
error (tl::to_string (tr ("Macro not found in LEF file: ")) + model);
|
||||||
|
}
|
||||||
|
|
||||||
while (test ("+")) {
|
while (test ("+")) {
|
||||||
|
|
||||||
if (test ("PLACED") || test ("FIXED") || test ("COVER")) {
|
if (test ("PLACED") || test ("FIXED") || test ("COVER")) {
|
||||||
|
|
@ -1283,7 +1294,7 @@ DEFImporter::read_components (db::Layout &layout, std::list<std::pair<std::strin
|
||||||
test (")");
|
test (")");
|
||||||
|
|
||||||
ft = get_orient (false /*mandatory*/);
|
ft = get_orient (false /*mandatory*/);
|
||||||
d = pt - m_lef_importer.macro_bbox_by_name (model).transformed (ft).lower_left ();
|
d = pt - m->second.bbox.transformed (ft).lower_left ();
|
||||||
is_placed = true;
|
is_placed = true;
|
||||||
|
|
||||||
} else if (test ("MASKSHIFT")) {
|
} else if (test ("MASKSHIFT")) {
|
||||||
|
|
@ -1302,19 +1313,10 @@ DEFImporter::read_components (db::Layout &layout, std::list<std::pair<std::strin
|
||||||
|
|
||||||
if (is_placed) {
|
if (is_placed) {
|
||||||
|
|
||||||
std::map<std::string, MacroDesc>::const_iterator m = m_lef_importer.macros ().find (model);
|
std::pair<db::Cell *, db::Trans> ct = reader_state ()->macro_cell (model, layout, string2masks (maskshift), m->second, &m_lef_importer);
|
||||||
if (m == m_lef_importer.macros ().end ()) {
|
if (ct.first) {
|
||||||
|
db::CellInstArray inst (db::CellInst (ct.first->cell_index ()), db::Trans (ft.rot (), d) * ct.second);
|
||||||
warn (tl::to_string (tr ("Macro not found in LEF file: ")) + model);
|
instances.push_back (std::make_pair (inst_name, inst));
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
std::pair<db::Cell *, db::Trans> ct = reader_state ()->macro_cell (model, layout, string2masks (maskshift), m->second, &m_lef_importer);
|
|
||||||
if (ct.first) {
|
|
||||||
db::CellInstArray inst (db::CellInst (ct.first->cell_index ()), db::Trans (ft.rot (), d) * ct.second);
|
|
||||||
instances.push_back (std::make_pair (inst_name, inst));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state);
|
void read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Provided for test purposes
|
||||||
|
*/
|
||||||
|
void finish_lef (Layout &layout);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void do_read (db::Layout &layout);
|
void do_read (db::Layout &layout);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,8 @@ private:
|
||||||
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
|
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
|
||||||
importer.read (m_stream, layout, state);
|
importer.read (m_stream, layout, state);
|
||||||
|
|
||||||
|
importer.finish_lef (layout);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading DEF file")));
|
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading DEF file")));
|
||||||
|
|
|
||||||
|
|
@ -188,26 +188,30 @@ LEFImporter::read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, Laye
|
||||||
test (")");
|
test (")");
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Coord iw = db::coord_traits<db::Coord>::rounded (w / dbu);
|
if (lg) {
|
||||||
db::Path p (points.begin (), points.end (), iw, iw / 2, iw / 2, false);
|
|
||||||
|
|
||||||
if (iterate) {
|
db::Coord iw = db::coord_traits<db::Coord>::rounded (w / dbu);
|
||||||
|
db::Path p (points.begin (), points.end (), iw, iw / 2, iw / 2, false);
|
||||||
|
|
||||||
std::vector<db::Trans> ti = get_iteration (dbu);
|
if (iterate) {
|
||||||
|
|
||||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
std::vector<db::Trans> ti = get_iteration (dbu);
|
||||||
db::Path pt = p.transformed (*t);
|
|
||||||
lg->add_path (layer_name, purpose, pt, mask, prop_id);
|
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||||
if (collect_boxes_for_labels) {
|
db::Path pt = p.transformed (*t);
|
||||||
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = pt.box ();
|
lg->add_path (layer_name, purpose, pt, mask, prop_id);
|
||||||
|
if (collect_boxes_for_labels) {
|
||||||
|
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = pt.box ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
lg->add_path (layer_name, purpose, p, mask, prop_id);
|
||||||
|
if (collect_boxes_for_labels) {
|
||||||
|
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = p.box ();
|
||||||
|
}
|
||||||
|
|
||||||
lg->add_path (layer_name, purpose, p, mask, prop_id);
|
|
||||||
if (collect_boxes_for_labels) {
|
|
||||||
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = p.box ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -233,25 +237,29 @@ LEFImporter::read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, Laye
|
||||||
test (")");
|
test (")");
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Polygon p;
|
if (lg) {
|
||||||
p.assign_hull (points.begin (), points.end ());
|
|
||||||
|
|
||||||
if (iterate) {
|
db::Polygon p;
|
||||||
|
p.assign_hull (points.begin (), points.end ());
|
||||||
|
|
||||||
std::vector<db::Trans> ti = get_iteration (dbu);
|
if (iterate) {
|
||||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
|
||||||
db::Polygon pt = p.transformed (*t);
|
std::vector<db::Trans> ti = get_iteration (dbu);
|
||||||
lg->add_polygon (layer_name, purpose, pt, mask, prop_id);
|
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||||
if (collect_boxes_for_labels) {
|
db::Polygon pt = p.transformed (*t);
|
||||||
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = pt.box ();
|
lg->add_polygon (layer_name, purpose, pt, mask, prop_id);
|
||||||
|
if (collect_boxes_for_labels) {
|
||||||
|
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = pt.box ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
lg->add_polygon (layer_name, purpose, p, mask, prop_id);
|
||||||
|
if (collect_boxes_for_labels) {
|
||||||
|
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = p.box ();
|
||||||
|
}
|
||||||
|
|
||||||
lg->add_polygon (layer_name, purpose, p, mask, prop_id);
|
|
||||||
if (collect_boxes_for_labels) {
|
|
||||||
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = p.box ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -279,25 +287,29 @@ LEFImporter::read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, Laye
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Box b (points [0], points [1]);
|
if (lg) {
|
||||||
|
|
||||||
if (iterate) {
|
db::Box b (points [0], points [1]);
|
||||||
|
|
||||||
std::vector<db::Trans> ti = get_iteration (dbu);
|
if (iterate) {
|
||||||
|
|
||||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
std::vector<db::Trans> ti = get_iteration (dbu);
|
||||||
db::Box bt = b.transformed (*t);
|
|
||||||
lg->add_box (layer_name, purpose, bt, mask, prop_id);
|
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||||
if (collect_boxes_for_labels) {
|
db::Box bt = b.transformed (*t);
|
||||||
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = bt;
|
lg->add_box (layer_name, purpose, bt, mask, prop_id);
|
||||||
|
if (collect_boxes_for_labels) {
|
||||||
|
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = bt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
lg->add_box (layer_name, purpose, b, mask, prop_id);
|
||||||
|
if (collect_boxes_for_labels) {
|
||||||
|
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = b;
|
||||||
|
}
|
||||||
|
|
||||||
lg->add_box (layer_name, purpose, b, mask, prop_id);
|
|
||||||
if (collect_boxes_for_labels) {
|
|
||||||
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -333,17 +345,21 @@ LEFImporter::read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, Laye
|
||||||
|
|
||||||
std::string vn = get ();
|
std::string vn = get ();
|
||||||
|
|
||||||
if (iterate) {
|
if (lg) {
|
||||||
|
|
||||||
|
if (iterate) {
|
||||||
|
|
||||||
|
std::vector<db::Trans> ti = get_iteration (dbu);
|
||||||
|
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||||
|
lg->add_via (vn, *t * db::Trans (points [0]), mask_bottom, mask_cut, mask_top);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
lg->add_via (vn, db::Trans (points [0]), mask_bottom, mask_cut, mask_top);
|
||||||
|
|
||||||
std::vector<db::Trans> ti = get_iteration (dbu);
|
|
||||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
|
||||||
lg->add_via (vn, *t * db::Trans (points [0]), mask_bottom, mask_cut, mask_top);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
lg->add_via (vn, db::Trans (points [0]), mask_bottom, mask_cut, mask_top);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expect (";");
|
expect (";");
|
||||||
|
|
@ -850,18 +866,24 @@ LEFImporter::read_macro (Layout &layout)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
db::properties_id_type prop_id = 0;
|
if (reader_state ()->tech_comp ()->produce_lef_pins ()) {
|
||||||
if (produce_pin_props ()) {
|
|
||||||
db::PropertiesRepository::properties_set props;
|
|
||||||
props.insert (std::make_pair (pin_prop_name_id (), tl::Variant (label)));
|
|
||||||
prop_id = layout.properties_repository ().properties_id (props);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map <std::string, db::Box> boxes_for_labels;
|
db::properties_id_type prop_id = 0;
|
||||||
read_geometries (mg, layout.dbu (), LEFPins, &boxes_for_labels, prop_id);
|
if (produce_pin_props ()) {
|
||||||
|
db::PropertiesRepository::properties_set props;
|
||||||
|
props.insert (std::make_pair (pin_prop_name_id (), tl::Variant (label)));
|
||||||
|
prop_id = layout.properties_repository ().properties_id (props);
|
||||||
|
}
|
||||||
|
|
||||||
for (std::map <std::string, db::Box>::const_iterator b = boxes_for_labels.begin (); b != boxes_for_labels.end (); ++b) {
|
std::map <std::string, db::Box> boxes_for_labels;
|
||||||
mg->add_text (b->first, Label, db::Text (label.c_str (), db::Trans (b->second.center () - db::Point ())), 0, 0);
|
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) {
|
||||||
|
mg->add_text (b->first, Label, db::Text (label.c_str (), db::Trans (b->second.center () - db::Point ())), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
read_geometries (0, layout.dbu (), LEFPins, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
expect ("END");
|
expect ("END");
|
||||||
|
|
@ -907,7 +929,12 @@ LEFImporter::read_macro (Layout &layout)
|
||||||
|
|
||||||
} else if (test ("OBS")) {
|
} else if (test ("OBS")) {
|
||||||
|
|
||||||
read_geometries (mg, layout.dbu (), Obstructions);
|
if (reader_state ()->tech_comp ()->produce_obstructions ()) {
|
||||||
|
read_geometries (mg, layout.dbu (), Obstructions);
|
||||||
|
} else {
|
||||||
|
read_geometries (0, layout.dbu (), Obstructions);
|
||||||
|
}
|
||||||
|
|
||||||
expect ("END");
|
expect ("END");
|
||||||
|
|
||||||
} else if (test ("FIXEDMASK")) {
|
} else if (test ("FIXEDMASK")) {
|
||||||
|
|
@ -1037,5 +1064,13 @@ LEFImporter::do_read (db::Layout &layout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LEFImporter::finish_lef (db::Layout &layout)
|
||||||
|
{
|
||||||
|
for (std::map<std::string, MacroDesc>::const_iterator m = m_macros.begin (); m != m_macros.end (); ++m) {
|
||||||
|
reader_state ()->macro_cell (m->first, layout, std::vector<unsigned int> (), m->second, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,11 +57,6 @@ public:
|
||||||
*/
|
*/
|
||||||
~LEFImporter ();
|
~LEFImporter ();
|
||||||
|
|
||||||
/**
|
|
||||||
* @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
|
* @brief Get the width for a layer with the given name
|
||||||
*
|
*
|
||||||
|
|
@ -128,6 +123,14 @@ public:
|
||||||
return m_macros;
|
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:
|
protected:
|
||||||
void do_read (db::Layout &layout);
|
void do_read (db::Layout &layout);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const ch
|
||||||
db::LEFDEFReaderState ld (&options, layout, fn_path);
|
db::LEFDEFReaderState ld (&options, layout, fn_path);
|
||||||
|
|
||||||
db::DEFImporter imp;
|
db::DEFImporter imp;
|
||||||
|
bool any_def = false;
|
||||||
|
bool any_lef = false;
|
||||||
|
|
||||||
while (! ex.at_end ()) {
|
while (! ex.at_end ()) {
|
||||||
|
|
||||||
|
|
@ -85,6 +87,8 @@ static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const ch
|
||||||
tl::InputStream stream (fn);
|
tl::InputStream stream (fn);
|
||||||
imp.read (stream, layout, ld);
|
imp.read (stream, layout, ld);
|
||||||
|
|
||||||
|
any_def = true;
|
||||||
|
|
||||||
} else if (ex.test ("lef:")) {
|
} else if (ex.test ("lef:")) {
|
||||||
|
|
||||||
std::string fn = fn_path, f;
|
std::string fn = fn_path, f;
|
||||||
|
|
@ -94,6 +98,8 @@ static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const ch
|
||||||
tl::InputStream stream (fn);
|
tl::InputStream stream (fn);
|
||||||
imp.read_lef (stream, layout, ld);
|
imp.read_lef (stream, layout, ld);
|
||||||
|
|
||||||
|
any_lef = true;
|
||||||
|
|
||||||
} else if (ex.test ("gds:")) {
|
} else if (ex.test ("gds:")) {
|
||||||
|
|
||||||
std::string fn = fn_path, f;
|
std::string fn = fn_path, f;
|
||||||
|
|
@ -116,6 +122,8 @@ static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const ch
|
||||||
lo.set_options (options);
|
lo.set_options (options);
|
||||||
reader.read (layout, lo);
|
reader.read (layout, lo);
|
||||||
|
|
||||||
|
any_def = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -128,6 +136,10 @@ static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const ch
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! any_def && any_lef) {
|
||||||
|
imp.finish_lef (layout);
|
||||||
|
}
|
||||||
|
|
||||||
ld.finish (layout);
|
ld.finish (layout);
|
||||||
|
|
||||||
// normalize the layout by writing to OASIS and reading from ..
|
// normalize the layout by writing to OASIS and reading from ..
|
||||||
|
|
@ -198,7 +210,8 @@ TEST(1)
|
||||||
|
|
||||||
TEST(2)
|
TEST(2)
|
||||||
{
|
{
|
||||||
run_test (_this, "lef2", "lef:in.lef", "au.oas.gz", default_options ());
|
// Also tests ability of plugin to properly read LEF
|
||||||
|
run_test (_this, "lef2", "read:in.lef", "au.oas.gz", default_options ());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(3)
|
TEST(3)
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue