From 0ecc8ee093d2c088e3f6e392d50f67cb1c798a52 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 4 Sep 2017 23:05:46 +0200 Subject: [PATCH] First version of DEF reader with GROUPS/REGIONS - needs feedback. --- src/ext/ext/LEFDEFImportOptionsDialog.ui | 10 +- .../ext/LEFDEFTechnologyComponentEditor.ui | 464 ++++++++++-------- src/ext/ext/extDEFImporter.cc | 193 +++++++- src/ext/ext/extLEFDEFImportDialogs.cc | 21 + src/ext/ext/extLEFDEFImporter.cc | 24 +- src/ext/ext/extLEFDEFImporter.h | 67 ++- src/ext/ext/extLEFDEFPlugin.cc | 4 + src/klayout.pro | 3 +- 8 files changed, 555 insertions(+), 231 deletions(-) diff --git a/src/ext/ext/LEFDEFImportOptionsDialog.ui b/src/ext/ext/LEFDEFImportOptionsDialog.ui index 9a6c17577..6be94aaf0 100644 --- a/src/ext/ext/LEFDEFImportOptionsDialog.ui +++ b/src/ext/ext/LEFDEFImportOptionsDialog.ui @@ -190,7 +190,7 @@ ... - + :/clear.png:/clear.png @@ -204,7 +204,7 @@ ... - + :/add.png:/add.png @@ -218,7 +218,7 @@ ... - + :/up.png:/up.png @@ -232,7 +232,7 @@ ... - + :/down.png:/down.png @@ -298,7 +298,7 @@ buttonBox - + diff --git a/src/ext/ext/LEFDEFTechnologyComponentEditor.ui b/src/ext/ext/LEFDEFTechnologyComponentEditor.ui index 39f459531..7ec26182d 100644 --- a/src/ext/ext/LEFDEFTechnologyComponentEditor.ui +++ b/src/ext/ext/LEFDEFTechnologyComponentEditor.ui @@ -113,7 +113,7 @@ ... - + :/clear.png:/clear.png @@ -140,7 +140,7 @@ ... - + :/down.png:/down.png @@ -167,7 +167,7 @@ ... - + :/add.png:/add.png @@ -181,7 +181,7 @@ ... - + :/up.png:/up.png @@ -264,18 +264,126 @@ 6 - - + + - Layer name suffix ... + + + + :/right.png - - + + + + + + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + + + + Blockages + + + + + + + + 0 + 0 + + + + + + + :/right.png + + + + + + + + + + On layer with spec ... + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + Pin labels + + + + + + + Pins + + + + + + + Via geometry + + + + + + + Routing + + + + + Produce ... + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + + 0 + 0 + + + + Cell outlines + @@ -285,32 +393,65 @@ - - - - Qt::Vertical - - + + - - + + + + + + + Layer name suffix ... + + + + + + + + + + As properties with name ... + + - - + + + + + 0 + 0 + + + + Blockages + + - - + + + + + 0 + 0 + + + + + + + :/right.png + + - - - - + <html><body>(<a href="int:/about/variant_notation.xml">See here for the name notation</a>)</body></html> @@ -320,6 +461,12 @@ + + + + + + @@ -334,115 +481,22 @@ - - - - - - - Pins - - - - - - - Routing - - - - - - - - - - - - - Obstructions - - - - - - - - - - Via geometry - - - - - - - As properties with name ... - - - - - - - - - - Pin labels - - - - - - - - + + - + 0 0 - Blockages + + + + :/right.png - - - - - - - - 0 - 0 - - - - Cell outlines - - - - - - - Blockages - - - - - - - On layer with spec ... - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - @@ -455,12 +509,25 @@ - :/right.png + :/right.png - - + + + + + 0 + 0 + + + + + + + :/right.png + + @@ -474,10 +541,20 @@ - :/right.png + :/right.png + + + + Inst names + + + + + + @@ -493,37 +570,8 @@ - - - - - 0 - 0 - - - - - - - :/right.png - - - - - - - - 0 - 0 - - - - - - - :/right.png - - + + @@ -537,51 +585,12 @@ - :/right.png + :/right.png - - - - Produce ... - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - - 0 - 0 - - - - - - - :/right.png - - - - - - - - 0 - 0 - - - - - - - :/right.png - - + + @@ -595,26 +604,57 @@ - :/right.png + :/right.png - - - - - 0 - 0 - + + + + + + + Obstructions + + + + + + + + + Produce ... + + + + + + + Regions + + + + + - :/right.png + :/right.png + + + + Qt::Vertical + + + + + + @@ -734,7 +774,7 @@ read_all_cbx - + diff --git a/src/ext/ext/extDEFImporter.cc b/src/ext/ext/extDEFImporter.cc index 4ab18aa5a..87b499929 100644 --- a/src/ext/ext/extDEFImporter.cc +++ b/src/ext/ext/extDEFImporter.cc @@ -23,6 +23,7 @@ #include "extDEFImporter.h" #include "dbPolygonTools.h" +#include "tlGlobPattern.h" #include @@ -124,6 +125,28 @@ DEFImporter::read_rect (db::Polygon &poly, double scale) poly = db::Polygon (db::Box (pt1, pt2)); } +struct Group +{ + Group (const std::string &n, const std::string &rn, const std::vector &m) + : name (n), region_name (rn), comp_match (m) + { + // .. nothing yet .. + } + + bool comp_matches (const std::string &name) const + { + for (std::vector::const_iterator m = comp_match.begin (); m != comp_match.end (); ++m) { + if (m->match (name)) { + return true; + } + } + return false; + } + + std::string name, region_name; + std::vector comp_match; +}; + void DEFImporter::do_read (db::Layout &layout) { @@ -131,6 +154,9 @@ DEFImporter::do_read (db::Layout &layout) double scale = 1.0 / (dbu_mic * layout.dbu ()); std::map styles; std::map via_desc; + std::map > regions; + std::list groups; + std::list > instances; db::Cell &design = layout.cell (layout.add_cell ("TOP")); @@ -241,10 +267,43 @@ DEFImporter::do_read (db::Layout &layout) test ("NONDEFAULTRULES"); } else if (test ("REGIONS")) { - // read over REGIONS statements - while (! test ("END") || ! test ("REGIONS")) { - take (); + + // Read REGION statements + get_long (); + expect (";"); + + while (test ("-")) { + + std::string n = get (); + std::vector &polygons = regions [n]; + + while (! peek (";")) { + + if (test ("+")) { + + // ignore other options for now + while (! peek (";")) { + take (); + } + break; + + } else { + + db::Polygon box; + read_rect (box, scale); + polygons.push_back (box); + + } + + } + + test (";"); + } + + test ("END"); + test ("REGIONS"); + } else if (test ("PINPROPERTIES")) { // read over PINPROPERTIES statements while (! test ("END") || ! test ("PINPROPERTIES")) { @@ -266,10 +325,49 @@ DEFImporter::do_read (db::Layout &layout) take (); } } else if (test ("GROUPS")) { - // read over GROUPS statements - while (! test ("END") || ! test ("GROUPS")) { - take (); + + // Read GROUPS statements + get_long (); + expect (";"); + + while (test ("-")) { + + std::string n = get (); + std::string rn; + std::vector match; + + while (! peek (";")) { + + if (test ("+")) { + + // gets the region name if there is one + if (test ("REGION")) { + rn = get (); + } + + // ignore the reset for now + while (! peek (";")) { + take (); + } + break; + + } else { + + match.push_back (tl::GlobPattern (get ())); + + } + + } + + groups.push_back (Group (n, rn, match)); + + test (";"); + } + + test ("END"); + test ("GROUPS"); + } else if (test ("BEGINEXT")) { // read over BEGINEXT sections while (! test ("ENDEXT")) { @@ -896,7 +994,7 @@ DEFImporter::do_read (db::Layout &layout) while (test ("-")) { - take (); // instance name + std::string inst_name = get (); std::string model = get (); db::Cell *cell = m_lef_importer.macro_by_name (model); @@ -915,9 +1013,10 @@ DEFImporter::do_read (db::Layout &layout) db::Vector d = pt - m_lef_importer.macro_bbox_by_name (model).transformed (ft).lower_left (); if (cell) { - design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), d))); + db::CellInstArray inst (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), d)); + instances.push_back (std::make_pair (inst_name, inst)); } else { - warn (tl::to_string (QObject::tr ("Macro not found in LEF file: ")) + model); + warn (tl::to_string (QObject::tr ("Macro not found in LEF file: ")) + model); } } else { @@ -1086,6 +1185,82 @@ DEFImporter::do_read (db::Layout &layout) } } + + // now we have collected the groups, regions and instances we create new subcells for each group + // and put the instances for this group there + + db::Cell *others_cell = &design; + + if (! groups.empty ()) { + + others_cell = &layout.cell (layout.add_cell ("NOGROUP")); + design.insert (db::CellInstArray (others_cell->cell_index (), db::Trans ())); + + // Walk through the groups, create a group container cell and put all instances + // that match the group match string there. Then delete these cells (spec says "do not assign any component to more than one group"). + + for (std::list::const_iterator g = groups.begin (); g != groups.end (); ++g) { + + db::Cell *group_cell = &layout.cell (layout.add_cell (("GROUP_" + g->name).c_str ())); + design.insert (db::CellInstArray (group_cell->cell_index (), db::Trans ())); + + if (! g->region_name.empty ()) { + + std::map >::const_iterator r = regions.find (g->region_name); + if (r == regions.end ()) { + warn (tl::to_string (QObject::tr ("Not a valid region name: %1 in group %2").arg (tl::to_qstring (g->region_name).arg (tl::to_qstring (g->name))))); + } else { + std::pair dl = open_layer (layout, std::string (), Region); + if (dl.first) { + for (std::vector::const_iterator p = r->second.begin (); p != r->second.end (); ++p) { + group_cell->shapes (dl.second).insert (*p); + } + } + } + + } + + if (! g->comp_match.empty ()) { + + for (std::list >::iterator i = instances.begin (); i != instances.end (); ) { + + std::list >::iterator ii = i++; + if (g->comp_matches (ii->first)) { + + if (produce_inst_props ()) { + db::PropertiesRepository::properties_set props; + props.insert (std::make_pair (inst_prop_name_id (), tl::Variant (ii->first))); + group_cell->insert (db::CellInstArrayWithProperties (ii->second, layout.properties_repository ().properties_id (props))); + } else { + group_cell->insert (ii->second); + } + + instances.erase (ii); + + } + + } + + } + + } + + } + + // treat all remaining cells and put them into the "others_cell" which is the top cell + // if there are no groups. + + for (std::list >::iterator ii = instances.begin (); ii != instances.end (); ++ii) { + + if (produce_inst_props ()) { + db::PropertiesRepository::properties_set props; + props.insert (std::make_pair (inst_prop_name_id (), tl::Variant (ii->first))); + others_cell->insert (db::CellInstArrayWithProperties (ii->second, layout.properties_repository ().properties_id (props))); + } else { + others_cell->insert (ii->second); + } + + } } } diff --git a/src/ext/ext/extLEFDEFImportDialogs.cc b/src/ext/ext/extLEFDEFImportDialogs.cc index dfc978afc..8d09bdf01 100644 --- a/src/ext/ext/extLEFDEFImportDialogs.cc +++ b/src/ext/ext/extLEFDEFImportDialogs.cc @@ -345,8 +345,10 @@ LEFDEFReaderOptionsEditor::LEFDEFReaderOptionsEditor (QWidget *parent) setupUi (this); connect (produce_net_names, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); + connect (produce_inst_names, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); connect (produce_outlines, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); connect (produce_placement_blockages, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); + connect (produce_regions, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); connect (produce_via_geometry, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); connect (produce_pins, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); connect (produce_obstructions, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ())); @@ -372,6 +374,7 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con data->set_read_all_layers (read_all_cbx->isChecked ()); data->set_layer_map (layer_map->get_layer_map ()); data->set_produce_net_names (produce_net_names->isChecked ()); + data->set_produce_inst_names (produce_inst_names->isChecked ()); double dbu_value = 0.0; tl::from_string (tl::to_string (dbu->text ()), dbu_value); @@ -390,8 +393,20 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con data->set_net_property_name (v); } + // parse the inst property name (may throw an exception) + { + std::string np = tl::to_string (inst_prop_name->text ()); + tl::Extractor ex (np.c_str ()); + tl::Variant v; + ex.read (v); + ex.expect_end (); + data->set_inst_property_name (v); + } + data->set_produce_cell_outlines (produce_outlines->isChecked ()); data->set_cell_outline_layer (tl::to_string (outline_layer->text ())); + data->set_produce_regions (produce_regions->isChecked ()); + data->set_region_layer (tl::to_string (region_layer->text ())); data->set_produce_placement_blockages (produce_placement_blockages->isChecked ()); data->set_placement_blockage_layer (tl::to_string (placement_blockage_layer->text ())); data->set_produce_via_geometry (produce_via_geometry->isChecked ()); @@ -436,8 +451,12 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options layer_map->set_layer_map (data->layer_map ()); produce_net_names->setChecked (data->produce_net_names ()); net_prop_name->setText (tl::to_qstring (data->net_property_name ().to_parsable_string ())); + produce_inst_names->setChecked (data->produce_inst_names ()); + inst_prop_name->setText (tl::to_qstring (data->inst_property_name ().to_parsable_string ())); produce_outlines->setChecked (data->produce_cell_outlines ()); outline_layer->setText (tl::to_qstring (data->cell_outline_layer ())); + produce_regions->setChecked (data->produce_regions ()); + region_layer->setText (tl::to_qstring (data->region_layer ())); produce_placement_blockages->setChecked (data->produce_placement_blockages ()); placement_blockage_layer->setText (tl::to_qstring (data->placement_blockage_layer ())); produce_via_geometry->setChecked (data->produce_via_geometry ()); @@ -478,7 +497,9 @@ void LEFDEFReaderOptionsEditor::checkbox_changed () { net_prop_name->setEnabled (produce_net_names->isChecked ()); + inst_prop_name->setEnabled (produce_inst_names->isChecked ()); outline_layer->setEnabled (produce_outlines->isChecked ()); + region_layer->setEnabled (produce_regions->isChecked ()); placement_blockage_layer->setEnabled (produce_placement_blockages->isChecked ()); suffix_via_geometry->setEnabled (produce_via_geometry->isChecked ()); suffix_pins->setEnabled (produce_pins->isChecked ()); diff --git a/src/ext/ext/extLEFDEFImporter.cc b/src/ext/ext/extLEFDEFImporter.cc index 0914eb166..2039ca399 100644 --- a/src/ext/ext/extLEFDEFImporter.cc +++ b/src/ext/ext/extLEFDEFImporter.cc @@ -42,10 +42,14 @@ LEFDEFReaderOptions::LEFDEFReaderOptions () m_dbu (0.001), m_produce_net_names (true), m_net_property_name (1), + m_produce_inst_names (true), + m_inst_property_name (1), m_produce_cell_outlines (true), m_cell_outline_layer ("OUTLINE"), m_produce_placement_blockages (true), m_placement_blockage_layer ("PLACEMENT_BLK"), + m_produce_regions (true), + m_region_layer ("REGIONS"), m_produce_via_geometry (true), m_via_geometry_suffix (""), m_via_geometry_datatype (0), @@ -74,10 +78,14 @@ LEFDEFReaderOptions::LEFDEFReaderOptions (const LEFDEFReaderOptions &d) m_dbu (d.m_dbu), m_produce_net_names (d.m_produce_net_names), m_net_property_name (d.m_net_property_name), + m_produce_inst_names (d.m_produce_inst_names), + m_inst_property_name (d.m_inst_property_name), m_produce_cell_outlines (d.m_produce_cell_outlines), m_cell_outline_layer (d.m_cell_outline_layer), m_produce_placement_blockages (d.m_produce_placement_blockages), m_placement_blockage_layer (d.m_placement_blockage_layer), + m_produce_regions (d.m_produce_regions), + m_region_layer (d.m_region_layer), m_produce_via_geometry (d.m_produce_via_geometry), m_via_geometry_suffix (d.m_via_geometry_suffix), m_via_geometry_datatype (d.m_via_geometry_datatype), @@ -136,7 +144,7 @@ LEFDEFLayerDelegate::register_layer (const std::string &ln) std::pair LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, LayerPurpose purpose) { - if (purpose == Outline || purpose == PlacementBlockage) { + if (purpose == Outline || purpose == PlacementBlockage || purpose == Region) { std::string ld; bool produce; @@ -144,6 +152,9 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer if (purpose == Outline) { produce = mp_tech_comp->produce_cell_outlines (); ld = mp_tech_comp->cell_outline_layer (); + } else if (purpose == Region) { + produce = mp_tech_comp->produce_regions (); + ld = mp_tech_comp->region_layer (); } else { produce = mp_tech_comp->produce_placement_blockages (); ld = mp_tech_comp->placement_blockage_layer (); @@ -348,7 +359,8 @@ LEFDEFLayerDelegate::finish (db::Layout &layout) LEFDEFImporter::LEFDEFImporter () : mp_progress (0), mp_stream (0), mp_layer_delegate (0), - m_produce_net_props (false), m_net_prop_name_id (0) + m_produce_net_props (false), m_net_prop_name_id (0), + m_produce_inst_props (false), m_inst_prop_name_id (0) { // .. nothing yet .. } @@ -376,6 +388,14 @@ LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFLayerDe m_net_prop_name_id = layout.properties_repository ().prop_name_id (ld.tech_comp ()->net_property_name ()); } + m_produce_inst_props = false; + m_inst_prop_name_id = 0; + + if (ld.tech_comp () && ld.tech_comp ()->produce_inst_names ()) { + m_produce_inst_props = true; + m_inst_prop_name_id = layout.properties_repository ().prop_name_id (ld.tech_comp ()->inst_property_name ()); + } + try { mp_progress = &progress; diff --git a/src/ext/ext/extLEFDEFImporter.h b/src/ext/ext/extLEFDEFImporter.h index 2f865f497..2eef55eec 100644 --- a/src/ext/ext/extLEFDEFImporter.h +++ b/src/ext/ext/extLEFDEFImporter.h @@ -126,6 +126,26 @@ public: m_net_property_name = s; } + bool produce_inst_names () const + { + return m_produce_inst_names; + } + + void set_produce_inst_names (bool f) + { + m_produce_inst_names = f; + } + + const tl::Variant &inst_property_name () const + { + return m_inst_property_name; + } + + void set_inst_property_name (const tl::Variant &s) + { + m_inst_property_name = s; + } + bool produce_cell_outlines () const { return m_produce_cell_outlines; @@ -166,6 +186,26 @@ public: m_placement_blockage_layer = s; } + bool produce_regions () const + { + return m_produce_regions; + } + + void set_produce_regions (bool f) + { + m_produce_regions = f; + } + + const std::string ®ion_layer () const + { + return m_region_layer; + } + + void set_region_layer (const std::string &s) + { + m_region_layer = s; + } + bool produce_via_geometry () const { return m_produce_via_geometry; @@ -382,10 +422,14 @@ private: double m_dbu; bool m_produce_net_names; tl::Variant m_net_property_name; + bool m_produce_inst_names; + tl::Variant m_inst_property_name; bool m_produce_cell_outlines; std::string m_cell_outline_layer; bool m_produce_placement_blockages; std::string m_placement_blockage_layer; + bool m_produce_regions; + std::string m_region_layer; bool m_produce_via_geometry; std::string m_via_geometry_suffix; int m_via_geometry_datatype; @@ -419,7 +463,8 @@ enum LayerPurpose Obstructions = 4, Outline = 5, Blockage = 6, - PlacementBlockage = 7 + PlacementBlockage = 7, + Region = 8 }; /** @@ -618,6 +663,22 @@ protected: return m_net_prop_name_id; } + /** + * @brief Gets a flag indicating whether instance names shall be produced as properties + */ + bool produce_inst_props () const + { + return m_produce_inst_props; + } + + /** + * @brief Gets the property name id of the instance name property + */ + db::property_names_id_type inst_prop_name_id () const + { + return m_inst_prop_name_id; + } + protected: void create_generated_via (std::vector &bottom, std::vector &cut, @@ -637,8 +698,10 @@ private: std::string m_cellname; std::string m_fn; std::string m_last_token; - db::property_names_id_type m_produce_net_props; + bool m_produce_net_props; db::property_names_id_type m_net_prop_name_id; + bool m_produce_inst_props; + db::property_names_id_type m_inst_prop_name_id; const std::string &next (); }; diff --git a/src/ext/ext/extLEFDEFPlugin.cc b/src/ext/ext/extLEFDEFPlugin.cc index d927fb883..dc2c2a78d 100644 --- a/src/ext/ext/extLEFDEFPlugin.cc +++ b/src/ext/ext/extLEFDEFPlugin.cc @@ -267,10 +267,14 @@ public: tl::make_member (&LEFDEFReaderOptions::dbu, &LEFDEFReaderOptions::set_dbu, "dbu") + tl::make_member (&LEFDEFReaderOptions::produce_net_names, &LEFDEFReaderOptions::set_produce_net_names, "produce-net-names") + tl::make_member (&LEFDEFReaderOptions::net_property_name, &LEFDEFReaderOptions::set_net_property_name, "net-property-name") + + tl::make_member (&LEFDEFReaderOptions::produce_inst_names, &LEFDEFReaderOptions::set_produce_inst_names, "produce-inst-names") + + tl::make_member (&LEFDEFReaderOptions::inst_property_name, &LEFDEFReaderOptions::set_inst_property_name, "inst-property-name") + tl::make_member (&LEFDEFReaderOptions::produce_cell_outlines, &LEFDEFReaderOptions::set_produce_cell_outlines, "produce-cell-outlines") + tl::make_member (&LEFDEFReaderOptions::cell_outline_layer, &LEFDEFReaderOptions::set_cell_outline_layer, "cell-outline-layer") + tl::make_member (&LEFDEFReaderOptions::produce_placement_blockages, &LEFDEFReaderOptions::set_produce_placement_blockages, "produce-placement-blockages") + tl::make_member (&LEFDEFReaderOptions::placement_blockage_layer, &LEFDEFReaderOptions::set_placement_blockage_layer, "placement-blockage-layer") + + tl::make_member (&LEFDEFReaderOptions::produce_regions, &LEFDEFReaderOptions::set_produce_regions, "produce-regions") + + tl::make_member (&LEFDEFReaderOptions::region_layer, &LEFDEFReaderOptions::set_region_layer, "region-layer") + tl::make_member (&LEFDEFReaderOptions::produce_via_geometry, &LEFDEFReaderOptions::set_produce_via_geometry, "produce-via-geometry") + tl::make_member (&LEFDEFReaderOptions::via_geometry_suffix, &LEFDEFReaderOptions::set_via_geometry_suffix, "via-geometry-suffix") + tl::make_member (&LEFDEFReaderOptions::via_geometry_datatype, &LEFDEFReaderOptions::set_via_geometry_datatype, "via-geometry-datatype") + diff --git a/src/klayout.pro b/src/klayout.pro index 858dbe841..9a54cd42a 100644 --- a/src/klayout.pro +++ b/src/klayout.pro @@ -77,4 +77,5 @@ unit_tests.depends += plugins $$MAIN_DEPENDS RESOURCES += \ laybasic/layResources.qrc \ - ant/layResources.qrc + ant/layResources.qrc \ + ext/lay/layResources.qrc