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:
Matthias Koefferlein 2020-08-23 01:29:10 +02:00
parent dcc99060fc
commit af7d8bba89
7 changed files with 140 additions and 80 deletions

View File

@ -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));
}
}

View File

@ -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);

View File

@ -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")));

View 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);
}
}
}

View File

@ -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 &macro_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);

View File

@ -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.