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);
|
||||
}
|
||||
|
||||
void
|
||||
DEFImporter::finish_lef (db::Layout &layout)
|
||||
{
|
||||
m_lef_importer.finish_lef (layout);
|
||||
}
|
||||
|
||||
void
|
||||
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;
|
||||
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 ("+")) {
|
||||
|
||||
if (test ("PLACED") || test ("FIXED") || test ("COVER")) {
|
||||
|
|
@ -1283,7 +1294,7 @@ DEFImporter::read_components (db::Layout &layout, std::list<std::pair<std::strin
|
|||
test (")");
|
||||
|
||||
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;
|
||||
|
||||
} else if (test ("MASKSHIFT")) {
|
||||
|
|
@ -1302,19 +1313,10 @@ DEFImporter::read_components (db::Layout &layout, std::list<std::pair<std::strin
|
|||
|
||||
if (is_placed) {
|
||||
|
||||
std::map<std::string, MacroDesc>::const_iterator m = m_lef_importer.macros ().find (model);
|
||||
if (m == m_lef_importer.macros ().end ()) {
|
||||
|
||||
warn (tl::to_string (tr ("Macro not found in LEF file: ")) + model);
|
||||
|
||||
} 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));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief Provided for test purposes
|
||||
*/
|
||||
void finish_lef (Layout &layout);
|
||||
|
||||
protected:
|
||||
void do_read (db::Layout &layout);
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@ private:
|
|||
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
|
||||
importer.read (m_stream, layout, state);
|
||||
|
||||
importer.finish_lef (layout);
|
||||
|
||||
} else {
|
||||
|
||||
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 (")");
|
||||
}
|
||||
|
||||
db::Coord iw = db::coord_traits<db::Coord>::rounded (w / dbu);
|
||||
db::Path p (points.begin (), points.end (), iw, iw / 2, iw / 2, false);
|
||||
if (lg) {
|
||||
|
||||
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) {
|
||||
db::Path pt = p.transformed (*t);
|
||||
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 ();
|
||||
std::vector<db::Trans> ti = get_iteration (dbu);
|
||||
|
||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||
db::Path pt = p.transformed (*t);
|
||||
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 (")");
|
||||
}
|
||||
|
||||
db::Polygon p;
|
||||
p.assign_hull (points.begin (), points.end ());
|
||||
if (lg) {
|
||||
|
||||
if (iterate) {
|
||||
db::Polygon p;
|
||||
p.assign_hull (points.begin (), points.end ());
|
||||
|
||||
std::vector<db::Trans> ti = get_iteration (dbu);
|
||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||
db::Polygon pt = p.transformed (*t);
|
||||
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 ();
|
||||
if (iterate) {
|
||||
|
||||
std::vector<db::Trans> ti = get_iteration (dbu);
|
||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||
db::Polygon pt = p.transformed (*t);
|
||||
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) {
|
||||
db::Box bt = b.transformed (*t);
|
||||
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;
|
||||
std::vector<db::Trans> ti = get_iteration (dbu);
|
||||
|
||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||
db::Box bt = b.transformed (*t);
|
||||
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 ();
|
||||
|
||||
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 (";");
|
||||
|
|
@ -850,18 +866,24 @@ LEFImporter::read_macro (Layout &layout)
|
|||
}
|
||||
*/
|
||||
|
||||
db::properties_id_type prop_id = 0;
|
||||
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);
|
||||
}
|
||||
if (reader_state ()->tech_comp ()->produce_lef_pins ()) {
|
||||
|
||||
std::map <std::string, db::Box> boxes_for_labels;
|
||||
read_geometries (mg, layout.dbu (), LEFPins, &boxes_for_labels, prop_id);
|
||||
db::properties_id_type prop_id = 0;
|
||||
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) {
|
||||
mg->add_text (b->first, Label, db::Text (label.c_str (), db::Trans (b->second.center () - db::Point ())), 0, 0);
|
||||
std::map <std::string, db::Box> boxes_for_labels;
|
||||
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");
|
||||
|
|
@ -907,7 +929,12 @@ LEFImporter::read_macro (Layout &layout)
|
|||
|
||||
} 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");
|
||||
|
||||
} 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 ();
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
|
|
@ -128,6 +123,14 @@ public:
|
|||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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::DEFImporter imp;
|
||||
bool any_def = false;
|
||||
bool any_lef = false;
|
||||
|
||||
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);
|
||||
imp.read (stream, layout, ld);
|
||||
|
||||
any_def = true;
|
||||
|
||||
} else if (ex.test ("lef:")) {
|
||||
|
||||
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);
|
||||
imp.read_lef (stream, layout, ld);
|
||||
|
||||
any_lef = true;
|
||||
|
||||
} else if (ex.test ("gds:")) {
|
||||
|
||||
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);
|
||||
reader.read (layout, lo);
|
||||
|
||||
any_def = true;
|
||||
|
||||
} else {
|
||||
|
||||
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);
|
||||
|
||||
// normalize the layout by writing to OASIS and reading from ..
|
||||
|
|
@ -198,7 +210,8 @@ TEST(1)
|
|||
|
||||
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)
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue