Skip to content

Commit 316a58e

Browse files
Merge pull request #2079 from KLayout/bugfix/issue-2075
Fixing issue #2075 (strm2oas ignores def net routing wire extensions)
2 parents f427f53 + 7acd11a commit 316a58e

File tree

6 files changed

+94
-28
lines changed

6 files changed

+94
-28
lines changed

src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
namespace db
3131
{
3232

33+
static const std::pair<db::Coord, db::Coord> ext_not_set = std::make_pair (std::numeric_limits<db::Coord>::min (), std::numeric_limits<db::Coord>::min ());
34+
3335
struct DEFImporterGroup
3436
{
3537
DEFImporterGroup (const std::string &n, const std::string &rn, const std::vector<tl::GlobPattern> &m)
@@ -133,7 +135,7 @@ DEFImporter::get_def_ext (const std::string & /*ln*/, const std::pair<db::Coord,
133135
return std::make_pair (de, de);
134136
#else
135137
// This implementation follows the LEFDEF 5.8 spec saying the "default extension is half the wire width":
136-
db::Coord de = std::min (wxy.first, wxy.second) / 2;
138+
auto de = std::min (wxy.second, wxy.first) / 2;
137139
return std::make_pair (de, de);
138140
#endif
139141
}
@@ -355,28 +357,46 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u
355357
bool was_path_before = false;
356358

357359
std::vector<db::Point>::const_iterator pt = pts.begin ();
360+
std::vector<std::pair<db::Coord, db::Coord> >::const_iterator ex = ext.begin ();
361+
358362
while (pt != pts.end ()) {
359363

360-
std::vector<db::Point>::const_iterator pt0 = pt;
364+
auto pt0 = pt;
365+
auto ex0 = ex;
361366
++pt;
367+
++ex;
362368
if (pt == pts.end ()) {
363369
break;
364370
}
365371

366372
bool multipart = false;
367373
if (is_isotropic) {
368-
while (pt != pts.end () && (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())) {
374+
while (pt != pts.end ()) {
375+
if (! (pt[-1].x () == pt[0].x () || pt[-1].y () == pt[0].y())) {
376+
// non-orthogonal segments are treated otherwise, not by paths
377+
break;
378+
}
379+
if (pt + 1 != pts.end () && ex[0] != ext_not_set) {
380+
// connection points feature non-default extensions and should not be represented by paths
381+
break;
382+
}
369383
++pt;
384+
++ex;
370385
multipart = true;
371386
}
372387
if (multipart) {
373388
--pt;
389+
--ex;
374390
}
375391
}
376392

377-
// The next part is the interval [pt0..pt] (pt inclusive)
393+
// The next part is the interval [pt0..pt] (including pt)
378394

379-
if (multipart || (pt0->x () == pt0[1].x () || pt0->y () == pt0[1].y())) {
395+
if (! multipart && (pt0->x () == pt0[1].x () && pt0->y () == pt0[1].y())) {
396+
397+
// ignore single-point paths
398+
399+
} else if (multipart || (pt0->x () == pt0[1].x () || pt0->y () == pt0[1].y())) {
380400

381401
db::Coord wxy, wxy_perp;
382402

@@ -388,33 +408,27 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u
388408
wxy_perp = w.second;
389409
}
390410

391-
// compute begin extension
411+
// compute begin and end extensions
392412
db::Coord be = 0;
393-
if (pt0 == pts.begin ()) {
394-
if (pt0->x () == pt0 [1].x ()) {
395-
be = ext.front ().second;
396-
} else {
397-
be = ext.front ().first;
398-
}
413+
if (*ex0 != ext_not_set) {
414+
be = (pt0->x () == pt0 [1].x ()) ? ex0->second : ex0->first;
399415
} else if (was_path_before) {
400416
// provides the overlap to the previous segment
401417
be = wxy_perp / 2;
402418
}
403419

404-
// compute end extension
405420
db::Coord ee = 0;
406-
if (pt + 1 == pts.end ()) {
407-
if (pt [-1].x () == pt->x ()) {
408-
ee = ext.back ().second;
409-
} else {
410-
ee = ext.back ().first;
411-
}
421+
if (*ex != ext_not_set) {
422+
ee = (pt [-1].x () == pt->x ()) ? ex->second : ex->first;
412423
}
413424

414425
auto pt_from = pt0;
415426
auto pt_to = pt + 1;
416427

417-
// do not split away end segments if they are shorter than half the width
428+
// Pplit paths if "joined_paths" is off. Sorry for spending the effort before to
429+
// compute multipath chains.
430+
// But now we can keep end segments joined if they are shorter than half the width
431+
// to establish a proper path end in that case.
418432

419433
auto pt_from_split = pt_from;
420434
auto pt_to_split = pt_to;
@@ -553,17 +567,16 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C
553567
const std::string *rulename = 0;
554568

555569
std::pair<db::Coord, db::Coord> w (0, 0);
556-
if (specialnets) {
557-
db::Coord n = db::coord_traits<db::Coord>::rounded (get_double () * scale);
558-
w = std::make_pair (n, n);
559-
}
560570

561571
const db::Polygon *style = 0;
562572

563573
int sn = std::numeric_limits<int>::max ();
564574

565575
if (specialnets) {
566576

577+
db::Coord n = db::coord_traits<db::Coord>::rounded (get_double () * scale);
578+
w = std::make_pair (n, n);
579+
567580
while (test ("+")) {
568581

569582
if (test ("STYLE")) {
@@ -598,11 +611,17 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C
598611
rulename = &nondefaultrule;
599612
}
600613

614+
if (! specialnets) {
615+
w = get_wire_width_for_rule (*rulename, ln, layout.dbu ());
616+
}
617+
618+
// default extension for first and last point
601619
std::pair<db::Coord, db::Coord> def_ext (0, 0);
620+
std::pair<db::Coord, db::Coord> def_ext_conn = get_def_ext (ln, w, layout.dbu ());
602621

603622
if (! specialnets) {
604-
w = get_wire_width_for_rule (*rulename, ln, layout.dbu ());
605-
def_ext = get_def_ext (ln, w, layout.dbu ());
623+
// first and last extensions are half width by default for routed nets
624+
def_ext = def_ext_conn;
606625
}
607626

608627
std::map<int, db::Polygon>::const_iterator s = m_styles.find (sn);
@@ -694,7 +713,7 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C
694713
y = get_double ();
695714
}
696715
pts.push_back (db::Point (db::DPoint (x * scale, y * scale)));
697-
std::pair<db::Coord, db::Coord> ee = def_ext;
716+
std::pair<db::Coord, db::Coord> ee = ext_not_set;
698717
if (! peek (")")) {
699718
db::Coord e = db::coord_traits<db::Coord>::rounded (get_double () * scale);
700719
ee.first = ee.second = e;
@@ -706,10 +725,20 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C
706725
}
707726

708727
if (pts.size () > 1) {
728+
729+
// replace the default extensions
730+
if (ext.front () == ext_not_set) {
731+
ext.front () = def_ext;
732+
}
733+
if (ext.back () == ext_not_set) {
734+
ext.back () = def_ext;
735+
}
736+
709737
std::set <unsigned int> dl = open_layer (layout, ln, specialnets ? SpecialRouting : Routing, mask);
710738
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
711739
produce_routing_geometry (design, style, *l, prop_id, pts, ext, w);
712740
}
741+
713742
}
714743

715744
// continue a segment with the current point and the new mask

src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ TEST(def16)
432432
// (complete example)
433433
db::LEFDEFReaderOptions opt = default_options ();
434434
opt.set_macro_resolution_mode (1);
435-
run_test (_this, "def16", "lef:a.lef+lef:tech.lef+def:a.def", "au_4b.oas.gz", opt);
435+
run_test (_this, "def16", "lef:a.lef+lef:tech.lef+def:a.def", "au_4c.oas.gz", opt);
436436
}
437437

438438
TEST(100)
@@ -1153,3 +1153,10 @@ TEST(215_multiDEF)
11531153

11541154
db::compare_layouts (_this, ly, fn_path + "au.oas", db::WriteOAS);
11551155
}
1156+
1157+
// issue-2075
1158+
TEST(216_line_extensions)
1159+
{
1160+
run_test (_this, "issue-2075", "map:test.map+lef:test.lef+def:test.def", "au.oas", default_options (), false);
1161+
}
1162+

testdata/lefdef/issue-2075/au.oas

474 Bytes
Binary file not shown.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
VERSION 5.8 ;
2+
3+
DESIGN test ;
4+
5+
UNITS DISTANCE MICRONS 2000 ;
6+
7+
DIEAREA ( 0 0 ) ( 6000 3000 ) ;
8+
9+
VIAS 1 ;
10+
END VIAS
11+
12+
NETS 1 ;
13+
- dummy + ROUTED M2 ( 1670 830 ) ( * * 300 ) ( 4950 * 300 ) ( * 2000 300 ) ;
14+
END NETS
15+
16+
END DESIGN
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
VERSION 5.8 ;
2+
3+
UNITS
4+
DATABASE MICRONS 2000 ;
5+
END UNITS
6+
7+
LAYER M2
8+
TYPE ROUTING ;
9+
WIDTH 0.2 ;
10+
END M2
11+
12+
END LIBRARY
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DIEAREA ALL 108 0
2+
M2 NET 32 0

0 commit comments

Comments
 (0)