mirror of https://github.com/KLayout/klayout.git
Tried to implement MINWIDTH .. WRONGDIRECTION in LEF58_MINWIDTH property
This commit is contained in:
parent
bcaf28c94c
commit
4a24b727d5
|
|
@ -136,10 +136,10 @@ struct Group
|
|||
std::vector<tl::GlobPattern> comp_match;
|
||||
};
|
||||
|
||||
db::Coord
|
||||
std::pair<db::Coord, db::Coord>
|
||||
DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::string &ln, double dbu)
|
||||
{
|
||||
double w = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_width (ln, rulename, 0.0) / dbu);
|
||||
db::Coord w = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_width (ln, rulename, 0.0) / dbu);
|
||||
|
||||
// try to find local nondefault rule
|
||||
if (! rulename.empty ()) {
|
||||
|
|
@ -152,7 +152,34 @@ DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::st
|
|||
}
|
||||
}
|
||||
|
||||
return w;
|
||||
std::pair<double, double> min_wxy = m_lef_importer.min_layer_width (ln);
|
||||
db::Coord min_wx = db::coord_traits<db::Coord>::rounded (min_wxy.first / dbu);
|
||||
db::Coord min_wy = db::coord_traits<db::Coord>::rounded (min_wxy.second / dbu);
|
||||
|
||||
return std::make_pair (std::max (w, min_wx), std::max (w, min_wy));
|
||||
}
|
||||
|
||||
std::pair<db::Coord, db::Coord>
|
||||
DEFImporter::get_def_ext (const std::string &ln, const std::pair<db::Coord, db::Coord> &wxy, double dbu)
|
||||
{
|
||||
if (wxy.first == wxy.second) {
|
||||
db::Coord de = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_ext (ln, wxy.first * 0.5 * dbu) / dbu);
|
||||
return std::make_pair (de, de);
|
||||
} else {
|
||||
#if 0
|
||||
// This implementation picks the default extension according to the real width
|
||||
// NOTE: the swapping of x and y for the default extension is intended. For horizontal lines, the
|
||||
// extension is in x direction but corresponds to a wire width of a vertical wire and vice versa.
|
||||
db::Coord dex = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_ext (ln, wxy.second * 0.5 * dbu) / dbu);
|
||||
db::Coord dey = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_ext (ln, wxy.first * 0.5 * dbu) / dbu);
|
||||
return std::make_pair (dex, dey);
|
||||
#else
|
||||
// This implementation picks the default extension according to the specified wire width (which is the minimum
|
||||
// of wx and wy)
|
||||
db::Coord de = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_ext (ln, std::min (wxy.first, wxy.second) * 0.5 * dbu) / dbu);
|
||||
return std::make_pair (de, de);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -501,9 +528,10 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
taperrule.clear ();
|
||||
const std::string *rulename = 0;
|
||||
|
||||
db::Coord w = 0;
|
||||
std::pair<db::Coord, db::Coord> w (0, 0);
|
||||
if (specialnets) {
|
||||
w = db::coord_traits<db::Coord>::rounded (get_double () * scale);
|
||||
db::Coord n = db::coord_traits<db::Coord>::rounded (get_double () * scale);
|
||||
w = std::make_pair (n, n);
|
||||
}
|
||||
|
||||
const db::Polygon *style = 0;
|
||||
|
|
@ -544,11 +572,11 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
rulename = &nondefaultrule;
|
||||
}
|
||||
|
||||
db::Coord def_ext = 0;
|
||||
std::pair<db::Coord, db::Coord> def_ext (0, 0);
|
||||
|
||||
if (! specialnets) {
|
||||
w = get_wire_width_for_rule (*rulename, ln, layout.dbu ());
|
||||
def_ext = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_ext (ln, w * 0.5 * layout.dbu ()) / layout.dbu ());
|
||||
def_ext = get_def_ext (ln, w, layout.dbu ());
|
||||
}
|
||||
|
||||
std::map<int, db::Polygon>::const_iterator s = styles.find (sn);
|
||||
|
|
@ -556,7 +584,7 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
style = &s->second;
|
||||
}
|
||||
|
||||
std::vector<db::Coord> ext;
|
||||
std::vector<std::pair<db::Coord, db::Coord> > ext;
|
||||
std::vector<db::Point> pts;
|
||||
|
||||
double x = 0.0, y = 0.0;
|
||||
|
|
@ -629,11 +657,12 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
y = get_double ();
|
||||
}
|
||||
pts.push_back (db::Point (db::DPoint (x * scale, y * scale)));
|
||||
db::Coord e = def_ext;
|
||||
std::pair<db::Coord, db::Coord> ee = def_ext;
|
||||
if (! peek (")")) {
|
||||
e = db::coord_traits<db::Coord>::rounded (get_double () * scale);
|
||||
db::Coord e = db::coord_traits<db::Coord>::rounded (get_double () * scale);
|
||||
ee.first = ee.second = e;
|
||||
}
|
||||
ext.push_back (e);
|
||||
ext.push_back (ee);
|
||||
|
||||
test (")");
|
||||
|
||||
|
|
@ -648,8 +677,11 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
|
||||
// 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
|
||||
|
||||
db::Coord e = std::max (ext.front (), ext.back ());
|
||||
std::pair<db::Coord, db::Coord> e = std::max (ext.front (), ext.back ());
|
||||
bool is_isotropic = (e.first == e.second && w.first == w.second);
|
||||
bool was_path = false;
|
||||
|
||||
std::vector<db::Point>::const_iterator pt = pts.begin ();
|
||||
while (pt != pts.end ()) {
|
||||
|
|
@ -657,11 +689,27 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
std::vector<db::Point>::const_iterator pt0 = pt;
|
||||
do {
|
||||
++pt;
|
||||
} while (pt != pts.end () && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y()));
|
||||
} while (pt != pts.end () && is_isotropic && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y()));
|
||||
|
||||
if (pt - pt0 > 1) {
|
||||
if (pt - pt0 > 1 || pt0->x () == pt0[1].x () || pt0->y () == pt0[0].y()) {
|
||||
|
||||
db::Path p (pt0, pt, w, pt0 == pts.begin () ? e : 0, pt == pts.end () ? e : 0, false);
|
||||
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<db::Path> (p, prop_id));
|
||||
} else {
|
||||
|
|
@ -674,10 +722,16 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
|
||||
--pt;
|
||||
|
||||
} else if (pt != pts.end ()) {
|
||||
was_path = true;
|
||||
|
||||
db::Coord s = (w + 1) / 2;
|
||||
db::Coord t = db::Coord (ceil (w * (M_SQRT2 - 1) / 2));
|
||||
} 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),
|
||||
|
|
@ -700,6 +754,8 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
design.shapes (dl.second).insert (p);
|
||||
}
|
||||
|
||||
was_path = false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -766,7 +822,7 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
|
||||
if (! specialnets) {
|
||||
w = get_wire_width_for_rule (*rulename, ln, layout.dbu ());
|
||||
def_ext = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_ext (ln, w * 0.5 * layout.dbu ()) / layout.dbu ());
|
||||
def_ext = get_def_ext (ln, w, layout.dbu ());
|
||||
}
|
||||
|
||||
// continue a segment with the current point and the new layer
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ private:
|
|||
db::FTrans get_orient (bool optional);
|
||||
void read_polygon (db::Polygon &poly, double scale);
|
||||
void read_rect (db::Polygon &poly, double scale);
|
||||
db::Coord get_wire_width_for_rule(const std::string &rule, const std::string &ln, double dbu);
|
||||
std::pair<Coord, Coord> get_wire_width_for_rule(const std::string &rule, const std::string &ln, double dbu);
|
||||
std::pair<db::Coord, db::Coord> get_def_ext (const std::string &ln, const std::pair<db::Coord, db::Coord> &wxy, double dbu);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -531,6 +531,22 @@ LEFDEFImporter::expect (const std::string &token)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFImporter::expect (const std::string &token1, const std::string &token2)
|
||||
{
|
||||
if (! test (token1) && ! test (token2)) {
|
||||
error ("Expected token: " + token1 + " or " + token2);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFImporter::expect (const std::string &token1, const std::string &token2, const std::string &token3)
|
||||
{
|
||||
if (! test (token1) && ! test (token2) && ! test (token3)) {
|
||||
error ("Expected token: " + token1 + ", " + token2 + " or " + token3);
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
LEFDEFImporter::get_double ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -642,6 +642,16 @@ protected:
|
|||
*/
|
||||
void expect (const std::string &token);
|
||||
|
||||
/**
|
||||
* @brief Test whether the next token matches one of the given ones and raise an error if it does not
|
||||
*/
|
||||
void expect (const std::string &token1, const std::string &token2);
|
||||
|
||||
/**
|
||||
* @brief Test whether the next token matches one of the given ones and raise an error if it does not
|
||||
*/
|
||||
void expect (const std::string &token, const std::string &token2, const std::string &token3);
|
||||
|
||||
/**
|
||||
* @brief Gets the next token
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -65,6 +65,17 @@ LEFImporter::layer_ext (const std::string &layer, double def_ext) const
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<double, double>
|
||||
LEFImporter::min_layer_width (const std::string &layer) const
|
||||
{
|
||||
std::map<std::string, std::pair<double, double> >::const_iterator l = m_min_widths.find (layer);
|
||||
if (l != m_min_widths.end ()) {
|
||||
return l->second;
|
||||
} else {
|
||||
return std::make_pair (0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
LEFImporter::layer_width (const std::string &layer, const std::string &nondefaultrule, double def_width) const
|
||||
{
|
||||
|
|
@ -361,59 +372,8 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p
|
|||
}
|
||||
|
||||
void
|
||||
LEFImporter::do_read (db::Layout &layout)
|
||||
LEFImporter::read_nondefaultrule (db::Layout & /*layout*/)
|
||||
{
|
||||
// TODO: what to do with that value?
|
||||
// double dbu_mic = 1000;
|
||||
|
||||
while (! at_end ()) {
|
||||
|
||||
if (test ("END")) {
|
||||
|
||||
// END LIBRARY terminates the file
|
||||
expect ("LIBRARY");
|
||||
break;
|
||||
|
||||
} else if (test ("VERSION")) {
|
||||
|
||||
// ignore VERSION statement currently
|
||||
take ();
|
||||
expect (";");
|
||||
|
||||
} else if (test ("UNITS")) {
|
||||
|
||||
// read over SPACING sections
|
||||
while (! test ("END")) {
|
||||
if (test ("DATABASE")) {
|
||||
expect ("MICRONS");
|
||||
// TODO: what to do with that value
|
||||
/* dbu_mic = */ get_double ();
|
||||
expect (";");
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expect ("UNITS");
|
||||
|
||||
} else if (test ("SPACING")) {
|
||||
|
||||
// read over SPACING sections
|
||||
while (! test ("END") || ! test ("SPACING")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("PROPERTYDEFINITIONS")) {
|
||||
|
||||
// read over PROPERTYDEFINITIONS sections
|
||||
while (! test ("END") || ! test ("PROPERTYDEFINITIONS")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("NONDEFAULTRULE")) {
|
||||
|
||||
// read NONDEFAULTRULE sections
|
||||
std::string n = get ();
|
||||
|
||||
|
|
@ -453,40 +413,11 @@ LEFImporter::do_read (db::Layout &layout)
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
} else if (test ("SITE")) {
|
||||
|
||||
// read over SITE sections
|
||||
std::string n = get ();
|
||||
while (! test ("END") || ! test (n)) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("VIARULE")) {
|
||||
|
||||
// read over VIARULE sections
|
||||
std::string n = get ();
|
||||
while (! test ("END") || ! test (n)) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("VIA")) {
|
||||
|
||||
std::string n = get ();
|
||||
|
||||
// produce a cell for vias
|
||||
std::string cellname = "VIA_" + n;
|
||||
db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ()));
|
||||
|
||||
ViaDesc &via_desc = m_vias[n];
|
||||
via_desc.cell = &cell;
|
||||
|
||||
while (test ("DEFAULT") || test ("TOPOFSTACKONLY"))
|
||||
;
|
||||
test (";");
|
||||
|
||||
if (test ("VIARULE")) {
|
||||
|
||||
void
|
||||
LEFImporter::read_viadef_by_rule (Layout &layout, db::Cell &cell, ViaDesc &via_desc, const std::string & /*n*/)
|
||||
{
|
||||
db::Vector cutsize, cutspacing;
|
||||
db::Vector be, te;
|
||||
db::Vector bo, to;
|
||||
|
|
@ -593,9 +524,11 @@ LEFImporter::do_read (db::Layout &layout)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
void
|
||||
LEFImporter::read_viadef_by_geometry (Layout &layout, db::Cell &cell, ViaDesc &via_desc, const std::string &n)
|
||||
{
|
||||
// ignore resistance spec
|
||||
if (test ("RESISTANCE")) {
|
||||
get_double ();
|
||||
|
|
@ -624,31 +557,53 @@ LEFImporter::do_read (db::Layout &layout)
|
|||
reset_cellname ();
|
||||
|
||||
expect ("END");
|
||||
}
|
||||
|
||||
void
|
||||
LEFImporter::read_viadef (Layout &layout)
|
||||
{
|
||||
std::string n = get ();
|
||||
|
||||
// produce a cell for vias
|
||||
std::string cellname = "VIA_" + n;
|
||||
db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ()));
|
||||
|
||||
ViaDesc &via_desc = m_vias[n];
|
||||
via_desc.cell = &cell;
|
||||
|
||||
while (test ("DEFAULT") || test ("TOPOFSTACKONLY"))
|
||||
;
|
||||
test (";");
|
||||
|
||||
if (test ("VIARULE")) {
|
||||
read_viadef_by_rule (layout, cell, via_desc, n);
|
||||
} else {
|
||||
read_viadef_by_geometry (layout, cell, via_desc, n);
|
||||
}
|
||||
|
||||
test ("VIA");
|
||||
expect (n);
|
||||
|
||||
} else if (test ("BEGINEXT")) {
|
||||
|
||||
// read over BEGINEXT sections
|
||||
while (! test ("ENDEXT")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("LAYER")) {
|
||||
|
||||
void
|
||||
LEFImporter::read_layer (Layout & /*layout*/)
|
||||
{
|
||||
std::string ln = get ();
|
||||
double wmin = 0.0, wmin_wrongdir = 0.0;
|
||||
bool is_horizontal = true;
|
||||
|
||||
register_layer (ln);
|
||||
|
||||
// just extract the width from the layer - we need that as the default width for paths
|
||||
while (! at_end ()) {
|
||||
|
||||
if (test ("END")) {
|
||||
|
||||
expect (ln);
|
||||
break;
|
||||
|
||||
} else if (test ("TYPE")) {
|
||||
|
||||
if (test ("ROUTING")) {
|
||||
m_routing_layers.insert (ln);
|
||||
} else if (test ("CUT")) {
|
||||
|
|
@ -657,15 +612,29 @@ LEFImporter::do_read (db::Layout &layout)
|
|||
get ();
|
||||
}
|
||||
expect (";");
|
||||
|
||||
} else if (test ("WIDTH")) {
|
||||
|
||||
double w = get_double ();
|
||||
m_default_widths.insert (std::make_pair (ln, w));
|
||||
expect (";");
|
||||
|
||||
} else if (test ("DIRECTION")) {
|
||||
|
||||
if (test ("HORIZONTAL")) {
|
||||
is_horizontal = true;
|
||||
} else {
|
||||
expect ("VERTICAL", "DIAG45", "DIAG135");
|
||||
}
|
||||
|
||||
} else if (test ("WIREEXTENSION")) {
|
||||
|
||||
double w = get_double ();
|
||||
m_default_ext.insert (std::make_pair (ln, w));
|
||||
expect (";");
|
||||
|
||||
} else if (test ("ACCURRENTDENSITY")) {
|
||||
|
||||
// ACCURRENTDENSITY needs some special attention because it can contain nested WIDTH
|
||||
// blocks following a semicolon
|
||||
take ();
|
||||
|
|
@ -677,15 +646,50 @@ LEFImporter::do_read (db::Layout &layout)
|
|||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("PROPERTY")) {
|
||||
|
||||
std::string name = get ();
|
||||
tl::Variant value = get ();
|
||||
|
||||
if (name == "LEF58_MINWIDTH") {
|
||||
|
||||
// Cadence extension
|
||||
tl::Extractor ex (value.to_string ());
|
||||
double mw = 0.0;
|
||||
if (ex.test ("MINWIDTH") && ex.try_read (mw)) {
|
||||
if (ex.test ("WRONGDIRECTION")) {
|
||||
wmin_wrongdir = mw;
|
||||
} else {
|
||||
wmin = mw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else if (test ("MACRO")) {
|
||||
if (wmin > 0.0 || wmin_wrongdir > 0.0) {
|
||||
|
||||
if (! is_horizontal) {
|
||||
std::swap (wmin, wmin_wrongdir);
|
||||
}
|
||||
|
||||
m_min_widths.insert (std::make_pair (ln, std::make_pair (wmin, wmin_wrongdir)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFImporter::read_macro (Layout &layout)
|
||||
{
|
||||
std::string mn = get ();
|
||||
set_cellname (mn);
|
||||
|
||||
|
|
@ -790,6 +794,98 @@ LEFImporter::do_read (db::Layout &layout)
|
|||
m_macro_bboxes_by_name.insert (std::make_pair (mn, db::Box (-origin, -origin + size)));
|
||||
|
||||
reset_cellname ();
|
||||
}
|
||||
|
||||
void
|
||||
LEFImporter::do_read (db::Layout &layout)
|
||||
{
|
||||
// TODO: what to do with that value?
|
||||
// double dbu_mic = 1000;
|
||||
|
||||
while (! at_end ()) {
|
||||
|
||||
if (test ("END")) {
|
||||
|
||||
// END LIBRARY terminates the file
|
||||
expect ("LIBRARY");
|
||||
break;
|
||||
|
||||
} else if (test ("VERSION")) {
|
||||
|
||||
// ignore VERSION statement currently
|
||||
take ();
|
||||
expect (";");
|
||||
|
||||
} else if (test ("UNITS")) {
|
||||
|
||||
// read over SPACING sections
|
||||
while (! test ("END")) {
|
||||
if (test ("DATABASE")) {
|
||||
expect ("MICRONS");
|
||||
// TODO: what to do with that value
|
||||
/* dbu_mic = */ get_double ();
|
||||
expect (";");
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expect ("UNITS");
|
||||
|
||||
} else if (test ("SPACING")) {
|
||||
|
||||
// read over SPACING sections
|
||||
while (! test ("END") || ! test ("SPACING")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("PROPERTYDEFINITIONS")) {
|
||||
|
||||
// read over PROPERTYDEFINITIONS sections
|
||||
while (! test ("END") || ! test ("PROPERTYDEFINITIONS")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("NONDEFAULTRULE")) {
|
||||
|
||||
read_nondefaultrule (layout);
|
||||
|
||||
} else if (test ("SITE")) {
|
||||
|
||||
// read over SITE sections
|
||||
std::string n = get ();
|
||||
while (! test ("END") || ! test (n)) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("VIARULE")) {
|
||||
|
||||
// read over VIARULE sections
|
||||
std::string n = get ();
|
||||
while (! test ("END") || ! test (n)) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("VIA")) {
|
||||
|
||||
read_viadef (layout);
|
||||
|
||||
} else if (test ("BEGINEXT")) {
|
||||
|
||||
// read over BEGINEXT sections
|
||||
while (! test ("ENDEXT")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("LAYER")) {
|
||||
|
||||
read_layer (layout);
|
||||
|
||||
} else if (test ("MACRO")) {
|
||||
|
||||
read_macro (layout);
|
||||
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,11 @@ public:
|
|||
*/
|
||||
double layer_ext (const std::string &layer, double def_ext = 0.0) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the minimum wire width in x and y direction for the given layer name
|
||||
*/
|
||||
std::pair<double, double> min_layer_width (const std::string &layer) const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the given layer is a routing layer
|
||||
*/
|
||||
|
|
@ -119,6 +124,7 @@ private:
|
|||
std::map<std::string, std::map<std::string, double> > m_nondefault_widths;
|
||||
std::map<std::string, double> m_default_widths;
|
||||
std::map<std::string, double> m_default_ext;
|
||||
std::map<std::string, std::pair<double, double> > m_min_widths;
|
||||
std::map<std::string, db::Cell *> m_macros_by_name;
|
||||
std::map<std::string, db::Box> m_macro_bboxes_by_name;
|
||||
std::map<std::string, ViaDesc> m_vias;
|
||||
|
|
@ -126,6 +132,12 @@ private:
|
|||
|
||||
std::vector <db::Trans> get_iteration (db::Layout &layout);
|
||||
void read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose purpose, std::map<std::string, db::Box> *collect_bboxes = 0, properties_id_type prop_id = 0);
|
||||
void read_nondefaultrule (Layout &layout);
|
||||
void read_viadef (Layout &layout);
|
||||
void read_viadef_by_rule (Layout &layout, db::Cell &cell, ViaDesc &desc, const std::string &n);
|
||||
void read_viadef_by_geometry (Layout &layout, db::Cell &cell, ViaDesc &desc, const std::string &n);
|
||||
void read_layer (Layout &layout);
|
||||
void read_macro (Layout &layout);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -270,12 +270,17 @@ TEST(103)
|
|||
run_test (_this, "issue-517", "def:in.def", "au.oas.gz", default_options (), false);
|
||||
}
|
||||
|
||||
TEST(104)
|
||||
TEST(104_doxy_vias)
|
||||
{
|
||||
run_test (_this, "doxy_vias", "def:test.def", "au.oas.gz", default_options (), false);
|
||||
}
|
||||
|
||||
TEST(105)
|
||||
TEST(105_specialnets_geo)
|
||||
{
|
||||
run_test (_this, "specialnets_geo", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
|
||||
}
|
||||
|
||||
TEST(106_wrongdirection)
|
||||
{
|
||||
run_test (_this, "wrongdirection", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,19 @@
|
|||
VERSION 5.8 ;
|
||||
DIVIDERCHAR "/" ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DESIGN test ;
|
||||
UNITS DISTANCE MICRONS 1000 ;
|
||||
DIEAREA ( 0 0 ) ( 10000 10000 ) ;
|
||||
NONDEFAULTRULES 1 ;
|
||||
- ndr
|
||||
+ HARDSPACING
|
||||
+ LAYER M3 WIDTH 500 SPACING 500
|
||||
;
|
||||
END NONDEFAULTRULES
|
||||
NETS 1 ;
|
||||
- net_b
|
||||
+ NONDEFAULTRULE ndr
|
||||
+ ROUTED M3 ( 0 0 ) ( 2000 0 ) via34 ( * 2000 ) ( 4000 * ) ( * 4000 )
|
||||
;
|
||||
END NETS
|
||||
END DESIGN
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
VERSION 5.8 ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DIVIDERCHAR "/" ;
|
||||
|
||||
UNITS
|
||||
DATABASE MICRONS 1000 ;
|
||||
END UNITS
|
||||
|
||||
MANUFACTURINGGRID 0.001 ;
|
||||
|
||||
PROPERTYDEFINITIONS
|
||||
LAYER LEF58_MINWIDTH STRING ;
|
||||
END PROPERTYDEFINITIONS
|
||||
|
||||
LAYER M3
|
||||
TYPE ROUTING ;
|
||||
DIRECTION VERTICAL ;
|
||||
WIDTH 0.6 ;
|
||||
END M3
|
||||
|
||||
LAYER VIA3
|
||||
TYPE CUT ;
|
||||
END VIA3
|
||||
|
||||
LAYER M4
|
||||
TYPE ROUTING ;
|
||||
DIRECTION HORIZONTAL ;
|
||||
WIDTH 0.5 ;
|
||||
PROPERTY LEF58_MINWIDTH "MINWIDTH 1.0 WRONGDIRECTION ; " ;
|
||||
END M4
|
||||
|
||||
VIA via34
|
||||
LAYER M3 ;
|
||||
RECT -0.4 -0.3 0.4 0.3 ;
|
||||
LAYER VIA3 ;
|
||||
RECT -0.3 -0.25 0.3 0.25 ;
|
||||
LAYER M4 ;
|
||||
RECT -1.00 -0.5 1.00 0.5 ;
|
||||
END via34
|
||||
|
||||
END LIBRARY
|
||||
Loading…
Reference in New Issue