diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 383f628ca..54c97fbb2 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -359,17 +359,831 @@ DEFImporter::read_blockages (db::Layout &layout, db::Cell &design, double scale) } } +void +DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool specialnets) +{ + while (test ("-")) { + + std::string net = get (); + std::string nondefaultrule; + std::string stored_netname, stored_nondefaultrule; + std::string taperrule; + bool in_subnet = false; + + db::properties_id_type prop_id = 0; + if (produce_net_props ()) { + db::PropertiesRepository::properties_set props; + props.insert (std::make_pair (net_prop_name_id (), tl::Variant (net))); + prop_id = layout.properties_repository ().properties_id (props); + } + + while (test ("(")) { + while (! test (")")) { + take (); + } + } + + while (test ("+")) { + + bool was_shield = false; + + if (! specialnets && test ("SUBNET")) { + + while (test ("(")) { + while (! test (")")) { + take (); + } + } + + if (! in_subnet) { + stored_netname = net; + stored_nondefaultrule = nondefaultrule; + in_subnet = true; + } + + } else if (! specialnets && test ("NONDEFAULTRULE")) { + + nondefaultrule = get (); + + } else if ((was_shield = test ("SHIELD")) == true || test ("NOSHIELD") || test ("ROUTED") || test ("FIXED") || test ("COVER")) { + + if (was_shield) { + take (); + } + + do { + + std::string ln = get (); + + taperrule.clear (); + const std::string *rulename = 0; + + std::pair w (0, 0); + if (specialnets) { + db::Coord n = db::coord_traits::rounded (get_double () * scale); + w = std::make_pair (n, n); + } + + const db::Polygon *style = 0; + + int sn = std::numeric_limits::max (); + + if (specialnets) { + + while (test ("+")) { + + if (test ("STYLE")) { + sn = get_long (); + } else if (test ("SHAPE")) { + take (); + } + + } + + } else { + + while (true) { + if (test ("TAPER")) { + taperrule.clear (); + rulename = &taperrule; + } else if (test ("TAPERRULE")) { + taperrule = get (); + rulename = &taperrule; + } else if (test ("STYLE")) { + sn = get_long (); + } else { + break; + } + } + + } + + if (! rulename) { + rulename = &nondefaultrule; + } + + std::pair def_ext (0, 0); + + if (! specialnets) { + w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); + def_ext = get_def_ext (ln, w, layout.dbu ()); + } + + std::map::const_iterator s = m_styles.find (sn); + if (s != m_styles.end ()) { + style = &s->second; + } + + std::vector > ext; + std::vector pts; + + double x = 0.0, y = 0.0; + + while (true) { + + if (test ("MASK")) { + // ignore mask spec + get_long (); + } + + if (test ("RECT")) { + + if (! test ("(")) { + error (tl::to_string (tr ("RECT routing specification not followed by coordinate list"))); + } + + // breaks wiring + pts.clear (); + + // rect spec + + double x1 = get_double (); + double y1 = get_double (); + double x2 = get_double (); + double y2 = get_double (); + + test (")"); + + std::pair dl = open_layer (layout, ln, Routing); + if (dl.first) { + + db::Box rect (db::Point (db::DPoint ((x + x1) * scale, (y + y1) * scale)), + db::Point (db::DPoint ((x + x2) * scale, (y + y2) * scale))); + + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (rect, prop_id)); + } else { + design.shapes (dl.second).insert (rect); + } + + } + + } else if (test ("VIRTUAL")) { + + // virtual specs simply create a new segment + pts.clear (); + + } else if (peek ("(")) { + + ext.clear (); + + while (peek ("(") || peek ("MASK")) { + + if (test ("MASK")) { + // ignore MASK spec + get_long (); + } + + if (! test ("(")) { + // We could have a via here: in that case we have swallowed MASK already, but + // since we don't do anything with that, this does not hurt for now. + break; + } + + if (! test ("*")) { + x = get_double (); + } + if (! test ("*")) { + y = get_double (); + } + pts.push_back (db::Point (db::DPoint (x * scale, y * scale))); + std::pair ee = def_ext; + if (! peek (")")) { + db::Coord e = db::coord_traits::rounded (get_double () * scale); + ee.first = ee.second = e; + } + ext.push_back (ee); + + test (")"); + + } + + if (pts.size () > 1) { + + std::pair dl = open_layer (layout, ln, Routing); + if (dl.first) { + + if (! style) { + + // Use the default style (octagon "pen" for non-manhattan segments, paths for + // horizontal/vertical segments). + // Manhattan paths are stitched together from two-point paths if they + + std::pair e = std::max (ext.front (), ext.back ()); + bool is_isotropic = (e.first == e.second && w.first == w.second); + bool was_path = false; + + std::vector::const_iterator pt = pts.begin (); + while (pt != pts.end ()) { + + std::vector::const_iterator pt0 = pt; + do { + ++pt; + } while (pt != pts.end () && is_isotropic && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())); + + if (pt - pt0 > 1 || pt0->x () == pt0[1].x () || pt0->y () == pt0[0].y()) { + + if (pt - pt0 == 1) { + ++pt; + } + + db::Coord wxy, wxy_perp, exy; + + if (pt0->x () == pt0 [1].x ()) { + wxy = w.second; + wxy_perp = w.first; + exy = e.second; + } else { + wxy = w.first; + wxy_perp = w.second; + exy = e.first; + } + + db::Path p (pt0, pt, wxy, pt0 == pts.begin () ? exy : (was_path ? wxy_perp / 2 : 0), pt == pts.end () ? exy : 0, false); + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + + if (pt == pts.end ()) { + break; + } + + --pt; + + was_path = true; + + } else { + + if (! is_isotropic) { + warn("Anisotropic wire widths not supported for diagonal wires"); + } + + db::Coord s = (w.first + 1) / 2; + db::Coord t = db::Coord (ceil (w.first * (M_SQRT2 - 1) / 2)); + + db::Point octagon[8] = { + db::Point (-s, t), + db::Point (-t, s), + db::Point (t, s), + db::Point (s, t), + db::Point (s, -t), + db::Point (t, -s), + db::Point (-t, -s), + db::Point (-s, -t) + }; + + db::Polygon k; + k.assign_hull (octagon, octagon + sizeof (octagon) / sizeof (octagon[0])); + + db::Polygon p = db::minkowsky_sum (k, db::Edge (*pt0, *pt)); + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + + was_path = false; + + } + + } + + } else { + + for (size_t i = 0; i < pts.size () - 1; ++i) { + db::Polygon p = db::minkowsky_sum (*style, db::Edge (pts [i], pts [i + 1])); + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + } + + } + + } + + } + + } else if (! peek ("NEW") && ! peek ("+") && ! peek ("-") && ! peek (";")) { + + // indicates a via + std::string vn = get (); + db::FTrans ft = get_orient (true /*optional*/); + + db::Coord dx = 0, dy = 0; + long nx = 1, ny = 1; + + if (specialnets && test ("DO")) { + + nx = std::max (0l, get_long ()); + test ("BY"); + ny = std::max (0l, get_long ()); + test ("STEP"); + dx = db::coord_traits::rounded (get_double () * scale); + dy = db::coord_traits::rounded (get_double () * scale); + + if (nx < 0) { + dx = -dx; + nx = -nx; + } + if (ny < 0) { + dy = -dy; + ny = -ny; + } + + } + + std::map::const_iterator vd = m_via_desc.find (vn); + if (vd != m_via_desc.end () && ! pts.empty ()) { + if (nx <= 1 && ny <= 1) { + design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())))); + } else { + design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())), db::Vector (dx, 0), db::Vector (0, dy), (unsigned long) nx, (unsigned long) ny)); + } + if (ln == vd->second.m1) { + ln = vd->second.m2; + } else if (ln == vd->second.m2) { + ln = vd->second.m1; + } + } + + if (! specialnets) { + w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); + def_ext = get_def_ext (ln, w, layout.dbu ()); + } + + // continue a segment with the current point and the new layer + if (pts.size () > 1) { + pts.erase (pts.begin (), pts.end () - 1); + } + + } else { + break; + } + + } + + } while (test ("NEW")); + + if (in_subnet) { + in_subnet = false; + net = stored_netname; + stored_netname.clear (); + nondefaultrule = stored_nondefaultrule; + stored_nondefaultrule.clear (); + } + + } else if (test ("POLYGON")) { + + std::string ln = get (); + + db::Polygon p; + read_polygon (p, scale); + + std::pair dl = open_layer (layout, ln, Routing); + if (dl.first) { + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + } + + } else if (test ("RECT")) { + + std::string ln = get (); + + db::Polygon p; + read_rect (p, scale); + + std::pair dl = open_layer (layout, ln, Routing); + if (dl.first) { + if (prop_id != 0) { + design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); + } else { + design.shapes (dl.second).insert (p); + } + } + + } else { + while (! peek ("+") && ! peek ("-") && ! peek (";")) { + take (); + } + } + + } + + expect (";"); + + } +} + +void +DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) +{ + while (test ("-")) { + + std::string n = get (); + ViaDesc &vd = m_via_desc.insert (std::make_pair (n, ViaDesc ())).first->second; + + // produce a cell for vias + std::string cellname = "VIA_" + n; + db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ())); + vd.cell = &cell; + + bool has_via_rule = false; + + db::Vector cutsize, cutspacing; + db::Vector be, te; + db::Vector bo, to; + db::Point offset; + int rows = 1, columns = 1; + std::string pattern; + + std::map > geometry; + std::vector *top = 0, *cut = 0, *bottom = 0; + + while (test ("+")) { + + double x, y; + + if (test ("VIARULE")) { + + has_via_rule = true; + take (); + + } else if (test ("CUTSIZE")) { + + x = get_double (); + y = get_double (); + cutsize = db::Vector (db::DVector (x * scale, y * scale)); + + } else if (test ("CUTSPACING")) { + + x = get_double (); + y = get_double (); + cutspacing = db::Vector (db::DVector (x * scale, y * scale)); + + } else if (test ("ORIGIN")) { + + x = get_double (); + y = get_double (); + offset = db::Point (db::DPoint (x * scale, y * scale)); + + } else if (test ("ENCLOSURE")) { + + x = get_double (); + y = get_double (); + be = db::Vector (db::DVector (x * scale, y * scale)); + + x = get_double (); + y = get_double (); + te = db::Vector (db::DVector (x * scale, y * scale)); + + } else if (test ("OFFSET")) { + + x = get_double (); + y = get_double (); + bo = db::Vector (db::DVector (x * scale, y * scale)); + + x = get_double (); + y = get_double (); + to = db::Vector (db::DVector (x * scale, y * scale)); + + } else if (test ("ROWCOL")) { + + rows = get_long (); + columns = get_long (); + + } else if (test ("PATTERN")) { + + pattern = get (); + + } else if (test ("LAYERS")) { + + std::string bn = get (); + std::string cn = get (); + std::string tn = get (); + + bottom = &geometry.insert (std::make_pair (bn, std::vector ())).first->second; + cut = &geometry.insert (std::make_pair (cn, std::vector ())).first->second; + top = &geometry.insert (std::make_pair (tn, std::vector ())).first->second; + + vd.m1 = bn; + vd.m2 = tn; + + } else if (test ("POLYGON")) { + + std::string ln = get (); + + if (test ("+")) { + expect ("MASK"); + get_long (); + } + + std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; + polygons.push_back (db::Polygon ()); + read_polygon (polygons.back (), scale); + + } else if (test ("RECT")) { + + std::string ln = get (); + + if (test ("+")) { + expect ("MASK"); + get_long (); + } + + std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; + polygons.push_back (db::Polygon ()); + read_rect (polygons.back (), scale); + + } + + } + + if (vd.m1.empty () && vd.m2.empty ()) { + + // analyze the layers to find the metals + std::vector routing_layers; + for (std::map >::const_iterator b = geometry.begin (); b != geometry.end (); ++b) { + if (m_lef_importer.is_routing_layer (b->first)) { + routing_layers.push_back (b->first); + } + } + + if (routing_layers.size () == 2) { + vd.m1 = routing_layers[0]; + vd.m2 = routing_layers[1]; + } else { + warn ("Can't determine routing layers for via: " + n); + } + + } + + test (";"); + + if (has_via_rule && top && cut && bottom) { + create_generated_via (*bottom, *cut, *top, + cutsize, cutspacing, be, te, bo, to, offset, rows, columns, pattern); + } + + for (std::map >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) { + std::pair dl = open_layer (layout, g->first, ViaGeometry); + if (dl.first) { + for (std::vector::const_iterator p = g->second.begin (); p != g->second.end (); ++p) { + cell.shapes (dl.second).insert (*p); + } + } + } + + } +} + +void +DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale) +{ + while (test ("-")) { + + take (); // pin name + + std::string net; + std::string dir; + std::map > geometry; + db::Trans trans; + + while (test ("+")) { + + bool flush = false; + + if (test ("DIRECTION")) { + dir = get (); + } else if (test ("NET")) { + net = get (); + } else if (test ("LAYER")) { + + std::string ln = get (); + + while (test ("DESIGNRULEWIDTH") || test ("SPACING")) { + take (); + } + + double x, y; + + test ("("); + x = get_double (); + y = get_double (); + db::Point pt1 = db::Point (db::DPoint (x * scale, y * scale)); + test (")"); + + test ("("); + x = get_double (); + y = get_double (); + db::Point pt2 = db::Point (db::DPoint (x * scale, y * scale)); + test (")"); + + geometry.insert (std::make_pair (ln, std::vector ())).first->second.push_back (db::Polygon (db::Box (pt1, pt2))); + + } else if (test ("POLYGON")) { + + std::string ln = get (); + + while (test ("DESIGNRULEWIDTH") || test ("SPACING")) { + take (); + } + + std::vector points; + + double x = 0.0, y = 0.0; + + while (! test ("+") && ! test (";")) { + + test ("("); + if (! test ("*")) { + x = get_double (); + } + if (! test ("*")) { + y = get_double (); + } + points.push_back (db::Point (db::DPoint (x * scale, y * scale))); + test (")"); + + } + + std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; + polygons.push_back (db::Polygon ()); + polygons.back ().assign_hull (points.begin (), points.end ()); + + } else if (test ("PLACED") || test ("FIXED") || test ("COVER")) { + + test ("("); + double x = get_double (); + double y = get_double (); + db::Vector d = db::Vector (db::DVector (x * scale, y * scale)); + test (")"); + + db::FTrans ft = get_orient (false /*mandatory*/); + trans = db::Trans (ft.rot (), d); + + } else if (test ("PORT")) { + + flush = true; + + } else { + while (! peek ("+") && ! peek ("-") && ! peek (";")) { + take (); + } + } + + if (flush || ! peek ("+")) { + + // TODO: put a label on every single object? + std::string label = net; + /* don't add the direction currently, a name is sufficient + if (! dir.empty ()) { + label += ":"; + label += dir; + } + */ + + // Produce geometry collected so far + for (std::map >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) { + + std::pair dl = open_layer (layout, g->first, Pins); + if (dl.first) { + + 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::vector::const_iterator p = g->second.begin (); p != g->second.end (); ++p) { + db::Polygon pt = p->transformed (trans); + if (prop_id == 0) { + design.shapes (dl.second).insert (pt); + } else { + design.shapes (dl.second).insert (db::PolygonWithProperties (pt, prop_id)); + } + } + + } + + dl = open_layer (layout, g->first, Label); + if (dl.first) { + db::Box bbox; + if (! g->second.empty ()) { + bbox = g->second.back ().box ().transformed (trans); + } + design.shapes (dl.second).insert (db::Text (label.c_str (), db::Trans (db::Vector (bbox.center ())))); + } + + } + + geometry.clear (); + trans = db::Trans (); + + } + + } + + expect (";"); + + } +} + +void +DEFImporter::read_styles (double scale) +{ + while (test ("-")) { + + test ("STYLE"); + + int sn = get_long (); + + std::vector points; + + double x = 0.0, y = 0.0; + + while (! test (";")) { + + test ("("); + if (! test ("*")) { + x = get_double (); + } + if (! test ("*")) { + y = get_double (); + } + points.push_back (db::Point (db::DPoint (x * scale, y * scale))); + test (")"); + + } + + m_styles.insert (std::make_pair (sn, db::Polygon ())).first->second.assign_hull (points.begin (), points.end ()); + + } +} + +void +DEFImporter::read_components (std::list > &instances, double scale) +{ + while (test ("-")) { + + std::string inst_name = get (); + std::string model = get (); + + db::Cell *cell = m_lef_importer.macro_by_name (model); + + while (test ("+")) { + + if (test ("PLACED") || test ("FIXED") || test ("COVER")) { + + test ("("); + double x = get_double (); + double y = get_double (); + db::Point pt = db::Point (db::DPoint (x * scale, y * scale)); + test (")"); + + db::FTrans ft = get_orient (false /*mandatory*/); + db::Vector d = pt - m_lef_importer.macro_bbox_by_name (model).transformed (ft).lower_left (); + + if (cell) { + db::CellInstArray inst (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), d)); + instances.push_back (std::make_pair (inst_name, inst)); + } else { + warn (tl::to_string (tr ("Macro not found in LEF file: ")) + model); + } + + } else { + while (! peek ("+") && ! peek ("-") && ! peek (";")) { + take (); + } + } + + } + + expect (";"); + + } +} + void DEFImporter::do_read (db::Layout &layout) { double dbu_mic = 1000.0; double scale = 1.0 / (dbu_mic * layout.dbu ()); - std::map styles; - std::map via_desc = m_lef_importer.vias (); + std::map > regions; std::list groups; std::list > instances; + m_via_desc = m_lef_importer.vias (); + m_styles.clear (); + db::Cell &design = layout.cell (layout.add_cell ("TOP")); while (! at_end ()) { @@ -491,429 +1305,13 @@ DEFImporter::do_read (db::Layout &layout) get_long (); expect (";"); - while (test ("-")) { + read_nets (layout, design, scale, specialnets); - std::string net = get (); - std::string nondefaultrule; - std::string stored_netname, stored_nondefaultrule; - std::string taperrule; - bool in_subnet = false; - - db::properties_id_type prop_id = 0; - if (produce_net_props ()) { - db::PropertiesRepository::properties_set props; - props.insert (std::make_pair (net_prop_name_id (), tl::Variant (net))); - prop_id = layout.properties_repository ().properties_id (props); - } - - while (test ("(")) { - while (! test (")")) { - take (); - } - } - - while (test ("+")) { - - bool was_shield = false; - - if (! specialnets && test ("SUBNET")) { - - while (test ("(")) { - while (! test (")")) { - take (); - } - } - - if (! in_subnet) { - stored_netname = net; - stored_nondefaultrule = nondefaultrule; - in_subnet = true; - } - - } else if (! specialnets && test ("NONDEFAULTRULE")) { - - nondefaultrule = get (); - - } else if ((was_shield = test ("SHIELD")) == true || test ("NOSHIELD") || test ("ROUTED") || test ("FIXED") || test ("COVER")) { - - if (was_shield) { - take (); - } - - do { - - std::string ln = get (); - - taperrule.clear (); - const std::string *rulename = 0; - - std::pair w (0, 0); - if (specialnets) { - db::Coord n = db::coord_traits::rounded (get_double () * scale); - w = std::make_pair (n, n); - } - - const db::Polygon *style = 0; - - int sn = std::numeric_limits::max (); - - if (specialnets) { - - while (test ("+")) { - - if (test ("STYLE")) { - sn = get_long (); - } else if (test ("SHAPE")) { - take (); - } - - } - - } else { - - while (true) { - if (test ("TAPER")) { - taperrule.clear (); - rulename = &taperrule; - } else if (test ("TAPERRULE")) { - taperrule = get (); - rulename = &taperrule; - } else if (test ("STYLE")) { - sn = get_long (); - } else { - break; - } - } - - } - - if (! rulename) { - rulename = &nondefaultrule; - } - - std::pair def_ext (0, 0); - - if (! specialnets) { - w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); - def_ext = get_def_ext (ln, w, layout.dbu ()); - } - - std::map::const_iterator s = styles.find (sn); - if (s != styles.end ()) { - style = &s->second; - } - - std::vector > ext; - std::vector pts; - - double x = 0.0, y = 0.0; - - while (true) { - - if (test ("MASK")) { - // ignore mask spec - get_long (); - } - - if (test ("RECT")) { - - if (! test ("(")) { - error (tl::to_string (tr ("RECT routing specification not followed by coordinate list"))); - } - - // breaks wiring - pts.clear (); - - // rect spec - - double x1 = get_double (); - double y1 = get_double (); - double x2 = get_double (); - double y2 = get_double (); - - test (")"); - - std::pair dl = open_layer (layout, ln, Routing); - if (dl.first) { - - db::Box rect (db::Point (db::DPoint ((x + x1) * scale, (y + y1) * scale)), - db::Point (db::DPoint ((x + x2) * scale, (y + y2) * scale))); - - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (rect, prop_id)); - } else { - design.shapes (dl.second).insert (rect); - } - - } - - } else if (test ("VIRTUAL")) { - - // virtual specs simply create a new segment - pts.clear (); - - } else if (peek ("(")) { - - ext.clear (); - - while (peek ("(") || peek ("MASK")) { - - if (test ("MASK")) { - // ignore MASK spec - get_long (); - } - - if (! test ("(")) { - // We could have a via here: in that case we have swallowed MASK already, but - // since we don't do anything with that, this does not hurt for now. - break; - } - - if (! test ("*")) { - x = get_double (); - } - if (! test ("*")) { - y = get_double (); - } - pts.push_back (db::Point (db::DPoint (x * scale, y * scale))); - std::pair ee = def_ext; - if (! peek (")")) { - db::Coord e = db::coord_traits::rounded (get_double () * scale); - ee.first = ee.second = e; - } - ext.push_back (ee); - - test (")"); - - } - - if (pts.size () > 1) { - - std::pair dl = open_layer (layout, ln, Routing); - if (dl.first) { - - if (! style) { - - // Use the default style (octagon "pen" for non-manhattan segments, paths for - // horizontal/vertical segments). - // Manhattan paths are stitched together from two-point paths if they - - std::pair e = std::max (ext.front (), ext.back ()); - bool is_isotropic = (e.first == e.second && w.first == w.second); - bool was_path = false; - - std::vector::const_iterator pt = pts.begin (); - while (pt != pts.end ()) { - - std::vector::const_iterator pt0 = pt; - do { - ++pt; - } while (pt != pts.end () && is_isotropic && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())); - - if (pt - pt0 > 1 || pt0->x () == pt0[1].x () || pt0->y () == pt0[0].y()) { - - if (pt - pt0 == 1) { - ++pt; - } - - db::Coord wxy, wxy_perp, exy; - - if (pt0->x () == pt0 [1].x ()) { - wxy = w.second; - wxy_perp = w.first; - exy = e.second; - } else { - wxy = w.first; - wxy_perp = w.second; - exy = e.first; - } - - db::Path p (pt0, pt, wxy, pt0 == pts.begin () ? exy : (was_path ? wxy_perp / 2 : 0), pt == pts.end () ? exy : 0, false); - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - - if (pt == pts.end ()) { - break; - } - - --pt; - - was_path = true; - - } else { - - if (! is_isotropic) { - warn("Anisotropic wire widths not supported for diagonal wires"); - } - - db::Coord s = (w.first + 1) / 2; - db::Coord t = db::Coord (ceil (w.first * (M_SQRT2 - 1) / 2)); - - db::Point octagon[8] = { - db::Point (-s, t), - db::Point (-t, s), - db::Point (t, s), - db::Point (s, t), - db::Point (s, -t), - db::Point (t, -s), - db::Point (-t, -s), - db::Point (-s, -t) - }; - - db::Polygon k; - k.assign_hull (octagon, octagon + sizeof (octagon) / sizeof (octagon[0])); - - db::Polygon p = db::minkowsky_sum (k, db::Edge (*pt0, *pt)); - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - - was_path = false; - - } - - } - - } else { - - for (size_t i = 0; i < pts.size () - 1; ++i) { - db::Polygon p = db::minkowsky_sum (*style, db::Edge (pts [i], pts [i + 1])); - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - } - - } - - } - - } - - } else if (! peek ("NEW") && ! peek ("+") && ! peek ("-") && ! peek (";")) { - - // indicates a via - std::string vn = get (); - db::FTrans ft = get_orient (true /*optional*/); - - db::Coord dx = 0, dy = 0; - long nx = 1, ny = 1; - - if (specialnets && test ("DO")) { - - nx = std::max (0l, get_long ()); - test ("BY"); - ny = std::max (0l, get_long ()); - test ("STEP"); - dx = db::coord_traits::rounded (get_double () * scale); - dy = db::coord_traits::rounded (get_double () * scale); - - if (nx < 0) { - dx = -dx; - nx = -nx; - } - if (ny < 0) { - dy = -dy; - ny = -ny; - } - - } - - std::map::const_iterator vd = via_desc.find (vn); - if (vd != via_desc.end () && ! pts.empty ()) { - if (nx <= 1 && ny <= 1) { - design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())))); - } else { - design.insert (db::CellInstArray (db::CellInst (vd->second.cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())), db::Vector (dx, 0), db::Vector (0, dy), (unsigned long) nx, (unsigned long) ny)); - } - if (ln == vd->second.m1) { - ln = vd->second.m2; - } else if (ln == vd->second.m2) { - ln = vd->second.m1; - } - } - - if (! specialnets) { - w = get_wire_width_for_rule (*rulename, ln, layout.dbu ()); - def_ext = get_def_ext (ln, w, layout.dbu ()); - } - - // continue a segment with the current point and the new layer - if (pts.size () > 1) { - pts.erase (pts.begin (), pts.end () - 1); - } - - } else { - break; - } - - } - - } while (test ("NEW")); - - if (in_subnet) { - in_subnet = false; - net = stored_netname; - stored_netname.clear (); - nondefaultrule = stored_nondefaultrule; - stored_nondefaultrule.clear (); - } - - } else if (test ("POLYGON")) { - - std::string ln = get (); - - db::Polygon p; - read_polygon (p, scale); - - std::pair dl = open_layer (layout, ln, Routing); - if (dl.first) { - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - } - - } else if (test ("RECT")) { - - std::string ln = get (); - - db::Polygon p; - read_rect (p, scale); - - std::pair dl = open_layer (layout, ln, Routing); - if (dl.first) { - if (prop_id != 0) { - design.shapes (dl.second).insert (db::object_with_properties (p, prop_id)); - } else { - design.shapes (dl.second).insert (p); - } - } - - } else { - while (! peek ("+") && ! peek ("-") && ! peek (";")) { - take (); - } - } - - } - - expect (";"); - - } - - test ("END"); + expect ("END"); if (specialnets) { - test ("SPECIALNETS"); + expect ("SPECIALNETS"); } else { - test ("NETS"); + expect ("NETS"); } } else if (test ("VIAS")) { @@ -921,163 +1319,7 @@ DEFImporter::do_read (db::Layout &layout) get_long (); expect (";"); - while (test ("-")) { - - std::string n = get (); - ViaDesc &vd = via_desc.insert (std::make_pair (n, ViaDesc ())).first->second; - - // produce a cell for vias - std::string cellname = "VIA_" + n; - db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ())); - vd.cell = &cell; - - bool has_via_rule = false; - - db::Vector cutsize, cutspacing; - db::Vector be, te; - db::Vector bo, to; - db::Point offset; - int rows = 1, columns = 1; - std::string pattern; - - std::map > geometry; - std::vector *top = 0, *cut = 0, *bottom = 0; - - while (test ("+")) { - - double x, y; - - if (test ("VIARULE")) { - - has_via_rule = true; - take (); - - } else if (test ("CUTSIZE")) { - - x = get_double (); - y = get_double (); - cutsize = db::Vector (db::DVector (x * scale, y * scale)); - - } else if (test ("CUTSPACING")) { - - x = get_double (); - y = get_double (); - cutspacing = db::Vector (db::DVector (x * scale, y * scale)); - - } else if (test ("ORIGIN")) { - - x = get_double (); - y = get_double (); - offset = db::Point (db::DPoint (x * scale, y * scale)); - - } else if (test ("ENCLOSURE")) { - - x = get_double (); - y = get_double (); - be = db::Vector (db::DVector (x * scale, y * scale)); - - x = get_double (); - y = get_double (); - te = db::Vector (db::DVector (x * scale, y * scale)); - - } else if (test ("OFFSET")) { - - x = get_double (); - y = get_double (); - bo = db::Vector (db::DVector (x * scale, y * scale)); - - x = get_double (); - y = get_double (); - to = db::Vector (db::DVector (x * scale, y * scale)); - - } else if (test ("ROWCOL")) { - - rows = get_long (); - columns = get_long (); - - } else if (test ("PATTERN")) { - - pattern = get (); - - } else if (test ("LAYERS")) { - - std::string bn = get (); - std::string cn = get (); - std::string tn = get (); - - bottom = &geometry.insert (std::make_pair (bn, std::vector ())).first->second; - cut = &geometry.insert (std::make_pair (cn, std::vector ())).first->second; - top = &geometry.insert (std::make_pair (tn, std::vector ())).first->second; - - vd.m1 = bn; - vd.m2 = tn; - - } else if (test ("POLYGON")) { - - std::string ln = get (); - - if (test ("+")) { - expect ("MASK"); - get_long (); - } - - std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; - polygons.push_back (db::Polygon ()); - read_polygon (polygons.back (), scale); - - } else if (test ("RECT")) { - - std::string ln = get (); - - if (test ("+")) { - expect ("MASK"); - get_long (); - } - - std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; - polygons.push_back (db::Polygon ()); - read_rect (polygons.back (), scale); - - } - - } - - if (vd.m1.empty () && vd.m2.empty ()) { - - // analyze the layers to find the metals - std::vector routing_layers; - for (std::map >::const_iterator b = geometry.begin (); b != geometry.end (); ++b) { - if (m_lef_importer.is_routing_layer (b->first)) { - routing_layers.push_back (b->first); - } - } - - if (routing_layers.size () == 2) { - vd.m1 = routing_layers[0]; - vd.m2 = routing_layers[1]; - } else { - warn ("Can't determine routing layers for via: " + n); - } - - } - - test (";"); - - if (has_via_rule && top && cut && bottom) { - create_generated_via (*bottom, *cut, *top, - cutsize, cutspacing, be, te, bo, to, offset, rows, columns, pattern); - } - - for (std::map >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) { - std::pair dl = open_layer (layout, g->first, ViaGeometry); - if (dl.first) { - for (std::vector::const_iterator p = g->second.begin (); p != g->second.end (); ++p) { - cell.shapes (dl.second).insert (*p); - } - } - } - - } + read_vias (layout, design, scale); expect ("END"); expect ("VIAS"); @@ -1087,80 +1329,17 @@ DEFImporter::do_read (db::Layout &layout) get_long (); expect (";"); - while (test ("-")) { + read_styles (scale); - test ("STYLE"); - - int sn = get_long (); - - std::vector points; - - double x = 0.0, y = 0.0; - - while (! test (";")) { - - test ("("); - if (! test ("*")) { - x = get_double (); - } - if (! test ("*")) { - y = get_double (); - } - points.push_back (db::Point (db::DPoint (x * scale, y * scale))); - test (")"); - - } - - styles.insert (std::make_pair (sn, db::Polygon ())).first->second.assign_hull (points.begin (), points.end ()); - - } - - test ("END"); - test ("STYLES"); + expect ("END"); + expect ("STYLES"); } else if (test ("COMPONENTS")) { get_long (); expect (";"); - while (test ("-")) { - - std::string inst_name = get (); - std::string model = get (); - - db::Cell *cell = m_lef_importer.macro_by_name (model); - - while (test ("+")) { - - if (test ("PLACED") || test ("FIXED") || test ("COVER")) { - - test ("("); - double x = get_double (); - double y = get_double (); - db::Point pt = db::Point (db::DPoint (x * scale, y * scale)); - test (")"); - - db::FTrans ft = get_orient (false /*mandatory*/); - db::Vector d = pt - m_lef_importer.macro_bbox_by_name (model).transformed (ft).lower_left (); - - if (cell) { - db::CellInstArray inst (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), d)); - instances.push_back (std::make_pair (inst_name, inst)); - } else { - warn (tl::to_string (tr ("Macro not found in LEF file: ")) + model); - } - - } else { - while (! peek ("+") && ! peek ("-") && ! peek (";")) { - take (); - } - } - - } - - expect (";"); - - } + read_components (instances, scale); expect ("END"); expect ("COMPONENTS"); @@ -1170,154 +1349,7 @@ DEFImporter::do_read (db::Layout &layout) get_long (); expect (";"); - while (test ("-")) { - - take (); // pin name - - std::string net; - std::string dir; - std::map > geometry; - db::Trans trans; - - while (test ("+")) { - - bool flush = false; - - if (test ("DIRECTION")) { - dir = get (); - } else if (test ("NET")) { - net = get (); - } else if (test ("LAYER")) { - - std::string ln = get (); - - while (test ("DESIGNRULEWIDTH") || test ("SPACING")) { - take (); - } - - double x, y; - - test ("("); - x = get_double (); - y = get_double (); - db::Point pt1 = db::Point (db::DPoint (x * scale, y * scale)); - test (")"); - - test ("("); - x = get_double (); - y = get_double (); - db::Point pt2 = db::Point (db::DPoint (x * scale, y * scale)); - test (")"); - - geometry.insert (std::make_pair (ln, std::vector ())).first->second.push_back (db::Polygon (db::Box (pt1, pt2))); - - } else if (test ("POLYGON")) { - - std::string ln = get (); - - while (test ("DESIGNRULEWIDTH") || test ("SPACING")) { - take (); - } - - std::vector points; - - double x = 0.0, y = 0.0; - - while (! test ("+") && ! test (";")) { - - test ("("); - if (! test ("*")) { - x = get_double (); - } - if (! test ("*")) { - y = get_double (); - } - points.push_back (db::Point (db::DPoint (x * scale, y * scale))); - test (")"); - - } - - std::vector &polygons = geometry.insert (std::make_pair (ln, std::vector ())).first->second; - polygons.push_back (db::Polygon ()); - polygons.back ().assign_hull (points.begin (), points.end ()); - - } else if (test ("PLACED") || test ("FIXED") || test ("COVER")) { - - test ("("); - double x = get_double (); - double y = get_double (); - db::Vector d = db::Vector (db::DVector (x * scale, y * scale)); - test (")"); - - db::FTrans ft = get_orient (false /*mandatory*/); - trans = db::Trans (ft.rot (), d); - - } else if (test ("PORT")) { - - flush = true; - - } else { - while (! peek ("+") && ! peek ("-") && ! peek (";")) { - take (); - } - } - - if (flush || ! peek ("+")) { - - // TODO: put a label on every single object? - std::string label = net; - /* don't add the direction currently, a name is sufficient - if (! dir.empty ()) { - label += ":"; - label += dir; - } - */ - - // Produce geometry collected so far - for (std::map >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) { - - std::pair dl = open_layer (layout, g->first, Pins); - if (dl.first) { - - 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::vector::const_iterator p = g->second.begin (); p != g->second.end (); ++p) { - db::Polygon pt = p->transformed (trans); - if (prop_id == 0) { - design.shapes (dl.second).insert (pt); - } else { - design.shapes (dl.second).insert (db::PolygonWithProperties (pt, prop_id)); - } - } - - } - - dl = open_layer (layout, g->first, Label); - if (dl.first) { - db::Box bbox; - if (! g->second.empty ()) { - bbox = g->second.back ().box ().transformed (trans); - } - design.shapes (dl.second).insert (db::Text (label.c_str (), db::Trans (db::Vector (bbox.center ())))); - } - - } - - geometry.clear (); - trans = db::Trans (); - - } - - } - - expect (";"); - - } + read_pins (layout, design, scale); expect ("END"); expect ("PINS"); diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h index 0ac133de8..13a8f90cb 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.h @@ -64,6 +64,8 @@ protected: private: LEFImporter m_lef_importer; std::map > m_nondefault_widths; + std::map m_via_desc; + std::map m_styles; db::FTrans get_orient (bool optional); void read_polygon (db::Polygon &poly, double scale); @@ -75,6 +77,11 @@ private: void read_regions (std::map > ®ions, double scale); void read_groups (std::list &groups, double scale); void read_blockages (db::Layout &layout, db::Cell &design, double scale); + void read_nets (db::Layout &layout, db::Cell &design, double scale, bool specialnets); + void read_vias (db::Layout &layout, db::Cell &design, double scale); + void read_pins (db::Layout &layout, db::Cell &design, double scale); + void read_styles (double scale); + void read_components (std::list > &instances, double scale); }; }