From a2aead8c5c431271bd3363ffc3c3ebd8f1ea9d1e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 12 Feb 2023 22:10:27 +0100 Subject: [PATCH 01/19] Fixed issue #1287 The problem was introduced during implementation of multi-segment rulers. This patch also fixes the tab order of the ruler properties dialog and adds some tests. --- src/ant/ant/RulerPropertiesPage.ui | 26 ++++++++- src/ant/ant/antObject.cc | 4 +- src/ant/unit_tests/antBasicTests.cc | 83 +++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 3 deletions(-) diff --git a/src/ant/ant/RulerPropertiesPage.ui b/src/ant/ant/RulerPropertiesPage.ui index 28451b680..79bfd6636 100644 --- a/src/ant/ant/RulerPropertiesPage.ui +++ b/src/ant/ant/RulerPropertiesPage.ui @@ -6,7 +6,7 @@ 0 0 - 622 + 669 621 @@ -1142,10 +1142,34 @@ + fmt_le + main_position + main_xalign + main_yalign fmt_x_le + xlabel_xalign + xlabel_yalign fmt_y_le + ylabel_xalign + ylabel_yalign style_cb outline_cb + segments_tab + x0 + y0 + x1 + y1 + x2 + y2 + swap_points + p1_to_layout + p2_to_layout + both_to_layout + dx + dy + dd + point_list + points_edit diff --git a/src/ant/ant/antObject.cc b/src/ant/ant/antObject.cc index 6cd43291c..805c5afff 100644 --- a/src/ant/ant/antObject.cc +++ b/src/ant/ant/antObject.cc @@ -331,7 +331,7 @@ Object::seg_p2 (size_t seg_index, const db::DPoint &p) void Object::p1 (const db::DPoint &p) { - if (! p1 ().equal (p)) { + if (m_points.size () < 1 || ! p1 ().equal (p)) { if (m_points.size () < 1) { m_points.push_back (p); } else { @@ -348,7 +348,7 @@ Object::p1 (const db::DPoint &p) void Object::p2 (const db::DPoint &p) { - if (! p2 ().equal (p)) { + if (m_points.size () < 2 || ! p2 ().equal (p)) { if (m_points.size () < 2) { if (m_points.empty ()) { m_points.push_back (db::DPoint ()); diff --git a/src/ant/unit_tests/antBasicTests.cc b/src/ant/unit_tests/antBasicTests.cc index 5802ffb4f..8302fb1c4 100644 --- a/src/ant/unit_tests/antBasicTests.cc +++ b/src/ant/unit_tests/antBasicTests.cc @@ -25,6 +25,8 @@ #include "antObject.h" #include "antTemplate.h" +// NOTE: most tests are in ruby/antTest.rb + TEST(1) { ant::Template tmp = ant::Template ("title", "fmt_x", "fmt_y", "fmt", @@ -48,3 +50,84 @@ TEST(1) EXPECT_EQ (a.category (), "cat"); } +TEST(2) +{ + ant::Template tmp = ant::Template ("title", "fmt_x", "fmt_y", "fmt", + ant::Object::STY_arrow_both, + ant::Object::OL_diag_xy, + true, + lay::AC_Ortho, + "cat"); + + ant::Object obj; + + EXPECT_EQ (obj.p1 ().to_string (), "0,0"); + EXPECT_EQ (obj.p2 ().to_string (), "0,0"); + + EXPECT_EQ (int (obj.segments ()), 1); + EXPECT_EQ (int (obj.points ().size ()), 0); + + obj.p1 (db::DPoint (1, 2)); + + EXPECT_EQ (obj.p1 ().to_string (), "1,2"); + EXPECT_EQ (obj.p2 ().to_string (), "1,2"); + + EXPECT_EQ (int (obj.segments ()), 1); + EXPECT_EQ (int (obj.points ().size ()), 1); + + obj.p2 (db::DPoint (2, 3)); + + EXPECT_EQ (obj.p1 ().to_string (), "1,2"); + EXPECT_EQ (obj.p2 ().to_string (), "2,3"); + + EXPECT_EQ (int (obj.segments ()), 1); + EXPECT_EQ (int (obj.points ().size ()), 2); + + obj = ant::Object (); + + EXPECT_EQ (obj.p1 ().to_string (), "0,0"); + EXPECT_EQ (obj.p2 ().to_string (), "0,0"); + + EXPECT_EQ (int (obj.segments ()), 1); + EXPECT_EQ (int (obj.points ().size ()), 0); + + obj.p1 (db::DPoint ()); + + EXPECT_EQ (obj.p1 ().to_string (), "0,0"); + EXPECT_EQ (obj.p2 ().to_string (), "0,0"); + + EXPECT_EQ (int (obj.segments ()), 1); + EXPECT_EQ (int (obj.points ().size ()), 1); + + obj.p2 (db::DPoint ()); + + EXPECT_EQ (obj.p1 ().to_string (), "0,0"); + EXPECT_EQ (obj.p2 ().to_string (), "0,0"); + + EXPECT_EQ (int (obj.segments ()), 1); + EXPECT_EQ (int (obj.points ().size ()), 1); + + obj = ant::Object (db::DPoint (1, 2), db::DPoint (2, 3), 0, tmp); + + EXPECT_EQ (obj.p1 ().to_string (), "1,2"); + EXPECT_EQ (obj.p2 ().to_string (), "2,3"); + + EXPECT_EQ (int (obj.segments ()), 1); + EXPECT_EQ (int (obj.points ().size ()), 2); + + obj = ant::Object (db::DPoint (1, 2), db::DPoint (1, 2), 0, tmp); + + EXPECT_EQ (obj.p1 ().to_string (), "1,2"); + EXPECT_EQ (obj.p2 ().to_string (), "1,2"); + + EXPECT_EQ (int (obj.segments ()), 1); + EXPECT_EQ (int (obj.points ().size ()), 1); + + obj = ant::Object (db::DPoint (), db::DPoint (), 0, tmp); + + EXPECT_EQ (obj.p1 ().to_string (), "0,0"); + EXPECT_EQ (obj.p2 ().to_string (), "0,0"); + + EXPECT_EQ (int (obj.segments ()), 1); + EXPECT_EQ (int (obj.points ().size ()), 1); +} From a54ea1f273bd16a464df91cf04d954e5828fdc21 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 15 Feb 2023 00:28:41 +0100 Subject: [PATCH 02/19] DEF reader bug fixes, turned some errors into warnings temporarily. --- .../lefdef/db_plugin/dbDEFImporter.cc | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 5ba6c5e0b..117d88b20 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -782,7 +782,7 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool } } - while (test ("+")) { + while ((in_subnet && ! at_end ()) || test ("+")) { bool was_shield = false; unsigned int mask = 0; @@ -820,6 +820,8 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool } else { + bool any = false; + bool prefixed = false; bool can_have_rect_polygon_or_via = true; @@ -831,8 +833,6 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool can_have_rect_polygon_or_via = test ("+"); } - bool any = false; - if (can_have_rect_polygon_or_via) { if (test ("SHAPE")) { take (); @@ -882,22 +882,29 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool } else if (can_have_rect_polygon_or_via && test ("VIA")) { + // For the via, the masks are encoded in a three-digit number ( ) + unsigned int mask_top = (mask / 100) % 10; + unsigned int mask_cut = (mask / 10) % 10; + unsigned int mask_bottom = mask % 10; + std::string vn = get (); db::FTrans ft = get_orient (true /*optional*/); - test ("("); - db::Vector pt = get_vector (scale); - test (")"); + while (test ("(")) { - std::map::const_iterator vd = m_via_desc.find (vn); - if (vd != m_via_desc.end ()) { - // TODO: no mask specification here? - db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, 0, 0, 0, &m_lef_importer); - if (cell) { - design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), pt))); + db::Vector pt = get_vector (scale); + test (")"); + + std::map::const_iterator vd = m_via_desc.find (vn); + if (vd != m_via_desc.end ()) { + db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer); + if (cell) { + design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), pt))); + } + } else { + warn (tl::to_string (tr ("Invalid via name: ")) + vn); } - } else { - error (tl::to_string (tr ("Invalid via name: ")) + vn); + } any = true; @@ -1204,7 +1211,7 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale) double x = 0.0, y = 0.0; - while (! at_end () && ! test ("+") && ! test (";")) { + while (! at_end () && ! peek ("+") && ! peek (";")) { test ("("); if (! test ("*")) { @@ -1238,7 +1245,17 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale) } else if (test ("VIA")) { // TODO: implement - error (tl::to_string (tr ("VIA not supported on pins currently"))); + warn (tl::to_string (tr ("VIA not supported on pins currently"))); + + get (); + + if (test ("MASK")) { + get_mask (get_long ()); + } + + test ("("); + db::Vector d = get_vector (scale); + test (")"); } else { while (! peek ("+") && ! peek ("-") && ! peek (";")) { @@ -1432,7 +1449,7 @@ DEFImporter::read_styles (double scale) } - m_styles.insert (std::make_pair (sn, db::Polygon ())).first->second.assign_hull (points.begin (), points.end ()); + m_styles.insert (std::make_pair (sn, db::Polygon ())).first->second.assign_hull (points.begin (), points.end (), false /*don't compress*/); } } From 93d9298b5101cb88fcdf15c84f0a3dd49ecb0d45 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 15 Feb 2023 00:29:26 +0100 Subject: [PATCH 03/19] Formally minkowsky sum now is allowed with empty polygon arguments --- src/db/db/dbPolygonTools.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/db/db/dbPolygonTools.cc b/src/db/db/dbPolygonTools.cc index 2032eeb36..0202ee908 100644 --- a/src/db/db/dbPolygonTools.cc +++ b/src/db/db/dbPolygonTools.cc @@ -2143,6 +2143,10 @@ ms_extraction (db::EdgeProcessor &ep, bool resolve_holes) static db::Polygon do_minkowski_sum (const db::Polygon &a, const db::Edge &b, bool resolve_holes) { + if (a.begin_hull () == a.end_hull ()) { + return db::Polygon (); + } + db::EdgeProcessor ep; db::ms_production (a, b.p1 (), b.p2 (), ep); return db::ms_extraction (ep, resolve_holes); @@ -2161,7 +2165,9 @@ minkowski_sum (const db::Polygon &a, const db::Edge &b, bool rh) static db::Polygon do_minkowski_sum (const db::Polygon &a, const db::Polygon &b, bool resolve_holes) { - tl_assert (a.begin_hull () != a.end_hull ()); + if (a.begin_hull () == a.end_hull () || b.begin_hull () == b.end_hull ()) { + return db::Polygon (); + } db::Vector p0 = *a.begin_hull () - db::Point (); From f73b2290241a840467c3eba05aa2435b3dfc8c4c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 15 Feb 2023 00:29:43 +0100 Subject: [PATCH 04/19] WIP --- .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 00797bdda..c97677899 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -277,81 +277,81 @@ static void run_test2 (tl::TestBase *_this, const char *lef_dir, const char *fil } } -TEST(1) +TEST(lef1) { run_test (_this, "lef1", "lef:in.lef", 0, default_options ()); } -TEST(2) +TEST(lef2) { // Also tests ability of plugin to properly read LEF run_test (_this, "lef2", "read:in.lef", "au.oas.gz", default_options ()); } -TEST(3) +TEST(lef3) { db::LEFDEFReaderOptions options = default_options (); options.set_cell_outline_layer ("OUTLINE (2/0)"); run_test (_this, "lef3", "lef:in.lef", "au.oas.gz", options); } -TEST(4) +TEST(lef4) { run_test (_this, "lef4", "lef:in.lef", 0, default_options ()); } -TEST(5) +TEST(lef5) { run_test (_this, "lef5", "lef:in.lef", 0, default_options ()); } -TEST(6) +TEST(lef6) { run_test (_this, "lef6", "lef:in.lef", 0, default_options ()); } -TEST(7) +TEST(lef7) { db::LEFDEFReaderOptions options = default_options (); options.set_cell_outline_layer ("OUTLINE (8/0)"); run_test (_this, "lef7", "lef:in_tech.lef+lef:in.lef", "au.oas.gz", options); } -TEST(10) +TEST(def1) { run_test (_this, "def1", "lef:in.lef+def:in.def", "au2.oas.gz", default_options ()); } -TEST(11) +TEST(def2) { db::LEFDEFReaderOptions options = default_options (); options.set_cell_outline_layer ("OUTLINE (10/0)"); run_test (_this, "def2", "lef:0.lef+lef:1.lef+def:in.def.gz", "au.oas.gz", options); } -TEST(12) +TEST(def3) { db::LEFDEFReaderOptions options = default_options (); options.set_cell_outline_layer ("OUTLINE (13/0)"); run_test (_this, "def3", "lef:in.lef+def:in.def", "au.oas.gz", options); } -TEST(13) +TEST(def4) { run_test (_this, "def4", "lef:in.lef+def:in.def", "au2.oas.gz", default_options ()); } -TEST(14) +TEST(def5) { run_test (_this, "def5", "lef:in.lef+def:in.def", "au.oas.gz", default_options ()); } -TEST(15) +TEST(def6) { run_test (_this, "def6", "lef:cells.lef+lef:tech.lef+def:in.def.gz", "au-new.oas.gz", default_options ()); } -TEST(16) +TEST(def7) { db::LEFDEFReaderOptions options = default_options (); options.set_placement_blockage_layer ("PLACEMENT_BLK (11/0)"); @@ -361,12 +361,12 @@ TEST(16) run_test (_this, "def7", "map:in.map+lef:cells.lef+lef:tech.lef+def:in.def.gz", "au2_with_map_file-new.oas.gz", options); } -TEST(17) +TEST(def8) { run_test (_this, "def8", "lef:tech.lef+def:in.def", "au.oas.gz", default_options ()); } -TEST(18) +TEST(def9) { db::LEFDEFReaderOptions options = default_options (); options.set_separate_groups (true); @@ -375,47 +375,54 @@ TEST(18) run_test (_this, "def9", "lef:tech.lef+lef:cells_modified.lef+def:in.def", "au_nogroups-new.oas.gz", default_options ()); } -TEST(19) +TEST(def10) { db::LEFDEFReaderOptions opt = default_options (); opt.set_cell_outline_layer ("OUTLINE (2/0)"); run_test (_this, "def10", "def:in.def", "au.oas.gz", opt); } -TEST(20) +TEST(def11) { db::LEFDEFReaderOptions opt = default_options (); opt.set_cell_outline_layer ("OUTLINE (12/0)"); run_test (_this, "def11", "lef:test.lef+def:test.def", "au.oas.gz", opt); } -TEST(21) +TEST(def12) { db::LEFDEFReaderOptions opt = default_options (); opt.set_cell_outline_layer ("OUTLINE (20/0)"); run_test (_this, "def12", "lef:test.lef+def:test.def", "au-new.oas.gz", opt); } -TEST(22) +TEST(def13) { db::LEFDEFReaderOptions opt = default_options (); run_test (_this, "def13", "map:test.map+lef:test.lef_5.8+def:top.def.gz", "au2.oas.gz", opt); } -TEST(23) +TEST(def14) { db::LEFDEFReaderOptions opt = default_options (); opt.set_macro_resolution_mode (1); run_test (_this, "def14", "map:test.map+lef:tech.lef+lef:stdlib.lef+def:test.def", "au.oas.gz", opt); } -TEST(24) +TEST(def15) { db::LEFDEFReaderOptions opt = default_options (); opt.set_macro_resolution_mode (1); run_test (_this, "def15", "map:test.map+lef:tech.lef+def:test.def", "au2.oas.gz", opt); } +TEST(def16) +{ + db::LEFDEFReaderOptions opt = default_options (); + opt.set_macro_resolution_mode (1); + run_test (_this, "def16", "lef:a.lef+def:a.def", "au.oas.gz", opt); +} + TEST(100) { run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", default_options (), false); From 3c9507ab63b7ad0468b4e3a997c0c1a958ebef11 Mon Sep 17 00:00:00 2001 From: Thomas Ferreira de Lima Date: Wed, 15 Feb 2023 11:01:06 -0500 Subject: [PATCH 05/19] added test for issue 1265 (writing and reading pngs) --- src/pya/unit_tests/pyaTests.cc | 2 +- testdata/pymod/pya_tests.py | 29 +++++++------- testdata/python/dbLayoutToNetlist.py | 27 +++++++------ testdata/python/dbLayoutVsSchematic.py | 7 ++-- testdata/python/layPixelBuffer.py | 52 ++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 32 deletions(-) create mode 100644 testdata/python/layPixelBuffer.py diff --git a/src/pya/unit_tests/pyaTests.cc b/src/pya/unit_tests/pyaTests.cc index 21a5a156c..c10a6d817 100644 --- a/src/pya/unit_tests/pyaTests.cc +++ b/src/pya/unit_tests/pyaTests.cc @@ -106,10 +106,10 @@ PYTHONTEST (dbLayoutToNetlist, "dbLayoutToNetlist.py") PYTHONTEST (dbLayoutVsSchematic, "dbLayoutVsSchematic.py") PYTHONTEST (dbNetlistCrossReference, "dbNetlistCrossReference.py") PYTHONTEST (layLayers, "layLayers.py") +PYTHONTEST (layPixelBuffer, "layPixelBuffer.py") PYTHONTEST (tlTest, "tlTest.py") #if defined(HAVE_QT) && defined(HAVE_QTBINDINGS) PYTHONTEST (qtbinding, "qtbinding.py") #endif #endif - diff --git a/testdata/pymod/pya_tests.py b/testdata/pymod/pya_tests.py index a0c12e856..1cf95af51 100644 --- a/testdata/pymod/pya_tests.py +++ b/testdata/pymod/pya_tests.py @@ -22,20 +22,23 @@ import dbLayoutToNetlist import dbLayoutVsSchematic import dbNetlistCrossReference import layLayers - +import layPixelBuffer + if __name__ == '__main__': - suite = unittest.TestLoader().loadTestsFromTestCase(tlTest.TLTest) - suite = unittest.TestLoader().loadTestsFromTestCase(dbPCells.DBPCellTests) - suite = unittest.TestLoader().loadTestsFromTestCase(dbLayoutTest.DBLayoutTest) - suite = unittest.TestLoader().loadTestsFromTestCase(dbPolygonTest.DBPolygonTests) - suite = unittest.TestLoader().loadTestsFromTestCase(dbReaders.DBReadersTests) - suite = unittest.TestLoader().loadTestsFromTestCase(dbRegionTest.DBRegionTest) - suite = unittest.TestLoader().loadTestsFromTestCase(dbTransTest.DBTransTests) - suite = unittest.TestLoader().loadTestsFromTestCase(dbLayoutToNetlist.DBLayoutToNetlistTests) - suite = unittest.TestLoader().loadTestsFromTestCase(dbLayoutVsSchematic.DBLayoutVsSchematicTests) - suite = unittest.TestLoader().loadTestsFromTestCase(dbNetlistCrossReference.DBNetlistCrossReferenceTests) - suite = unittest.TestLoader().loadTestsFromTestCase(layLayers.LAYLayersTests) + loader = unittest.TestLoader() + suite = unittest.TestSuite() + suite.addTests(loader.loadTestsFromTestCase(tlTest.TLTest)) + suite.addTests(loader.loadTestsFromTestCase(dbPCells.DBPCellTests)) + suite.addTests(loader.loadTestsFromTestCase(dbLayoutTest.DBLayoutTest)) + suite.addTests(loader.loadTestsFromTestCase(dbPolygonTest.DBPolygonTests)) + suite.addTests(loader.loadTestsFromTestCase(dbReaders.DBReadersTests)) + suite.addTests(loader.loadTestsFromTestCase(dbRegionTest.DBRegionTest)) + suite.addTests(loader.loadTestsFromTestCase(dbTransTest.DBTransTests)) + suite.addTests(loader.loadTestsFromTestCase(dbLayoutToNetlist.DBLayoutToNetlistTests)) + suite.addTests(loader.loadTestsFromTestCase(dbLayoutVsSchematic.DBLayoutVsSchematicTests)) + suite.addTests(loader.loadTestsFromTestCase(dbNetlistCrossReference.DBNetlistCrossReferenceTests)) + suite.addTests(loader.loadTestsFromTestCase(layLayers.LAYLayersTests)) + suite.addTests(loader.loadTestsFromTestCase(layPixelBuffer.LAYPixelBufferTests)) if not unittest.TextTestRunner(verbosity = 1).run(suite).wasSuccessful(): sys.exit(1) - diff --git a/testdata/python/dbLayoutToNetlist.py b/testdata/python/dbLayoutToNetlist.py index 2e881231f..87760f8ce 100644 --- a/testdata/python/dbLayoutToNetlist.py +++ b/testdata/python/dbLayoutToNetlist.py @@ -46,7 +46,7 @@ class DBLayoutToNetlistTests(unittest.TestCase): self.assertEqual(l2n.internal_layout().top_cell().name, ly.top_cell().name) self.assertEqual(l2n.internal_top_cell().name, ly.top_cell().name) - self.assertNotEqual(l2n.layer_of(r), ly.layer(6, 0)) # would be a strange coincidence ... + self.assertNotEqual(l2n.layer_of(r), ly.layer(6, 0)) # would be a strange coincidence ... cm = l2n.const_cell_mapping_into(ly, ly.top_cell()) for ci in range(0, l2n.internal_layout().cells()): @@ -80,7 +80,7 @@ class DBLayoutToNetlistTests(unittest.TestCase): rvia1 = l2n.make_polygon_layer( ly.layer(7, 0), "via1" ) rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0), "metal2" ) rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1), "metal2_lbl" ) - + # Intra-layer l2n.connect(rmetal1) l2n.connect(rvia1) @@ -92,7 +92,7 @@ class DBLayoutToNetlistTests(unittest.TestCase): l2n.connect(rmetal1, rmetal1_lbl) # attaches labels l2n.connect(rmetal2, rmetal2_lbl) # attaches labels - # Perform netlist extraction + # Perform netlist extraction l2n.extract_netlist() self.assertEqual(str(l2n.netlist()), """circuit TRANS ($1=$1,$2=$2); @@ -137,7 +137,7 @@ end; self.assertEqual(",".join(a), "$2") self.assertEqual(str(t), "r0 *1 2.64,0") - self.assertEqual(str(l2n.shapes_of_net(n, rmetal1, True)), + self.assertEqual(str(l2n.shapes_of_net(n, rmetal1, True)), "(-980,-420;-980,2420;-620,2420;-620,-420);(-800,820;-800,1180;580,1180;580,820);(-980,2420;-980,3180;-620,3180;-620,2420);(-980,-380;-980,380;-620,380;-620,-380)") shapes = pya.Shapes() @@ -145,7 +145,7 @@ end; r = pya.Region() for s in shapes.each(): r.insert(s.polygon) - self.assertEqual(str(r), + self.assertEqual(str(r), "(-980,-420;-980,2420;-620,2420;-620,-420);(-800,820;-800,1180;580,1180;580,820);(-980,2420;-980,3180;-620,3180;-620,2420);(-980,-380;-980,380;-620,380;-620,-380)") def test_10_LayoutToNetlistExtractionWithoutDevices(self): @@ -169,7 +169,7 @@ end; rvia1 = l2n.make_polygon_layer( ly.layer(7, 0), "via1" ) rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0), "metal2" ) rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1), "metal2_lbl" ) - + rsd = ractive - rpoly l2n.register(rsd, "sd") @@ -194,7 +194,7 @@ end; l2n.connect(rmetal1, rmetal1_lbl) # attaches labels l2n.connect(rmetal2, rmetal2_lbl) # attaches labels - # Perform netlist extraction + # Perform netlist extraction l2n.extract_netlist() self.assertEqual(str(l2n.netlist()), """circuit TRANS ($1=$1,$2=$2,$3=$3); @@ -247,7 +247,7 @@ end; rnactive = ractive - rnwell rngate = rnactive & rpoly rnsd = rnactive - rngate - + # PMOS transistor device extraction pmos_ex = pya.DeviceExtractorMOS3Transistor("PMOS") l2n.extract_devices(pmos_ex, { "SD": rpsd, "G": rpgate, "P": rpoly }) @@ -282,8 +282,8 @@ end; l2n.connect(rpoly, rpoly_lbl) # attaches labels l2n.connect(rmetal1, rmetal1_lbl) # attaches labels l2n.connect(rmetal2, rmetal2_lbl) # attaches labels - - # Perform netlist extraction + + # Perform netlist extraction l2n.extract_netlist() self.assertEqual(str(l2n.netlist()), """circuit RINGO (); @@ -397,8 +397,8 @@ end; # Global connections l2n.connect_global(rptie, "BULK") l2n.connect_global(rbulk, "BULK") - - # Perform netlist extraction + + # Perform netlist extraction l2n.extract_netlist() self.assertEqual(str(l2n.netlist()), """circuit RINGO (); @@ -455,7 +455,7 @@ end; def test_13_ReadAndWrite(self): ut_testsrc = os.getenv("TESTSRC") - ut_testtmp = os.getenv("TESTTMP") + ut_testtmp = os.getenv("TESTTMP", "") l2n = pya.LayoutToNetlist() @@ -725,4 +725,3 @@ if __name__ == '__main__': if not unittest.TextTestRunner(verbosity = 1).run(suite).wasSuccessful(): sys.exit(1) - diff --git a/testdata/python/dbLayoutVsSchematic.py b/testdata/python/dbLayoutVsSchematic.py index aff873f92..d512c300b 100644 --- a/testdata/python/dbLayoutVsSchematic.py +++ b/testdata/python/dbLayoutVsSchematic.py @@ -98,7 +98,7 @@ class DBLayoutVsSchematicTests(unittest.TestCase): lvs.connect(metal2) lvs.connect(ptie) lvs.connect(ntie) - + # inter-layer lvs.connect(psd, diff_cont) lvs.connect(nsd, diff_cont) @@ -113,7 +113,7 @@ class DBLayoutVsSchematicTests(unittest.TestCase): lvs.connect(poly, poly_lbl) # attaches labels lvs.connect(metal1, metal1_lbl) # attaches labels lvs.connect(metal2, metal2_lbl) # attaches labels - + # global lvs.connect_global(ptie, "BULK") lvs.connect_global(bulk, "BULK") @@ -144,7 +144,7 @@ class DBLayoutVsSchematicTests(unittest.TestCase): def test_3_ReadAndWrite(self): ut_testsrc = os.getenv("TESTSRC") - ut_testtmp = os.getenv("TESTTMP") + ut_testtmp = os.getenv("TESTTMP", "") lvs = pya.LayoutVsSchematic() @@ -181,4 +181,3 @@ if __name__ == '__main__': if not unittest.TextTestRunner(verbosity = 1).run(suite).wasSuccessful(): sys.exit(1) - diff --git a/testdata/python/layPixelBuffer.py b/testdata/python/layPixelBuffer.py new file mode 100644 index 000000000..a37e77f92 --- /dev/null +++ b/testdata/python/layPixelBuffer.py @@ -0,0 +1,52 @@ +# KLayout Layout Viewer +# Copyright (C) 2006-2023 Matthias Koefferlein +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +import pya +import unittest +import os +import sys + +class LAYPixelBufferTests(unittest.TestCase): + + def test_4(self): + pb = pya.PixelBuffer(10, 20) + pb.transparent = True + pb.fill(0xf0010203) + + png = pb.to_png_data() + + # some range because implementations may differ + self.assertGreater(len(png), 20) + self.assertLess(len(png), 200) + pb_copy = pya.PixelBuffer.from_png_data(png) + self.assertEqual(pb, pb_copy) + + ut_testtmp = os.getenv("TESTTMP", ".") + tmp = os.path.join(ut_testtmp, "tmp.png") + + pb.write_png(tmp) + pb_copy = pya.PixelBuffer.read_png(tmp) + self.assertEqual(pb, pb_copy) + + +# run unit tests +if __name__ == '__main__': + suite = unittest.TestLoader().loadTestsFromTestCase(LAYPixelBufferTests) + + if not unittest.TextTestRunner(verbosity = 1).run(suite).wasSuccessful(): + sys.exit(1) From 66a683259416f54e2245e8089f890c1b10057c0a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 15 Feb 2023 22:11:12 +0100 Subject: [PATCH 06/19] Some enhancements to DEF reader based on the 'complete' example. VIAs in FILL und PIN, a variety of syntax fixes. --- .../lefdef/db_plugin/dbDEFImporter.cc | 82 +++++++++++++++--- .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 2 +- testdata/lefdef/specialnets_geo/au.oas.gz | Bin 682 -> 478 bytes .../lefdef/specialnets_geo/au_no_spnet.oas.gz | Bin 529 -> 350 bytes .../specialnets_geo/au_spnet_mapped.oas.gz | Bin 765 -> 510 bytes testdata/lefdef/viasize/au.oas.gz | Bin 863 -> 519 bytes testdata/lefdef/viasize2/au.oas.gz | Bin 424 -> 542 bytes 7 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc index 117d88b20..989081b88 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbDEFImporter.cc @@ -1127,9 +1127,9 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale) if (vd.m1.empty () && vd.m2.empty ()) { // analyze the layers to find the metals - if (routing_layers.size () == 2) { - vd.m1 = routing_layers[0]; - vd.m2 = routing_layers[1]; + if (routing_layers.size () == 2 || routing_layers.size () == 1) { + vd.m1 = routing_layers.front (); + vd.m2 = routing_layers.back (); } else { warn (tl::to_string (tr ("Cannot determine routing layers for via: ")) + n); } @@ -1244,18 +1244,36 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale) } else if (test ("VIA")) { - // TODO: implement - warn (tl::to_string (tr ("VIA not supported on pins currently"))); + // TODO: clarify - VIA on pins is regarded VIA purpose, not PIN and gives a separate cell - get (); + std::string vn = get (); + unsigned int mask = 0; if (test ("MASK")) { - get_mask (get_long ()); + mask = get_mask (get_long ()); } - test ("("); - db::Vector d = get_vector (scale); - test (")"); + while (test ("(")) { + + db::Vector pt = get_vector (scale); + test (")"); + + unsigned int mask_top = (mask / 100) % 10; + unsigned int mask_cut = (mask / 10) % 10; + unsigned int mask_bottom = mask % 10; + + std::map::const_iterator vd = m_via_desc.find (vn); + if (vd != m_via_desc.end ()) { + std::string nondefaultrule; + db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer); + if (cell) { + design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (pt))); + } + } else { + warn (tl::to_string (tr ("Invalid via name: ")) + vn); + } + + } } else { while (! peek ("+") && ! peek ("-") && ! peek (";")) { @@ -1408,13 +1426,49 @@ DEFImporter::read_fills (db::Layout &layout, db::Cell &design, double scale) } else if (test ("VIA")) { - // TODO: implement - warn (tl::to_string (tr ("VIA not supported on fills currently"))); + // TODO: clarify - VIA on fill is regarded VIA purpose, not PIN and gives a separate cell - while (! at_end () && ! test (";")) { - take (); + std::string vn = get (); + + unsigned int mask = 0; + while (test ("+")) { + if (test ("MASK")) { + mask = get_mask (get_long ()); + } else if (test ("OPC")) { + // ignore + } else { + error (tl::to_string (tr ("Expected 'MASK' or 'OPC' inside fill/VIA definition"))); + } } + if (peek ("+") && test ("MASK")) { + mask = get_mask (get_long ()); + } + + unsigned int mask_top = (mask / 100) % 10; + unsigned int mask_cut = (mask / 10) % 10; + unsigned int mask_bottom = mask % 10; + + while (test ("(")) { + + db::Vector pt = get_vector (scale); + test (")"); + + std::map::const_iterator vd = m_via_desc.find (vn); + if (vd != m_via_desc.end ()) { + std::string nondefaultrule; + db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer); + if (cell) { + design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (pt))); + } + } else { + warn (tl::to_string (tr ("Invalid via name: ")) + vn); + } + + } + + test (";"); + } else { error (tl::to_string (tr ("'LAYER' or 'VIA' keyword expected"))); } diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index c97677899..328feedcc 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -420,7 +420,7 @@ TEST(def16) { db::LEFDEFReaderOptions opt = default_options (); opt.set_macro_resolution_mode (1); - run_test (_this, "def16", "lef:a.lef+def:a.def", "au.oas.gz", opt); + run_test (_this, "def16", "lef:a.lef+lef:tech.lef+def:a.def", "au.oas.gz", opt); } TEST(100) diff --git a/testdata/lefdef/specialnets_geo/au.oas.gz b/testdata/lefdef/specialnets_geo/au.oas.gz index dced1c01d169597f188d940a11aa1f5310af4dcf..72437372a7be92691aa6a0fe39523b295dcde6f4 100644 GIT binary patch literal 478 zcmV<40U`b$iwFovN$q0*19WY0UomB7Wid86VJ>fBa{yBfcJ=kt^>+;R4CduxWH!_@ zV0gjKC?n3q!6L)YEF;ds&!EJR>XUoMnybM;fb~F;;|1o9>4KX(8~>b$4qRRSKbqrK z6n{_8gJqfS+Zf>O#gP;E6wD0`9A3uI6PEAWpd*Jx2!1$+>p)oV-LX!#kC(dv@ zYtGD@X5jDcoTj#bV-70=FO#S>GXo=2N{X?us3jvKlTCo8yr?A;Ba?=Ps3*|KU|3+hgyTe4ZpxDshMVfzs}68%`NwiWgE?h!3ZoK(lTq?Bk8>w45e=gz4L7gzV3QChL+W7|izk8BD%-}W#tG5%&^WMEWgEM{zB UWMpU+;R4CduxWH!_@V0gjKfDB|rrGn#q9V6m{J>C6WUE)3cLR{TlgW|(I zT|zuKSY&u*Akv|J*c8Z!as|hS_y@#0yZZR>a3p7B7Q~n27qIgM$Gf`(#|H%Y2e<}> zL~^pGl;-AEGQ$-x^M!dj#sjfoJXnUC-9I$M$J5W1nT45w2bsgo%m2W_A%qpgNG01q=HrrbA38m>T%cF&$$%!?cC*3KLwogZ}^%NVtbzvf7c3 diff --git a/testdata/lefdef/specialnets_geo/au_no_spnet.oas.gz b/testdata/lefdef/specialnets_geo/au_no_spnet.oas.gz index 021f51106a270a0e6eaf02b9087957147f539168..dfb6a9b0b28952912fd91ea8f4295eb9d3b36701 100644 GIT binary patch literal 350 zcmV-k0ipgMiwFovN$q0*19WY0Uo+;R4CduxWH!_@ zV0gjKC?n3q!6L)YEF;ds&!EJR>XUoMnybM;fb~F;;|1o9>4KX(8~>b$4qRRSKbqrK z6n{_8gJqfq3(W`A5$1JZsL(n`Yqe z?wqE!fMX6T122=PH6sHflTCo8yr?BJBU4I>v9YKn6C;y`hNvhnBVJhs!Ea0xm?tm` zeqcPo$RKiu_{16UXD=oAkF+;R4CduxWH!_@V0gjKfDB|rrGn#q9V6m{J>C6WUE)3cLR{TlgW|(I zT|zuKSY&u*Akv|J*c8Z!as|hS_y@#0yZZR>a3p7B7Q~n27ce7Od|{rB@jz@CpHiBe zTglDt9~$E0>F3JK!py*f%;9G8HDqQ43PNch--wwR%m>rlEFe>unSdg27B8cyH6sHf zlTCo8yr?BJBU4I>v9YKn6C;y`hNvhngWxyD3Ct6i1q)6vGKd^zVOYb&)G(3(0|NjH CakUo! diff --git a/testdata/lefdef/specialnets_geo/au_spnet_mapped.oas.gz b/testdata/lefdef/specialnets_geo/au_spnet_mapped.oas.gz index 70d7ce49400a914d3c7979334c442de450e5c290..244696cf00d99bf7087d90cd8a466f89c2eab4b9 100644 GIT binary patch literal 510 zcmVQlGcIpoa{yBfcJ=kt^>+;R4CduxWH!_@ zV0gjKC?n3q!6L)YEF;ds&!EJR>XUoMnybM;fb~F;;|1o9>4KX(8~>b$4qRRSKbqrK z6n{_8gJqfS+Zf>O#!#qZx$7$dBc|U&qQk_h_wXpS zM@n2X=&Vh9_9$IEk)>-+!j!=DCkao|MYbj++8-_HSlRra;j-njWFOlA&5pi}fXl_+4ly|The2$;_^ zW|Q1I^l6{wxfBa{yBfcJ=kt^>+;R4CduxWH!_@ zV0gjKC?n3q!6L)YEF;ds&!EJR>XUoMnybM;fb~F;;|1o9>4KX(8~>b$4qRRSKbqrK z6n{_8gJqfS+Zf>O#!zads$7$dBc|U&qQkyyS;6NYQm=mQY0D literal 863 zcmY!lcJ=kt^>+;R4CduxWH!_@V0gjKfDB|rrGn#q9V6m{J>C6WUE)3cLR{TlgW|(I zT|zuKSY&u*Akv|J*c8Z!as|hS_y@#0yZZR>a3p7B7Q~n27qIgM$Gf`(#|H%Y2e<}> zL~^pGl;-AEGQ$-x^M!dj#sjfod~t4KP7V@3C$T6!m7Co^G{nc#&y|^xnSlqH!_DJs zsORSzq8}UpB$?TP(ikE@HAYBkIKgVrM7TLXw(9{2W)7e{3XfY1CTA7w8RcrAXJ8Zo zB7iCxdGN?_OJL|T0c$h?>SW@e|ASubqh%Cs+$fThm zD$2_s_>E}-^8{wW4~!=m8AJ{gk$e}L&6(=nzVe$gJVD3XpfOmJlT#&%FZxt XVY~toW@G{x^M#o~mZ@PR0|o{F;1vXa diff --git a/testdata/lefdef/viasize2/au.oas.gz b/testdata/lefdef/viasize2/au.oas.gz index 5da4dd619c09b1b68a4422c59bb31f10d52a30e7..c1ab0c221a0f64ddf30e46b875986f89f7a0c222 100644 GIT binary patch literal 542 zcmV+(0^$81iwFoYN9|((19WY0UomB7Wid86VJ>fBa{yBfcJ=kt^>+;R4CduxWH!_@ zV0gjKC?n3q!6L)YEF;ds&!EJR>XUoMnybM;fb~F;;|1o9>4KX(8~>b$4qRRSKbqrK z6n{_8gJqfS+Zf>O#!y2ZH$7$dBc|U&qQkyyS;6NYQm=mQY*47|*u)*Q@?Oa=y$lDtenHX|dGhK8spFC&o6 z1Y{dXit+;e+{aih{O6brBL}O!!Q6xtfj!488Y7<=C?A$m3v?}WTgG`tT_W|0q@~19 zNmt&82(gX23DF13dY-d&uesswS63$Jc1+koLp$r>p}MY@0>SM68J89N9G_A3!?pUr zA`h!;1_!6kO~`t{u4#REOY282j~Np=Q_hH|u|)#y4s%L==5g+XPKW+U{Rx8U4`!S? zaz^;sO9}oXZ67^5T@^O^sioQNh$zfU^5gUPqOZJ}BgRC1qlT^NJ%f7+_ZU>ZPZVTe gVw}v($iS$~Sj^bM$jHzzvH$}E02kfczu5u+07+I9IRF3v literal 424 zcmV;Z0ayMXiwFoh6Jufk17US8Z((x)<&C>a13?sqXU?qIjl1g-aH5e-VIkTWH^D-* z3TB84$tGmhYcs?PDkLag3cHjR7I_4*vas|4L_vaxm57gEsUX(QDu(q!Ucfob;r##i z&zvF7itcDB%Uy1EW0Foe=t)K4W77dHirEFh-Mq(g!u5QXXB9E;=KL8=u}%9E&w76a zY}(C*Un+}fRwx+S%Esol*xTAxd$`EwxF}ajWmfSQqg|`}_4)y62Z%A}W`(?Iv0U9D zJ#DpHuhwcIU90Y_ujy)O)-SjoBbXo~EOeuoPI=59<7L^2D)BEzW-=is`jPqJ=vuHX zB^%Ks|EBc#mzw165_3{cW+7;jVWR`n`~GI*5`xhQ>ixgqc$*TVBQ*(~lFPwy5(yLJ zj4_OiP- Date: Thu, 16 Feb 2023 21:23:59 +0100 Subject: [PATCH 07/19] Fixed issue #1294 (grid snap not working in partial mode) --- src/edt/edt/edtPartialService.cc | 55 +++++++++++++++++++++++++++++--- src/edt/edt/edtPartialService.h | 2 ++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/edt/edt/edtPartialService.cc b/src/edt/edt/edtPartialService.cc index fa20bb0e2..95fbeb1a8 100644 --- a/src/edt/edt/edtPartialService.cc +++ b/src/edt/edt/edtPartialService.cc @@ -1552,15 +1552,19 @@ PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, boo m_alt_ac = ac_from_buttons (buttons); // drag the vertex or edge/segment - if (m_selection.size () == 1 && ! m_selection.begin ()->first.is_cell_inst () && (m_selection.begin ()->second.size () == 1 /*p*/ || m_selection.begin ()->second.size () == 3 /*p1,p2,edge*/)) { + if (is_single_point_selection () || is_single_edge_selection ()) { lay::PointSnapToObjectResult snap_details; // for a single selected point or edge, m_start is the original position and we snap the target - // thus, we can bring the point on grid or to an object's edge or vertex snap_details = snap2 (p); - m_current = snap_details.snapped_point; - mouse_cursor_from_snap_details (snap_details); + if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) { + m_current = m_start + snap (p - m_start); + } else { + m_current = snap_details.snapped_point; + mouse_cursor_from_snap_details (snap_details); + } } else { @@ -1601,6 +1605,17 @@ PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, boo return false; } +static db::DPoint +projected_to_edge (const db::DEdge &edge, const db::DPoint &p) +{ + if (edge.is_degenerate ()) { + return edge.p1 (); + } else { + db::DVector v = edge.d () * (1.0 / edge.length ()); + return edge.p1 () + v * db::sprod (p - edge.p1 (), v); + } +} + bool PartialService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio) { @@ -1674,8 +1689,12 @@ PartialService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bo if (is_single_point_selection ()) { // for a single selected point we use the original point as the start location which - // allows bringing a to grid + // allows bringing it to grid m_current = m_start = single_selected_point (); + } else if (is_single_edge_selection ()) { + // for an edge selection use the point projected to edge as the start location which + // allows bringing it to grid + m_current = m_start = projected_to_edge (single_selected_edge (), p); } else { m_current = m_start = p; } @@ -1863,8 +1882,12 @@ PartialService::mouse_click_event (const db::DPoint &p, unsigned int buttons, bo if (is_single_point_selection ()) { // for a single selected point we use the original point as the start location which - // allows bringing a to grid + // allows bringing it to grid m_current = m_start = single_selected_point (); + } else if (is_single_edge_selection ()) { + // for an edge selection use the point projected to edge as the start location which + // allows bringing it to grid + m_current = m_start = projected_to_edge (single_selected_edge (), p); } else { m_current = m_start = p; } @@ -2390,6 +2413,28 @@ PartialService::is_single_point_selection () const return (m_selection.size () == 1 && ! m_selection.begin ()->first.is_cell_inst () && m_selection.begin ()->second.size () == 1 /*p*/); } +db::DEdge +PartialService::single_selected_edge () const +{ + // build the transformation variants cache and + // use only the first one of the explicit transformations + // TODO: clarify how this can be implemented in a more generic form or leave it thus. + TransformationVariants tv (view ()); + const std::vector *tv_list = tv.per_cv_and_layer (m_selection.begin ()->first.cv_index (), m_selection.begin ()->first.layer ()); + + const lay::CellView &cv = view ()->cellview (m_selection.begin ()->first.cv_index ()); + db::ICplxTrans gt (cv.context_trans () * m_selection.begin ()->first.trans ()); + db::CplxTrans tt = (*tv_list)[0] * db::CplxTrans (cv->layout ().dbu ()) * gt; + + return tt * *m_selection.begin ()->second.begin (); +} + +bool +PartialService::is_single_edge_selection () const +{ + return (m_selection.size () == 1 && ! m_selection.begin ()->first.is_cell_inst () && m_selection.begin ()->second.size () == 3 /*p1,p2,edge*/); +} + bool PartialService::select (const db::DBox &box, SelectionMode mode) { diff --git a/src/edt/edt/edtPartialService.h b/src/edt/edt/edtPartialService.h index db3088705..749eddce5 100644 --- a/src/edt/edt/edtPartialService.h +++ b/src/edt/edt/edtPartialService.h @@ -363,7 +363,9 @@ private: void resize_markers (size_t n, bool transient); void resize_inst_markers (size_t n, bool transient); bool is_single_point_selection () const; + bool is_single_edge_selection () const; db::DPoint single_selected_point () const; + db::DEdge single_selected_edge () const; bool handle_guiding_shape_changes (); void transform_selection (const db::DTrans &move_trans); }; From 33c858924f9338956feb2b31f165fba88f3d4f29 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 16 Feb 2023 23:49:24 +0100 Subject: [PATCH 08/19] Some LEF reader fixes based on the complete sample --- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 18 +- .../lefdef/db_plugin/dbLEFDEFImporter.h | 23 ++ .../lefdef/db_plugin/dbLEFImporter.cc | 250 +++++++++++++----- .../lefdef/db_plugin/dbLEFImporter.h | 1 + .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 7 + 5 files changed, 225 insertions(+), 74 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index bc9fac2c7..031b34726 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -1990,7 +1990,11 @@ LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderS void LEFDEFImporter::error (const std::string &msg) { - throw LEFDEFReaderException (msg, int (mp_stream->line_number ()), m_cellname, m_fn); + if (m_sections.empty ()) { + throw LEFDEFReaderException (msg, int (mp_stream->line_number ()), m_cellname, m_fn); + } else { + throw LEFDEFReaderException (msg + tl::sprintf (tl::to_string (tr (" (inside %s)")), tl::join (m_sections, "/")), int (mp_stream->line_number ()), m_cellname, m_fn); + } } void @@ -2140,6 +2144,18 @@ LEFDEFImporter::get () return r; } +void +LEFDEFImporter::enter_section (const std::string &name) +{ + m_sections.push_back (name); +} + +void +LEFDEFImporter::leave_section () +{ + m_sections.pop_back (); +} + const std::string & LEFDEFImporter::next () { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h index beb161fb3..84fdc7525 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.h @@ -1706,8 +1706,31 @@ private: db::property_names_id_type m_pin_prop_name_id; db::LEFDEFReaderOptions m_options; int m_warn_level; + std::vector m_sections; + + friend class LEFDEFSection; const std::string &next (); + void enter_section (const std::string &name); + void leave_section (); +}; + +class DB_PLUGIN_PUBLIC LEFDEFSection +{ +public: + LEFDEFSection (LEFDEFImporter *importer, const std::string &name) + : mp_importer (importer) + { + mp_importer->enter_section (name); + } + + ~LEFDEFSection () + { + mp_importer->leave_section (); + } + +private: + LEFDEFImporter *mp_importer; }; class DB_PLUGIN_PUBLIC LEFDEFReader diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index 12f7cb6b4..4b136bb7e 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -388,9 +388,7 @@ LEFImporter::read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, Laye } else if (test ("PROPERTY")) { // skip properties - while (! at_end () && ! test (";")) { - take (); - } + skip_entry (); } else { // stop at unknown token @@ -406,7 +404,7 @@ LEFImporter::read_nondefaultrule (db::Layout &layout) // read NONDEFAULTRULE sections std::string n = get (); - while (! test ("END") || ! test (n)) { + while (! test ("END")) { if (test ("LAYER")) { @@ -419,9 +417,7 @@ LEFImporter::read_nondefaultrule (db::Layout &layout) test (";"); m_nondefault_widths[n][l] = std::make_pair (w, w); } else { - while (! at_end () && ! test (";")) { - take (); - } + skip_entry (); } } @@ -432,12 +428,25 @@ LEFImporter::read_nondefaultrule (db::Layout &layout) read_viadef (layout, n); } else { - while (! at_end () && ! test (";")) { - take (); + + std::string token = get (); + + if (token == "SPACING") { + // read over sections we do not need + while (! at_end () && ! test ("END")) { + skip_entry (); + } + test (token); + } else if (token != ";") { + // read over lines we do not need + skip_entry (); } + } } + + test (n); } void @@ -557,6 +566,13 @@ LEFImporter::read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc get_double (); test (";"); + } else if (test ("FOREIGN")) { + + // undocumented + while (! at_end () && ! test (";")) { + take (); + } + } else if (test ("LAYER")) { layer_name = get (); @@ -631,9 +647,7 @@ LEFImporter::read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc } else if (test ("PROPERTY")) { // skip properties - while (! at_end () && ! test (";")) { - take (); - } + skip_entry (); } else { // stop at unknown token @@ -663,7 +677,7 @@ LEFImporter::read_viadef (Layout &layout, const std::string &nondefaultrule) ViaDesc &via_desc = m_vias[n]; - while (test ("DEFAULT") || test ("TOPOFSTACKONLY")) + while (test ("DEFAULT") || test ("TOPOFSTACKONLY") || test("GENERATED")) ; test (";"); @@ -746,55 +760,51 @@ LEFImporter::read_layer (Layout & /*layout*/) // blocks following a semicolon take (); if (test ("FREQUENCY")) { - while (! test ("TABLEENTRIES")) { + while (! at_end () && ! test ("TABLEENTRIES")) { take (); } } - while (! at_end () && ! test (";")) { - take (); - } + skip_entry (); } else if (test ("PROPERTY")) { - std::string name = get (); - tl::Variant value = get (); + while (! test (";") && ! at_end ()) { - if (name == "LEF58_MINWIDTH") { + std::string name = get (); + tl::Variant value = get (); - // Cadence extension - tl::Extractor ex (value.to_string ()); - double v = 0.0; - if (ex.test ("MINWIDTH") && ex.try_read (v)) { - if (ex.test ("WRONGDIRECTION")) { - wmin_wrongdir = v; - } else { - wmin = v; + if (name == "LEF58_MINWIDTH") { + + // Cadence extension + tl::Extractor ex (value.to_string ()); + double v = 0.0; + if (ex.test ("MINWIDTH") && ex.try_read (v)) { + if (ex.test ("WRONGDIRECTION")) { + wmin_wrongdir = v; + } else { + wmin = v; + } } - } - } else if (name == "LEF58_WIDTH") { + } else if (name == "LEF58_WIDTH") { - // Cadence extension - tl::Extractor ex (value.to_string ()); - double v = 0.0; - if (ex.test ("WIDTH") && ex.try_read (v)) { - if (ex.test ("WRONGDIRECTION")) { - w_wrongdir = v; - } else { - w = v; + // Cadence extension + tl::Extractor ex (value.to_string ()); + double v = 0.0; + if (ex.test ("WIDTH") && ex.try_read (v)) { + if (ex.test ("WRONGDIRECTION")) { + w_wrongdir = v; + } else { + w = v; + } } + } } - expect (";"); - } else { - - while (! at_end () && ! test (";")) { - take (); - } - + skip_entry (); } } @@ -865,6 +875,8 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("PIN")) { + LEFDEFSection section (this, "PIN"); + std::string pn = get (); std::string dir; @@ -881,6 +893,8 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("PORT")) { + LEFDEFSection section (this, "PORT"); + // produce pin labels // TODO: put a label on every single object? std::string label = pn; @@ -916,9 +930,7 @@ LEFImporter::read_macro (Layout &layout) expect ("END"); } else { - while (! at_end () && ! test (";")) { - take (); - } + skip_entry (); } } @@ -926,12 +938,19 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("FOREIGN")) { + LEFDEFSection section (this, "FOREIGN"); + std::string cn = get (); db::Point vec; db::FTrans ft; if (! peek (";")) { - vec = get_point (1.0 / layout.dbu ()); + if (test ("(")) { + vec = get_point (1.0 / layout.dbu ()); + expect (")"); + } else { + vec = get_point (1.0 / layout.dbu ()); + } ft = get_orient (true); } @@ -940,7 +959,7 @@ LEFImporter::read_macro (Layout &layout) if (options ().macro_resolution_mode () != 1) { if (! foreign_name.empty ()) { - error (tl::to_string (tr ("Duplicate FOREIGN definition"))); + warn (tl::to_string (tr ("Duplicate FOREIGN definition"))); } // What is the definition of the FOREIGN transformation? @@ -956,6 +975,8 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("OBS")) { + LEFDEFSection section (this, "OBS"); + if (reader_state ()->tech_comp ()->produce_obstructions ()) { read_geometries (mg, layout.dbu (), Obstructions); } else { @@ -966,8 +987,10 @@ LEFImporter::read_macro (Layout &layout) } else if (test ("DENSITY")) { + LEFDEFSection section (this, "DENSITY"); + // read over DENSITY statements - while (! test ("END")) { + while (! at_end () && ! test ("END")) { if (test ("LAYER")) { get (); expect (";"); @@ -980,17 +1003,27 @@ LEFImporter::read_macro (Layout &layout) } } - expect ("END"); - } else if (test ("FIXEDMASK")) { mg->set_fixedmask (true); expect (";"); } else { - while (! at_end () && ! test (";")) { - take (); + + std::string token = get (); + LEFDEFSection section (this, token); + + if (token == "TIMING") { + // read over sections we do not need + while (! at_end () && ! test ("END")) { + skip_entry (); + } + test (token); + } else if (token != ";") { + // read over lines we do not need + skip_entry (); } + } } @@ -1031,17 +1064,16 @@ LEFImporter::do_read (db::Layout &layout) } else if (test ("UNITS")) { - // read over SPACING sections - while (! test ("END")) { + LEFDEFSection section (this, "UNITS"); + + while (! at_end () && ! test ("END")) { if (test ("DATABASE")) { expect ("MICRONS"); // TODO: what to do with that value /* dbu_mic = */ get_double (); expect (";"); } else { - while (! at_end () && ! test (";")) { - take (); - } + skip_entry (); } } @@ -1049,44 +1081,105 @@ LEFImporter::do_read (db::Layout &layout) } else if (test ("SPACING")) { + LEFDEFSection section (this, "SPACING"); + // read over SPACING sections - while (! test ("END") || ! test ("SPACING")) { - take (); + while (! at_end () && ! test ("END")) { + skip_entry (); } + test ("SPACING"); + } else if (test ("PROPERTYDEFINITIONS")) { + LEFDEFSection section (this, "PROPERTYDEFINITIONS"); + // read over PROPERTYDEFINITIONS sections - while (! test ("END") || ! test ("PROPERTYDEFINITIONS")) { - take (); + while (! at_end () && ! test ("END")) { + skip_entry (); } + test ("PROPERTYDEFINITIONS"); + } else if (test ("NONDEFAULTRULE")) { + LEFDEFSection section (this, "NONDEFAULTRULE"); + read_nondefaultrule (layout); } else if (test ("SITE")) { - // read over SITE sections + LEFDEFSection section (this, "NONDEFAULTRULE"); + + // read over SITE or VIARULE sections std::string n = get (); - while (! test ("END") || ! test (n)) { - take (); + while (! at_end () && ! test ("END")) { + skip_entry (); } + test (n); + } else if (test ("VIARULE")) { - // read over VIARULE sections + LEFDEFSection section (this, "VIARULE"); + + // read over SITE or VIARULE sections std::string n = get (); - while (! test ("END") || ! test (n)) { - take (); + while (! at_end () && ! test ("END")) { + skip_entry (); } + test (n); + + } else if (test ("NOISETABLE")) { + + LEFDEFSection section (this, "NOISETABLE"); + + // read over NOISETABLE sections + while (! at_end () && ! test ("END")) { + skip_entry (); + } + + test ("NOISETABLE"); + + } else if (test ("IRDROP")) { + + LEFDEFSection section (this, "IRDROP"); + + // read over IRDROP sections + while (! at_end () && ! test ("END")) { + skip_entry (); + } + + test ("IRDROP"); + + } else if (test ("ARRAY")) { + + LEFDEFSection section (this, "ARRAY"); + + // read over ARRAY sections + std::string n = get (); + while (! at_end () && ! test ("END")) { + if (test ("FLOORPLAN")) { + while (! at_end () && ! test ("END")) { + skip_entry (); + } + } else { + skip_entry (); + } + } + + test (n); + } else if (test ("VIA")) { + LEFDEFSection section (this, "VIA"); read_viadef (layout, std::string ()); } else if (test ("BEGINEXT")) { + LEFDEFSection section (this, "BEGINEXT"); + // read over BEGINEXT sections while (! test ("ENDEXT")) { take (); @@ -1094,21 +1187,32 @@ LEFImporter::do_read (db::Layout &layout) } else if (test ("LAYER")) { + LEFDEFSection section (this, "LAYER"); read_layer (layout); } else if (test ("MACRO")) { + LEFDEFSection section (this, "MACRO"); read_macro (layout); } else { - while (! at_end () && ! test (";")) { - take (); - } + + // read over entries we do not need + skip_entry (); + } } } +void +LEFImporter::skip_entry () +{ + while (! at_end () && ! test (";")) { + take (); + } +} + void LEFImporter::finish_lef (db::Layout &layout) { diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h index 266b887aa..5c6402af4 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.h @@ -152,6 +152,7 @@ private: void read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc &desc, const std::string &n, double dbu); void read_layer (Layout &layout); void read_macro (Layout &layout); + void skip_entry (); }; } diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 328feedcc..09b435dfb 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -317,6 +317,12 @@ TEST(lef7) run_test (_this, "lef7", "lef:in_tech.lef+lef:in.lef", "au.oas.gz", options); } +TEST(lef8) +{ + // this is rather a smoke test and throws a number of warnings + run_test (_this, "lef8", "lef:tech.lef+lef:a.lef", "au.oas.gz", default_options ()); +} + TEST(def1) { run_test (_this, "def1", "lef:in.lef+def:in.def", "au2.oas.gz", default_options ()); @@ -418,6 +424,7 @@ TEST(def15) TEST(def16) { + // this is rather a smoke test db::LEFDEFReaderOptions opt = default_options (); opt.set_macro_resolution_mode (1); run_test (_this, "def16", "lef:a.lef+lef:tech.lef+def:a.def", "au.oas.gz", opt); From 4eb48738e47b4dd7a6543a746f29eb1b33b79691 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 17 Feb 2023 00:02:59 +0100 Subject: [PATCH 09/19] Confirming that issue #1282 is fixed --- src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc | 8 ++++---- .../streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc index 4b136bb7e..92a8046ff 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFImporter.cc @@ -404,14 +404,14 @@ LEFImporter::read_nondefaultrule (db::Layout &layout) // read NONDEFAULTRULE sections std::string n = get (); - while (! test ("END")) { + while (! at_end () && ! test ("END")) { if (test ("LAYER")) { std::string l = get (); // read the width for the layer - while (! test ("END")) { + while (! at_end () && ! test ("END")) { if (test ("WIDTH")) { double w = get_double (); test (";"); @@ -452,7 +452,7 @@ LEFImporter::read_nondefaultrule (db::Layout &layout) void LEFImporter::read_viadef_by_rule (RuleBasedViaGenerator *vg, ViaDesc &via_desc, const std::string & /*n*/, double dbu) { - while (! test ("END")) { + while (! at_end () && ! test ("END")) { double x, y; @@ -1181,7 +1181,7 @@ LEFImporter::do_read (db::Layout &layout) LEFDEFSection section (this, "BEGINEXT"); // read over BEGINEXT sections - while (! test ("ENDEXT")) { + while (! at_end () && ! test ("ENDEXT")) { take (); } diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 09b435dfb..0dcc0c646 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -320,6 +320,7 @@ TEST(lef7) TEST(lef8) { // this is rather a smoke test and throws a number of warnings + // (complete example) run_test (_this, "lef8", "lef:tech.lef+lef:a.lef", "au.oas.gz", default_options ()); } @@ -425,6 +426,7 @@ TEST(def15) TEST(def16) { // this is rather a smoke test + // (complete example) db::LEFDEFReaderOptions opt = default_options (); opt.set_macro_resolution_mode (1); run_test (_this, "def16", "lef:a.lef+lef:tech.lef+def:a.def", "au.oas.gz", opt); @@ -968,3 +970,9 @@ TEST(205_lef_resistance) run_test (_this, "issue-1214", "read:merged.nom.lef", "au.oas.gz", lefdef_opt, false); } +// issue 1282 +TEST(206_lef_spacing) +{ + run_test (_this, "issue-1282", "read:a.lef", 0, default_options (), false); +} + From 68db8fc867e21318bf903cd8a6612211f5dd9b1a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 17 Feb 2023 21:42:59 +0100 Subject: [PATCH 10/19] Added missing files --- testdata/lefdef/issue-1282/a.lef | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 testdata/lefdef/issue-1282/a.lef diff --git a/testdata/lefdef/issue-1282/a.lef b/testdata/lefdef/issue-1282/a.lef new file mode 100644 index 000000000..bb736ef5f --- /dev/null +++ b/testdata/lefdef/issue-1282/a.lef @@ -0,0 +1,25 @@ +VERSION 5.4 ; + +NAMESCASESENSITIVE ON ; +BUSBITCHARS "[]" ; +DIVIDERCHAR "/" ; +NOWIREEXTENSIONATPIN OFF ; + +UNITS + DATABASE MICRONS 1000 ; +END UNITS + +NONDEFAULTRULE DOUBLESPACE + LAYER M1 + WIDTH 0.16 ; + SPACING 0.36 ; + END M1 + +# klayout 0.28.5 lef reader get's confused by the SPACING in NONDEFAULTRULE + SPACING + SAMENET M1 M1 0.36 ; + END SPACING + +END DOUBLESPACE +END LIBRARY + From f6edc9c802ca705b863792dd9b64f0f58e9d5ae2 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 17 Feb 2023 23:41:36 +0100 Subject: [PATCH 11/19] Implemented solution for issue #1249 (persist layer properties in session) --- src/laybasic/laybasic/gsiDeclLayLayers.cc | 10 +++++ src/laybasic/laybasic/layLayerProperties.cc | 44 ++++++++++++++++--- src/laybasic/laybasic/layLayerProperties.h | 31 ++++++++++++- src/laybasic/laybasic/layLayoutViewBase.cc | 15 +++++++ src/laybasic/laybasic/layLayoutViewBase.h | 20 +++++++++ src/layui/layui/layLayerControlPanel.cc | 48 +++++++++------------ src/layui/layui/layLayerControlPanel.h | 2 +- src/layui/layui/layLayerTreeModel.cc | 15 ++++++- src/layui/layui/layLayerTreeModel.h | 16 +++++++ testdata/ruby/layLayers.rb | 6 +++ 10 files changed, 170 insertions(+), 37 deletions(-) diff --git a/src/laybasic/laybasic/gsiDeclLayLayers.cc b/src/laybasic/laybasic/gsiDeclLayLayers.cc index 7647b79bb..787eab65d 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayers.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayers.cc @@ -1189,6 +1189,16 @@ Class decl_LayerPropertiesNode ( "Unlike the name suggests, this node will still contain a hierarchy of nodes below if the original " "node did so." ) + + method ("is_expanded?", &lay::LayerPropertiesNode::expanded, + "@brief Gets a value indicating whether the layer tree node is expanded.\n" + "This predicate has been introduced in version 0.28.6." + ) + + method ("expanded=", &lay::LayerPropertiesNode::set_expanded, gsi::arg ("ex"), + "@brief Set a value indicating whether the layer tree node is expanded.\n" + "Setting this value to 'true' will expand (open) the tree node. Setting it to 'false' will collapse the node.\n" + "\n" + "This predicate has been introduced in version 0.28.6." + ) + method_ext ("add_child", &add_child0, "@brief Add a child entry\n" "@return A reference to the node created\n" diff --git a/src/laybasic/laybasic/layLayerProperties.cc b/src/laybasic/laybasic/layLayerProperties.cc index 8d009643b..3175306f5 100644 --- a/src/laybasic/laybasic/layLayerProperties.cc +++ b/src/laybasic/laybasic/layLayerProperties.cc @@ -591,6 +591,12 @@ LayerProperties::need_realize (unsigned int flags, bool /*force*/) } } +void +LayerProperties::expanded_state_changed () +{ + // .. no effect .. +} + void LayerProperties::do_realize (const LayoutViewBase *view) const { @@ -651,7 +657,7 @@ static unsigned int s_unique_id = 0; LayerPropertiesNode::LayerPropertiesNode () : LayerProperties (), - m_list_index (0) + m_list_index (0), m_expanded (false) { m_id = ++s_unique_id; } @@ -663,7 +669,7 @@ LayerPropertiesNode::~LayerPropertiesNode () LayerPropertiesNode::LayerPropertiesNode (const LayerProperties &d) : LayerProperties (d), - m_list_index (0) + m_list_index (0), m_expanded (false) { m_id = ++s_unique_id; } @@ -671,6 +677,7 @@ LayerPropertiesNode::LayerPropertiesNode (const LayerProperties &d) LayerPropertiesNode::LayerPropertiesNode (const LayerPropertiesNode &d) : LayerProperties (d), tl::Object (), m_list_index (0), + m_expanded (d.m_expanded), m_children (d.m_children), m_id (d.m_id) { @@ -687,6 +694,7 @@ LayerPropertiesNode::operator= (const LayerPropertiesNode &d) LayerProperties::operator= (d); m_children = d.m_children; + m_expanded = d.m_expanded; m_id = d.m_id; for (iterator c = m_children.begin (); c != m_children.end (); ++c) { @@ -705,7 +713,7 @@ LayerPropertiesNode::operator== (const LayerPropertiesNode &d) const if (! LayerProperties::operator== (d)) { return false; } - return m_children == d.m_children; + return m_children == d.m_children && m_expanded == d.m_expanded; } LayoutViewBase *LayerPropertiesNode::view() const @@ -713,6 +721,15 @@ LayoutViewBase *LayerPropertiesNode::view() const return const_cast (mp_view.get ()); } +void +LayerPropertiesNode::set_expanded (bool ex) +{ + if (expanded () != ex) { + m_expanded = ex; + expanded_state_changed (); + } +} + unsigned int LayerPropertiesNode::list_index () const { @@ -740,6 +757,12 @@ LayerPropertiesNode::realize_source () const do_realize (mp_view.get ()); } +void +LayerPropertiesNode::expanded_state_changed () +{ + touch (); +} + void LayerPropertiesNode::need_realize (unsigned int flags, bool force) { @@ -1763,8 +1786,9 @@ struct LineStyleIndexConverter static const tl::XMLElementList layer_element = tl::XMLElementList ( // HINT: these make_member calls want to be qualified: otherwise an internal error // was observed .. - tl::make_member (&LayerPropertiesNode::frame_color_loc, &LayerPropertiesNode::set_frame_color_code, "frame-color", UIntColorConverter ()) + - tl::make_member (&LayerPropertiesNode::fill_color_loc, &LayerPropertiesNode::set_fill_color_code, "fill-color", UIntColorConverter ()) + + tl::make_member (&LayerPropertiesNode::expanded, &LayerPropertiesNode::set_expanded, "expanded") + + tl::make_member (&LayerPropertiesNode::frame_color_loc, &LayerPropertiesNode::set_frame_color_code, "frame-color", UIntColorConverter ()) + + tl::make_member (&LayerPropertiesNode::fill_color_loc, &LayerPropertiesNode::set_fill_color_code, "fill-color", UIntColorConverter ()) + tl::make_member (&LayerPropertiesNode::frame_brightness_loc, &LayerPropertiesNode::set_frame_brightness, "frame-brightness") + tl::make_member (&LayerPropertiesNode::fill_brightness_loc, &LayerPropertiesNode::set_fill_brightness, "fill-brightness") + tl::make_member (&LayerPropertiesNode::dither_pattern_loc, &LayerPropertiesNode::set_dither_pattern, "dither-pattern", DitherPatternIndexConverter ()) + @@ -2061,6 +2085,16 @@ LayerPropertiesNodeRef::need_realize (unsigned int flags, bool force) } } +void +LayerPropertiesNodeRef::expanded_state_changed () +{ + LayerPropertiesNode::expanded_state_changed (); + + if (is_valid ()) { + view ()->set_layer_node_expanded (m_iter, expanded ()); + } +} + void LayerPropertiesNodeRef::refresh () const { diff --git a/src/laybasic/laybasic/layLayerProperties.h b/src/laybasic/laybasic/layLayerProperties.h index 60c7f79f1..4318dbab1 100644 --- a/src/laybasic/laybasic/layLayerProperties.h +++ b/src/laybasic/laybasic/layLayerProperties.h @@ -919,6 +919,11 @@ protected: */ virtual void need_realize (unsigned int flags, bool force = false); + /** + * @brief indicates a change of the collapsed/expanded state + */ + virtual void expanded_state_changed (); + /** * @brief Fetches the current status from the original properties for the LayerPropertiesNodeRef implementation */ @@ -1069,6 +1074,20 @@ public: return r; } + /** + * @brief Sets the expanded state of the layer properties tree node + */ + void set_expanded (bool ex); + + /** + * @brief Gets the expanded state of the layer properties node + */ + bool expanded () const + { + refresh (); + return m_expanded; + } + /** * @brief Child layers: begin iterator */ @@ -1207,14 +1226,21 @@ public: virtual void realize_source () const; virtual void realize_visual () const; + void set_expanded_silent (bool ex) + { + m_expanded = ex; + } + protected: virtual void need_realize (unsigned int flags, bool force); + virtual void expanded_state_changed (); void set_parent (const LayerPropertiesNode *); private: // A reference to the view tl::weak_ptr mp_view; unsigned int m_list_index; + bool m_expanded; // the parent node tl::weak_ptr mp_parent; // the list of children @@ -2009,8 +2035,9 @@ private: tl::weak_ptr mp_node; size_t m_synched_gen_id; - void need_realize (unsigned int flags, bool force); - void refresh () const; + virtual void need_realize (unsigned int flags, bool force); + virtual void expanded_state_changed (); + virtual void refresh () const; }; } diff --git a/src/laybasic/laybasic/layLayoutViewBase.cc b/src/laybasic/laybasic/layLayoutViewBase.cc index bf711a53d..908ef1ff1 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.cc +++ b/src/laybasic/laybasic/layLayoutViewBase.cc @@ -1880,6 +1880,21 @@ LayoutViewBase::replace_layer_node (unsigned int index, const LayerPropertiesCon } } +void +LayoutViewBase::set_layer_node_expanded (unsigned int index, const LayerPropertiesConstIterator &iter, bool ex) +{ + if (ex != iter->expanded ()) { + + LayerPropertiesIterator non_const_iter (get_properties (index), iter.uint ()); + non_const_iter->set_expanded (ex); + + if (index == current_layer_list ()) { + layer_list_changed_event (8 /*expanded state needs update*/); + } + + } +} + void LayoutViewBase::set_properties (unsigned int index, const LayerPropertiesConstIterator &iter, const LayerProperties &props) { diff --git a/src/laybasic/laybasic/layLayoutViewBase.h b/src/laybasic/laybasic/layLayoutViewBase.h index 7d6257c19..0263a208a 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.h +++ b/src/laybasic/laybasic/layLayoutViewBase.h @@ -335,6 +335,17 @@ public: set_properties (current_layer_list (), iter, props); } + /** + * @brief Sets a value indicating whether the given node is expanded in the layer tree + * + * @param iter Points to the layer node to be modified + * @param ex True if the layer node shall be expanded, false if it shall be collapsed + */ + void set_layer_node_expanded (const LayerPropertiesConstIterator &iter, bool ex) + { + set_layer_node_expanded (current_layer_list (), iter, ex); + } + /** * @brief Set the layer properties of a layer with the given position (by iterator) for the layer list with the given index * @@ -344,6 +355,15 @@ public: */ void set_properties (unsigned int index, const LayerPropertiesConstIterator &iter, const LayerProperties &props); + /** + * @brief Sets a value indicating whether the given node is expanded in the layer tree + * + * @param index The layer list's index + * @param iter Points to the layer node to be modified + * @param ex True if the layer node shall be expanded, false if it shall be collapsed + */ + void set_layer_node_expanded (unsigned int index, const LayerPropertiesConstIterator &iter, bool ex); + /** * @brief Expand the layer properties of all tabs * diff --git a/src/layui/layui/layLayerControlPanel.cc b/src/layui/layui/layLayerControlPanel.cc index 4234bc4ae..31b3bacf2 100644 --- a/src/layui/layui/layLayerControlPanel.cc +++ b/src/layui/layui/layLayerControlPanel.cc @@ -205,6 +205,7 @@ LayerControlPanel::LayerControlPanel (lay::LayoutViewBase *view, db::Manager *ma db::Object (manager), mp_view (view), m_needs_update (true), + m_expanded_state_needs_update (false), m_tabs_need_update (true), m_hidden_flags_need_update (true), m_in_update (false), @@ -1696,6 +1697,7 @@ LayerControlPanel::cancel_updates () { m_in_update = false; m_needs_update = false; + m_expanded_state_needs_update = false; m_hidden_flags_need_update = false; m_tabs_need_update = false; } @@ -1874,11 +1876,13 @@ LayerControlPanel::do_update_content () } if (m_hidden_flags_need_update) { - do_update_hidden_flags (); - m_hidden_flags_need_update = false; + } + if (m_expanded_state_needs_update) { + restore_expanded (); + m_expanded_state_needs_update = false; } } @@ -1993,6 +1997,11 @@ LayerControlPanel::signal_li_changed (int) void LayerControlPanel::update_required (int f) { + // the name of a layer list has changed + if ((f & 8) != 0) { + m_expanded_state_needs_update = true; + } + // the name of a layer list has changed if ((f & 4) != 0) { m_tabs_need_update = true; @@ -2032,18 +2041,18 @@ LayerControlPanel::current_index_changed (const QModelIndex &index) void LayerControlPanel::group_collapsed (const QModelIndex &index) { - lay::LayerPropertiesConstIterator iter = mp_model->iterator (index); + auto iter = mp_model->iterator_nc (index); if (! iter.is_null () && ! iter.at_end ()) { - m_expanded.erase (iter->id ()); + iter->set_expanded_silent (false); } } void LayerControlPanel::group_expanded (const QModelIndex &index) { - lay::LayerPropertiesConstIterator iter = mp_model->iterator (index); + auto iter = mp_model->iterator_nc (index); if (! iter.is_null () && ! iter.at_end ()) { - m_expanded.insert (iter->id ()); + iter->set_expanded_silent (true); } } @@ -2052,33 +2061,16 @@ LayerControlPanel::restore_expanded () { mp_layer_list->blockSignals (true); -#if 1 - // By keeping m_expanded, we can preserve the expansion state of different tabs. - // However we will always continue filling m_expanded. lay::LayerPropertiesConstIterator l = mp_view->begin_layers (); while (! l.at_end ()) { - if (m_expanded.find (l->id ()) != m_expanded.end ()) { - QModelIndex index = mp_model->index (l, 0); + QModelIndex index = mp_model->index (l, 0); + if (l->expanded ()) { mp_layer_list->expand (index); + } else { + mp_layer_list->collapse (index); } ++l; } -#else - // this solution will forget the other tab's expansion flags. - std::set new_expanded; - - lay::LayerPropertiesConstIterator l = mp_view->begin_layers (); - while (! l.at_end ()) { - if (m_expanded.find (l->id ()) != m_expanded.end ()) { - new_expanded.insert (l->id ()); - QModelIndex index = mp_model->index (l, 0); - mp_layer_list->expand (index); - } - ++l; - } - - m_expanded.swap (new_expanded); -#endif mp_layer_list->blockSignals (false); } @@ -2287,7 +2279,7 @@ public: menu_entries.push_back (lay::menu_item ("cm_lv_select_all", "select_all", at, tl::to_string (QObject::tr ("Select All")))); // It is not sure, whether "expandAll" destabilizes the tree widget: - // menu_entries.push_back (lay::menu_item ("cm_lv_expand_all", "expand_all", at, tl::to_string (QObject::tr ("Expand All"))); + // menu_entries.push_back (lay::menu_item ("cm_lv_expand_all", "expand_all", at, tl::to_string (QObject::tr ("Expand All")))); menu_entries.push_back (lay::separator ("tab_group", at)); menu_entries.push_back (lay::submenu ("tab_menu", at, tl::to_string (QObject::tr ("Tabs")))); diff --git a/src/layui/layui/layLayerControlPanel.h b/src/layui/layui/layLayerControlPanel.h index 9e38da689..40134c9e5 100644 --- a/src/layui/layui/layLayerControlPanel.h +++ b/src/layui/layui/layLayerControlPanel.h @@ -352,6 +352,7 @@ private: LayerTreeModel *mp_model; lay::LayoutViewBase *mp_view; bool m_needs_update; + bool m_expanded_state_needs_update; bool m_tabs_need_update; bool m_hidden_flags_need_update; bool m_in_update; @@ -360,7 +361,6 @@ private: int m_oversampling; bool m_hrm; tl::DeferredMethod m_do_update_content_dm; - std::set m_expanded; bool m_no_stipples; QLabel *m_no_stipples_label; lay::DecoratedLineEdit *mp_search_edit_box; diff --git a/src/layui/layui/layLayerTreeModel.cc b/src/layui/layui/layLayerTreeModel.cc index 36e3a3be8..a8f733c61 100644 --- a/src/layui/layui/layLayerTreeModel.cc +++ b/src/layui/layui/layLayerTreeModel.cc @@ -756,7 +756,20 @@ LayerTreeModel::iterator (const QModelIndex &index) const return lay::LayerPropertiesConstIterator (); } -QModelIndex +lay::LayerPropertiesIterator +LayerTreeModel::iterator_nc (const QModelIndex &index) +{ + if (index.isValid ()) { + size_t iter_index = size_t (index.internalPointer ()); + if (mp_view->layer_lists () > 0 && iter_index >= m_id_start && iter_index < m_id_end) { + return lay::LayerPropertiesIterator (mp_view->get_properties (), iter_index - m_id_start); + } + } + + return lay::LayerPropertiesIterator (); +} + +QModelIndex LayerTreeModel::index (lay::LayerPropertiesConstIterator iter, int column) const { try { diff --git a/src/layui/layui/layLayerTreeModel.h b/src/layui/layui/layLayerTreeModel.h index 94c5af84e..7071a2438 100644 --- a/src/layui/layui/layLayerTreeModel.h +++ b/src/layui/layui/layLayerTreeModel.h @@ -51,6 +51,7 @@ namespace lay class LayoutViewBase; class LayerPropertiesConstIterator; +class LayerPropertiesIterator; /** * @brief A helper class implementing a cache for the "test shapes in view" feature @@ -107,6 +108,16 @@ public: virtual QModelIndex index (int row, int column, const QModelIndex &parent) const; virtual QModelIndex parent (const QModelIndex &index) const; + /** + * @brief Sets the expanded state for a given model index + */ + void set_expanded (const QModelIndex &index, bool ex); + + /** + * @brief Gets the expanded state for a given model index + */ + bool expanded (const QModelIndex &index) const; + /** * @brief Provides an icon for a given layer style */ @@ -127,6 +138,11 @@ public: */ lay::LayerPropertiesConstIterator iterator (const QModelIndex &index) const; + /** + * @brief Converts a QModelIndex to an iterator (non-const) + */ + lay::LayerPropertiesIterator iterator_nc (const QModelIndex &index); + /** * @brief Gets a flag indicating that an entry is hidden */ diff --git a/testdata/ruby/layLayers.rb b/testdata/ruby/layLayers.rb index 8bf617f78..1f08758a9 100644 --- a/testdata/ruby/layLayers.rb +++ b/testdata/ruby/layLayers.rb @@ -667,12 +667,18 @@ class LAYLayers_TestClass < TestBase p.clear_line_style assert_equal( p.has_line_style?, false ) + assert_equal( p.is_expanded?, false ) + p.expanded = true + assert_equal( p.is_expanded?, true ) + pp = RBA::LayerPropertiesNode::new assert_equal( pp == p, false ) assert_equal( pp != p, true ) + assert_equal( pp.is_expanded?, false ) pp = p.dup assert_equal( pp == p, true ) assert_equal( pp != p, false ) + assert_equal( pp.is_expanded?, true ) end From 3e42106ddf9d628aa035c7f5d427a7341513d7f9 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 18 Feb 2023 00:08:29 +0100 Subject: [PATCH 12/19] Provide a true compare for pixel buffer test (otherwise, only the object references are compared) --- testdata/python/layPixelBuffer.py | 44 ++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/testdata/python/layPixelBuffer.py b/testdata/python/layPixelBuffer.py index a37e77f92..9806395a4 100644 --- a/testdata/python/layPixelBuffer.py +++ b/testdata/python/layPixelBuffer.py @@ -21,27 +21,41 @@ import unittest import os import sys +def compare(pb1, pb2): + + if pb1.width != pb2.width or pb1.height != pb2.height: + return False + + for x in range(0, pb1.width): + for y in range(0, pb1.height): + if pb1.pixel(x, y) != pb2.pixel(x, y): + return False + + return True + + class LAYPixelBufferTests(unittest.TestCase): - def test_4(self): - pb = pya.PixelBuffer(10, 20) - pb.transparent = True - pb.fill(0xf0010203) + def test_1(self): - png = pb.to_png_data() + pb = pya.PixelBuffer(10, 20) + pb.transparent = True + pb.fill(0xf0010203) - # some range because implementations may differ - self.assertGreater(len(png), 20) - self.assertLess(len(png), 200) - pb_copy = pya.PixelBuffer.from_png_data(png) - self.assertEqual(pb, pb_copy) + png = pb.to_png_data() - ut_testtmp = os.getenv("TESTTMP", ".") - tmp = os.path.join(ut_testtmp, "tmp.png") + # some range because implementations may differ + self.assertGreater(len(png), 20) + self.assertLess(len(png), 200) + pb_copy = pya.PixelBuffer.from_png_data(png) + self.assertEqual(pb, pb_copy) - pb.write_png(tmp) - pb_copy = pya.PixelBuffer.read_png(tmp) - self.assertEqual(pb, pb_copy) + ut_testtmp = os.getenv("TESTTMP", ".") + tmp = os.path.join(ut_testtmp, "tmp.png") + + pb.write_png(tmp) + pb_copy = pya.PixelBuffer.read_png(tmp) + self.assertEqual(pb, pb_copy) # run unit tests From 1e718c3d864c983cc2fc15a117869496809f1b05 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 18 Feb 2023 00:50:18 +0100 Subject: [PATCH 13/19] Rectified previous patch --- testdata/python/layPixelBuffer.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testdata/python/layPixelBuffer.py b/testdata/python/layPixelBuffer.py index 9806395a4..b9cba810e 100644 --- a/testdata/python/layPixelBuffer.py +++ b/testdata/python/layPixelBuffer.py @@ -23,11 +23,11 @@ import sys def compare(pb1, pb2): - if pb1.width != pb2.width or pb1.height != pb2.height: + if pb1.width() != pb2.width() or pb1.height() != pb2.height(): return False - for x in range(0, pb1.width): - for y in range(0, pb1.height): + for x in range(0, pb1.width()): + for y in range(0, pb1.height()): if pb1.pixel(x, y) != pb2.pixel(x, y): return False @@ -55,7 +55,7 @@ class LAYPixelBufferTests(unittest.TestCase): pb.write_png(tmp) pb_copy = pya.PixelBuffer.read_png(tmp) - self.assertEqual(pb, pb_copy) + self.assertEqual(compare(pb, pb_copy), True) # run unit tests From 0a15425745143c2aece646e3409c8b74c3563d99 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 18 Feb 2023 09:49:03 +0100 Subject: [PATCH 14/19] Make pixelBuffer test work (hopefully) --- testdata/python/layPixelBuffer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testdata/python/layPixelBuffer.py b/testdata/python/layPixelBuffer.py index b9cba810e..6ee8c3d28 100644 --- a/testdata/python/layPixelBuffer.py +++ b/testdata/python/layPixelBuffer.py @@ -48,7 +48,7 @@ class LAYPixelBufferTests(unittest.TestCase): self.assertGreater(len(png), 20) self.assertLess(len(png), 200) pb_copy = pya.PixelBuffer.from_png_data(png) - self.assertEqual(pb, pb_copy) + self.assertEqual(compare(pb, pb_copy), True) ut_testtmp = os.getenv("TESTTMP", ".") tmp = os.path.join(ut_testtmp, "tmp.png") From 8038acc23630e7e22c1527891374c3f6aae9373d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 18 Feb 2023 09:50:34 +0100 Subject: [PATCH 15/19] Updated test data --- src/laybasic/unit_tests/layLayerProperties.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/laybasic/unit_tests/layLayerProperties.cc b/src/laybasic/unit_tests/layLayerProperties.cc index f6175a348..26e7ecb20 100644 --- a/src/laybasic/unit_tests/layLayerProperties.cc +++ b/src/laybasic/unit_tests/layLayerProperties.cc @@ -135,6 +135,7 @@ TEST (1) "\n" "\n" " \n" + " false\n" " \n" " \n" " 0\n" From f8b865e4e08028632193bdae74c7c7accc8c8bde Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 19 Feb 2023 12:55:31 +0100 Subject: [PATCH 16/19] Generalizing Jenkinsfile --- Jenkinsfile-linux | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 Jenkinsfile-linux diff --git a/Jenkinsfile-linux b/Jenkinsfile-linux new file mode 100644 index 000000000..0bb82e97d --- /dev/null +++ b/Jenkinsfile-linux @@ -0,0 +1,65 @@ + +@Library("osconfig") _ + +properties([disableConcurrentBuilds()]) + +// from shared library +target = osconfig() + +currentBuild.description = "Pipelined " + target + +node("linux") { + + artefacts = pwd() + "/artefacts" + target_dir = artefacts + "/" + target + + stage("Checkout sources") { + + checkout scm + checkout_private() + + } + + stage("Building target ${target}") { + + withDockerContainer(image: "jenkins-${target}") { + // from shared library + build(target, target_dir) + } + + } + + stage("Publish and test") { + + parallel( + "Publish": { + + // from shared library - only publish for normal branch, not for PR + if (! BRANCH_NAME.startsWith('PR')) { + publish(BRANCH_NAME, target, target_dir) + } + + }, + "Unit testing": { + + ut_result = "no-result" + withDockerContainer(image: "jenkins-${target}") { + ut_result = run_ut(target) + } + + junit(testResults: ut_result) + + }, + "Installtest": { + + withDockerContainer(image: "jenkins-${target}-basic") { + // from shared library + installtest_nopython(target, target_dir) + } + + }) + + } + +} + From 82f9a7543d490091cd868422be7c02b3d4334f29 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 24 Feb 2023 00:00:40 +0100 Subject: [PATCH 17/19] Added docker_args config to multipipeline Jenkins file for Linux cluster --- Jenkinsfile-linux | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile-linux b/Jenkinsfile-linux index 0bb82e97d..4b59d2ff1 100644 --- a/Jenkinsfile-linux +++ b/Jenkinsfile-linux @@ -5,6 +5,7 @@ properties([disableConcurrentBuilds()]) // from shared library target = osconfig() +docker_args = docker_args() currentBuild.description = "Pipelined " + target @@ -22,7 +23,7 @@ node("linux") { stage("Building target ${target}") { - withDockerContainer(image: "jenkins-${target}") { + withDockerContainer(image: "jenkins-${target}", args: docker_args) { // from shared library build(target, target_dir) } @@ -43,7 +44,7 @@ node("linux") { "Unit testing": { ut_result = "no-result" - withDockerContainer(image: "jenkins-${target}") { + withDockerContainer(image: "jenkins-${target}", args: docker_args) { ut_result = run_ut(target) } @@ -52,7 +53,7 @@ node("linux") { }, "Installtest": { - withDockerContainer(image: "jenkins-${target}-basic") { + withDockerContainer(image: "jenkins-${target}-basic", args: docker_args) { // from shared library installtest_nopython(target, target_dir) } From 3ac791234a7e8e6aadbf95b2502cb6bc7e2556cc Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 24 Feb 2023 14:47:23 +0100 Subject: [PATCH 18/19] Adjusting Jenkinsfiles to Linux cluster --- Jenkinsfile-publish-doc | 2 +- Jenkinsfile-publish-sources | 2 +- Jenkinsfile-pypi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile-publish-doc b/Jenkinsfile-publish-doc index e7a3f453b..24db16275 100644 --- a/Jenkinsfile-publish-doc +++ b/Jenkinsfile-publish-doc @@ -3,7 +3,7 @@ properties([disableConcurrentBuilds()]) -node("master") { +node("linux") { stage("Checkout sources") { checkout scm diff --git a/Jenkinsfile-publish-sources b/Jenkinsfile-publish-sources index 0ed9f228e..91ac205f1 100644 --- a/Jenkinsfile-publish-sources +++ b/Jenkinsfile-publish-sources @@ -3,7 +3,7 @@ properties([disableConcurrentBuilds()]) -node("master") { +node("linux") { stage("Checkout sources") { checkout scm diff --git a/Jenkinsfile-pypi b/Jenkinsfile-pypi index 632fab52e..44d0e6d2f 100644 --- a/Jenkinsfile-pypi +++ b/Jenkinsfile-pypi @@ -14,7 +14,7 @@ currentBuild.description = "PyPI deployment " + platform docker_image = "jenkins-manylinux2014_x86_64-pypi" target = platform + ".whl" -node("master") { +node("linux") { stage("Checkout sources") { checkout scm From 3bef4917ad748446eaf554c9410fb04134d19267 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 24 Feb 2023 18:33:24 +0100 Subject: [PATCH 19/19] Fixed doc publishing Jenkinsfile --- Jenkinsfile-publish-doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile-publish-doc b/Jenkinsfile-publish-doc index 24db16275..619c89019 100644 --- a/Jenkinsfile-publish-doc +++ b/Jenkinsfile-publish-doc @@ -10,7 +10,7 @@ node("linux") { } stage("Producing doc") { - sh "./scripts/extract_user_doc.sh -i " + BRANCH_NAME + linux_sh "./scripts/extract_user_doc.sh -i " + BRANCH_NAME } stage("Publish doc") {