Merge pull request #789 from KLayout/lefdef-macro-layouts-for-gui

Lefdef macro layouts for gui
This commit is contained in:
Matthias Köfferlein 2021-05-08 22:25:56 +02:00 committed by GitHub
commit 3f46098d1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 693 additions and 377 deletions

View File

@ -394,34 +394,7 @@ MainWindow::MainWindow (QApplication *app, const char *name, bool undo_enabled)
// layout file dialog
std::string fmts = tl::to_string (QObject::tr ("All layout files ("));
for (tl::Registrar<db::StreamFormatDeclaration>::iterator rdr = tl::Registrar<db::StreamFormatDeclaration>::begin (); rdr != tl::Registrar<db::StreamFormatDeclaration>::end (); ++rdr) {
if (rdr != tl::Registrar<db::StreamFormatDeclaration>::begin ()) {
fmts += " ";
}
std::string f = rdr->file_format ();
if (!f.empty ()) {
const char *fp = f.c_str ();
while (*fp && *fp != '(') {
++fp;
}
if (*fp) {
++fp;
}
while (*fp && *fp != ')') {
fmts += *fp++;
}
}
}
fmts += ");;";
for (tl::Registrar<db::StreamFormatDeclaration>::iterator rdr = tl::Registrar<db::StreamFormatDeclaration>::begin (); rdr != tl::Registrar<db::StreamFormatDeclaration>::end (); ++rdr) {
if (!rdr->file_format ().empty ()) {
fmts += rdr->file_format ();
fmts += ";;";
}
}
fmts += tl::to_string (QObject::tr ("All files (*)"));
mp_layout_fdia = new lay::FileDialog (this, tl::to_string (QObject::tr ("Layout File")), fmts);
mp_layout_fdia = new lay::FileDialog (this, tl::to_string (QObject::tr ("Layout File")), all_layout_file_formats ());
// save & load layout options
mp_layout_save_as_options = new lay::SaveLayoutAsOptionsDialog (this, tl::to_string (QObject::tr ("Save Layout Options")));
@ -478,6 +451,40 @@ MainWindow::~MainWindow ()
mp_assistant = 0;
}
std::string
MainWindow::all_layout_file_formats () const
{
std::string fmts = tl::to_string (QObject::tr ("All layout files ("));
for (tl::Registrar<db::StreamFormatDeclaration>::iterator rdr = tl::Registrar<db::StreamFormatDeclaration>::begin (); rdr != tl::Registrar<db::StreamFormatDeclaration>::end (); ++rdr) {
if (rdr != tl::Registrar<db::StreamFormatDeclaration>::begin ()) {
fmts += " ";
}
std::string f = rdr->file_format ();
if (!f.empty ()) {
const char *fp = f.c_str ();
while (*fp && *fp != '(') {
++fp;
}
if (*fp) {
++fp;
}
while (*fp && *fp != ')') {
fmts += *fp++;
}
}
}
fmts += ");;";
for (tl::Registrar<db::StreamFormatDeclaration>::iterator rdr = tl::Registrar<db::StreamFormatDeclaration>::begin (); rdr != tl::Registrar<db::StreamFormatDeclaration>::end (); ++rdr) {
if (!rdr->file_format ().empty ()) {
fmts += rdr->file_format ();
fmts += ";;";
}
}
fmts += tl::to_string (QObject::tr ("All files (*)"));
return fmts;
}
void
MainWindow::init_menu ()
{

View File

@ -526,6 +526,11 @@ public:
*/
void open (int mode);
/**
* @brief Gets a format string with all registered layout formats
*/
std::string all_layout_file_formats () const;
/**
* @brief An event indicating that the current view has changed
* This event is fired if the current view was changed.

View File

@ -580,6 +580,7 @@ LEFDEFReaderOptions &LEFDEFReaderOptions::operator= (const LEFDEFReaderOptions &
m_map_file = d.m_map_file;
m_macro_resolution_mode = d.m_macro_resolution_mode;
m_lef_files = d.m_lef_files;
m_macro_layout_files = d.m_macro_layout_files;
m_read_lef_with_def = d.m_read_lef_with_def;
set_macro_layouts (d.macro_layouts ());
}

View File

@ -877,6 +877,36 @@ public:
return res;
}
void clear_macro_layout_files ()
{
m_macro_layout_files.clear ();
}
void push_macro_layout_file (const std::string &l)
{
m_macro_layout_files.push_back (l);
}
std::vector<std::string>::const_iterator begin_macro_layout_files () const
{
return m_macro_layout_files.begin ();
}
std::vector<std::string>::const_iterator end_macro_layout_files () const
{
return m_macro_layout_files.end ();
}
std::vector<std::string> macro_layout_files () const
{
return m_macro_layout_files;
}
void set_macro_layout_files (const std::vector<std::string> &lf)
{
m_macro_layout_files = lf;
}
private:
bool m_read_all_layers;
db::LayerMap m_layer_map;
@ -939,6 +969,7 @@ private:
bool m_read_lef_with_def;
std::vector<std::string> m_lef_files;
tl::weak_collection<db::Layout> m_macro_layouts;
std::vector<std::string> m_macro_layout_files;
};
/**
@ -1599,6 +1630,24 @@ private:
const std::string &next ();
};
class DB_PLUGIN_PUBLIC LEFDEFReader
: public db::ReaderBase
{
public:
LEFDEFReader (tl::InputStream &s);
virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options);
virtual const db::LayerMap &read (db::Layout &layout);
virtual const char *format () const;
const db::LayerMap &read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &options, bool import_lef);
private:
tl::InputStream &m_stream;
db::LayerMap m_layer_map;
};
}
#endif

View File

@ -80,112 +80,108 @@ static bool is_def_format (const std::string &fn)
return false;
}
class LEFDEFReader
: public db::ReaderBase
// ---------------------------------------------------------------
// LEFDEFReader implementation
LEFDEFReader::LEFDEFReader (tl::InputStream &s)
: m_stream (s)
{
public:
// .. nothing yet ..
}
LEFDEFReader (tl::InputStream &s)
: m_stream (s)
{
// .. nothing yet ..
const db::LayerMap &
LEFDEFReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
{
return read_lefdef (layout, options, is_lef_format (m_stream.filename ()));
}
const db::LayerMap &
LEFDEFReader::read (db::Layout &layout)
{
return read_lefdef (layout, db::LoadLayoutOptions (), is_lef_format (m_stream.filename ()));
}
const char *
LEFDEFReader::format () const
{
return "LEFDEF";
}
const db::LayerMap &
LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &options, bool import_lef)
{
const db::LEFDEFReaderOptions *lefdef_options = dynamic_cast<const db::LEFDEFReaderOptions *> (options.get_options (format ()));
db::LEFDEFReaderOptions effective_options;
if (lefdef_options) {
effective_options = *lefdef_options;
}
virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options)
{
return read_lefdef (layout, options, is_lef_format (m_stream.filename ()));
}
db::LEFDEFReaderState state (&effective_options, layout, tl::dirname (m_stream.absolute_path ()));
virtual const db::LayerMap &read (db::Layout &layout)
{
return read_lefdef (layout, db::LoadLayoutOptions (), is_lef_format (m_stream.filename ()));
}
layout.dbu (effective_options.dbu ());
virtual const char *format () const
{
return "LEFDEF";
}
if (import_lef) {
private:
tl::InputStream &m_stream;
db::LayerMap m_layer_map;
// Always produce LEF geometry when reading LEF
effective_options.set_macro_resolution_mode (1);
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file")));
db::LEFImporter importer;
for (std::vector<std::string>::const_iterator l = effective_options.begin_lef_files (); l != effective_options.end_lef_files (); ++l) {
std::string lp = correct_path (*l, layout, tl::dirname (m_stream.absolute_path ()));
tl::InputStream lef_stream (lp);
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
importer.read (lef_stream, layout, state);
const db::LayerMap &read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &options, bool import_lef)
{
const db::LEFDEFReaderOptions *lefdef_options = dynamic_cast<const db::LEFDEFReaderOptions *> (options.get_options (format ()));
db::LEFDEFReaderOptions effective_options;
if (lefdef_options) {
effective_options = *lefdef_options;
}
db::LEFDEFReaderState state (&effective_options, layout, tl::dirname (m_stream.absolute_path ()));
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
importer.read (m_stream, layout, state);
layout.dbu (effective_options.dbu ());
importer.finish_lef (layout);
if (import_lef) {
} else {
// Always produce LEF geometry when reading LEF
effective_options.set_macro_resolution_mode (1);
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading DEF file")));
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file")));
DEFImporter importer;
db::LEFImporter importer;
for (std::vector<std::string>::const_iterator l = effective_options.begin_lef_files (); l != effective_options.end_lef_files (); ++l) {
for (std::vector<std::string>::const_iterator l = effective_options.begin_lef_files (); l != effective_options.end_lef_files (); ++l) {
std::string lp = correct_path (*l, layout, tl::dirname (m_stream.absolute_path ()));
std::string lp = correct_path (*l, layout, tl::dirname (m_stream.absolute_path ()));
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp);
tl::InputStream lef_stream (lp);
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
importer.read (lef_stream, layout, state);
tl::InputStream lef_stream (lp);
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
importer.read_lef (lef_stream, layout, state);
}
}
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
importer.read (m_stream, layout, state);
// Additionally read all LEF files next to the DEF file
importer.finish_lef (layout);
if (effective_options.read_lef_with_def ()) {
} else {
std::string input_dir = tl::absolute_path (m_stream.absolute_path ());
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading DEF file")));
if (tl::file_exists (input_dir)) {
DEFImporter importer;
std::vector<std::string> entries = tl::dir_entries (input_dir, true, false, true);
for (std::vector<std::string>::const_iterator e = entries.begin (); e != entries.end (); ++e) {
for (std::vector<std::string>::const_iterator l = effective_options.begin_lef_files (); l != effective_options.end_lef_files (); ++l) {
if (is_lef_format (*e)) {
std::string lp = correct_path (*l, layout, tl::dirname (m_stream.absolute_path ()));
std::string lp = tl::combine_path (input_dir, *e);
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp);
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp);
tl::InputStream lef_stream (lp);
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
importer.read_lef (lef_stream, layout, state);
}
// Additionally read all LEF files next to the DEF file
if (effective_options.read_lef_with_def ()) {
std::string input_dir = tl::absolute_path (m_stream.absolute_path ());
if (tl::file_exists (input_dir)) {
std::vector<std::string> entries = tl::dir_entries (input_dir, true, false, true);
for (std::vector<std::string>::const_iterator e = entries.begin (); e != entries.end (); ++e) {
if (is_lef_format (*e)) {
std::string lp = tl::combine_path (input_dir, *e);
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp);
tl::InputStream lef_stream (lp);
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
importer.read_lef (lef_stream, layout, state);
}
tl::InputStream lef_stream (lp);
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
importer.read_lef (lef_stream, layout, state);
}
@ -193,46 +189,69 @@ private:
}
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
importer.read (m_stream, layout, state);
}
// Resolve unresolved COMPONENT cells
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
importer.read (m_stream, layout, state);
std::map<std::string, db::cell_index_type> foreign_cells = state.foreign_cells ();
db::cell_index_type seen = std::numeric_limits<db::cell_index_type>::max ();
// Resolve unresolved COMPONENT cells
std::vector<db::Layout *> macro_layouts = effective_options.macro_layouts ();
for (std::vector<db::Layout *>::const_iterator m = macro_layouts.begin (); m != macro_layouts.end (); ++m) {
std::map<std::string, db::cell_index_type> foreign_cells = state.foreign_cells ();
db::cell_index_type seen = std::numeric_limits<db::cell_index_type>::max ();
std::vector<db::cell_index_type> target_cells, source_cells;
std::vector<db::Layout *> macro_layouts = effective_options.macro_layouts ();
// collect the cells to pull in
for (std::map<std::string, db::cell_index_type>::iterator f = foreign_cells.begin (); f != foreign_cells.end (); ++f) {
if (f->second != seen) {
std::pair<bool, db::cell_index_type> cp = (*m)->cell_by_name (f->first.c_str ());
if (cp.first) {
target_cells.push_back (f->second);
source_cells.push_back (cp.second);
layout.cell (f->second).set_ghost_cell (false);
f->second = seen;
}
}
}
// Additionally read the layouts from the given paths
tl::shared_collection<db::Layout> macro_layout_object_holder;
for (std::vector<std::string>::const_iterator l = effective_options.begin_macro_layout_files (); l != effective_options.end_macro_layout_files (); ++l) {
db::CellMapping cm;
cm.create_multi_mapping_full (layout, target_cells, **m, source_cells);
layout.copy_tree_shapes (**m, cm);
std::string lp = correct_path (*l, layout, tl::dirname (m_stream.absolute_path ()));
}
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF macro layout file: ")) + lp);
tl::InputStream macro_layout_stream (lp);
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
db::Layout *new_layout = new db::Layout (false);
macro_layout_object_holder.push_back (new_layout);
macro_layouts.push_back (new_layout);
db::Reader reader (macro_layout_stream);
reader.read (*new_layout, options);
}
state.finish (layout);
for (std::vector<db::Layout *>::const_iterator m = macro_layouts.begin (); m != macro_layouts.end (); ++m) {
std::vector<db::cell_index_type> target_cells, source_cells;
// collect the cells to pull in
for (std::map<std::string, db::cell_index_type>::iterator f = foreign_cells.begin (); f != foreign_cells.end (); ++f) {
if (f->second != seen) {
std::pair<bool, db::cell_index_type> cp = (*m)->cell_by_name (f->first.c_str ());
if (cp.first) {
target_cells.push_back (f->second);
source_cells.push_back (cp.second);
layout.cell (f->second).set_ghost_cell (false);
f->second = seen;
}
}
}
db::CellMapping cm;
cm.create_multi_mapping_full (layout, target_cells, **m, source_cells);
layout.copy_tree_shapes (**m, cm);
}
m_layer_map = state.layer_map ();
return m_layer_map;
}
};
state.finish (layout);
m_layer_map = state.layer_map ();
return m_layer_map;
}
// ---------------------------------------------------------------
namespace {
@ -371,6 +390,7 @@ class LEFDEFFormatDeclaration
tl::make_member (&LEFDEFReaderOptions::special_routing_datatype_str, &LEFDEFReaderOptions::set_special_routing_datatype_str, "special-routing-datatype-string") +
tl::make_member (&LEFDEFReaderOptions::via_cellname_prefix, &LEFDEFReaderOptions::set_via_cellname_prefix, "via-cellname-prefix") +
tl::make_member (&LEFDEFReaderOptions::begin_lef_files, &LEFDEFReaderOptions::end_lef_files, &LEFDEFReaderOptions::push_lef_file, "lef-files") +
tl::make_member (&LEFDEFReaderOptions::begin_macro_layout_files, &LEFDEFReaderOptions::end_macro_layout_files, &LEFDEFReaderOptions::push_macro_layout_file, "macro_layout-files") +
tl::make_member (&LEFDEFReaderOptions::read_lef_with_def, &LEFDEFReaderOptions::set_read_lef_with_def, "read-lef-with-def") +
tl::make_member (&LEFDEFReaderOptions::macro_resolution_mode, &LEFDEFReaderOptions::set_macro_resolution_mode, "macro-resolution-mode", MacroResolutionModeConverter ()) +
tl::make_member (&LEFDEFReaderOptions::separate_groups, &LEFDEFReaderOptions::set_separate_groups, "separate-groups") +

View File

@ -119,7 +119,7 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"The setter is \\layer_map=. \\create_other_layers= is available to control whether layers "
"not specified in the layer mapping table shall be created automatically."
) +
gsi::method ("layer_map=", &db::LEFDEFReaderOptions::set_layer_map,
gsi::method ("layer_map=", &db::LEFDEFReaderOptions::set_layer_map, gsi::arg ("m"),
"@brief Sets the layer map to be used for the LEF/DEF reader\n"
"See \\layer_map for details."
) +
@ -127,7 +127,7 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"@brief Gets a value indicating whether layers not mapped in the layer map shall be created too\n"
"See \\layer_map for details."
) +
gsi::method ("create_other_layers=", &db::LEFDEFReaderOptions::set_read_all_layers,
gsi::method ("create_other_layers=", &db::LEFDEFReaderOptions::set_read_all_layers, gsi::arg ("f"),
"@brief Sets a value indicating whether layers not mapped in the layer map shall be created too\n"
"See \\layer_map for details."
) +
@ -216,7 +216,7 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"This string can be either a layer number, a layer/datatype pair, a name or a combination of both. See \\LayerInfo for details."
"The setter for this attribute is \\placement_blockage_layer=. See also \\produce_placement_blockages."
) +
gsi::method ("placement_blockage_layer=", &db::LEFDEFReaderOptions::set_placement_blockage_layer,
gsi::method ("placement_blockage_layer=", &db::LEFDEFReaderOptions::set_placement_blockage_layer, gsi::arg ("layer"),
"@brief Sets the layer on which to produce the placement blockage.\n"
"See \\placement_blockage_layer for details.\n"
) +
@ -240,7 +240,7 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"\n"
"The attribute has been introduced in version 0.27."
) +
gsi::method ("region_layer=", &db::LEFDEFReaderOptions::set_region_layer,
gsi::method ("region_layer=", &db::LEFDEFReaderOptions::set_region_layer, gsi::arg ("layer"),
"@brief Sets the layer on which to produce the regions.\n"
"See \\region_layer for details.\n"
"\n"
@ -312,7 +312,7 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("via_geometry_datatype", &db::LEFDEFReaderOptions::via_geometry_datatype_per_mask,
gsi::method ("via_geometry_datatype", &db::LEFDEFReaderOptions::via_geometry_datatype_per_mask, gsi::arg ("mask"),
"@brief Gets the via geometry layer datatype value per mask.\n"
"See \\produce_via_geometry for details about this property.\n"
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
@ -400,7 +400,7 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("pins_datatype", &db::LEFDEFReaderOptions::pins_datatype_per_mask,
gsi::method ("pins_datatype", &db::LEFDEFReaderOptions::pins_datatype_per_mask, gsi::arg ("mask"),
"@brief Gets the pin geometry layer datatype value per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
@ -476,7 +476,7 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("lef_pins_datatype", &db::LEFDEFReaderOptions::lef_pins_datatype_per_mask,
gsi::method ("lef_pins_datatype", &db::LEFDEFReaderOptions::lef_pins_datatype_per_mask, gsi::arg ("mask"),
"@brief Gets the LEF pin geometry layer datatype value per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
@ -564,7 +564,7 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("fills_datatype", &db::LEFDEFReaderOptions::fills_datatype_per_mask,
gsi::method ("fills_datatype", &db::LEFDEFReaderOptions::fills_datatype_per_mask, gsi::arg ("mask"),
"@brief Gets the fill geometry layer datatype value per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
@ -712,7 +712,7 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("routing_datatype", &db::LEFDEFReaderOptions::routing_datatype_per_mask,
gsi::method ("routing_datatype", &db::LEFDEFReaderOptions::routing_datatype_per_mask, gsi::arg ("mask"),
"@brief Gets the routing geometry layer datatype value per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
@ -800,7 +800,7 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"\n\n"
"Mask specific rules have been introduced in version 0.27."
) +
gsi::method ("special_routing_datatype", &db::LEFDEFReaderOptions::special_routing_datatype_per_mask,
gsi::method ("special_routing_datatype", &db::LEFDEFReaderOptions::special_routing_datatype_per_mask, gsi::arg ("mask"),
"@brief Gets the special routing geometry layer datatype value per mask.\n"
"See \\produce_via_geometry for details about the layer production rules."
"The mask number is a zero-based mask index (0: MASK 1, 1: MASK 2 ...)."
@ -885,11 +885,13 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"LEF macros. The \\macro_resolution_mode controls whether to use LEF geometry. If LEF geometry is not "
"used, the DEF reader will look up macro cells from the \\macro_layouts and pull cell layouts from there.\n"
"\n"
"The LEF cells are looked up by name from the macro layouts in the order these are given in this array.\n"
"The LEF cells are looked up as cells by name from the macro layouts in the order these are given in this array.\n"
"\n"
"\\macro_layout_files is another way of specifying such substitution layouts. This method accepts file names instead of layout objects.\n"
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("macro_layouts=", &db::LEFDEFReaderOptions::set_macro_layouts,
gsi::method ("macro_layouts=", &db::LEFDEFReaderOptions::set_macro_layouts, gsi::arg ("layouts"),
"@brief Sets the layout objects used for resolving LEF macros in the DEF reader.\n"
"See \\macro_layouts for more details about this property.\n"
"\n"
@ -898,14 +900,33 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"\n"
"This property has been added in version 0.27.\n"
) +
gsi::method ("macro_layout_files", &db::LEFDEFReaderOptions::macro_layout_files,
"@brief Gets the list of layout files to read for substituting macros in DEF\n"
"These files play the same role than the macro layouts (see \\macro_layouts), except that this property specifies a list of file names. "
"The given files are loaded automatically to resolve macro layouts instead of LEF geometry. See \\macro_resolution_mode for details when this happens. "
"Relative paths are resolved relative to the DEF file to read or relative to the technology base path.\n"
"Macros in need for substitution are looked up in the layout files by searching for cells with the same name. "
"The files are scanned in the order they are given in the file list.\n"
"The files from \\macro_layout_files are scanned after the layout objects specified with \\macro_layouts.\n"
"\n"
"The setter for this property is \\macro_layout_files=.\n"
"\n"
"This property has been added in version 0.27.1.\n"
) +
gsi::method ("macro_layout_files=", &db::LEFDEFReaderOptions::set_macro_layout_files, gsi::arg ("file_paths"),
"@brief Sets the list of layout files to read for substituting macros in DEF\n"
"See \\macro_layout_files for details.\n"
"\n"
"This property has been added in version 0.27.1.\n"
) +
gsi::method ("lef_files", &db::LEFDEFReaderOptions::lef_files,
"@brief Gets the list technology LEF files to additionally import\n"
"Returns a list of path names for technology LEF files to read in addition to the primary file. "
"Relative paths are resolved relative to the file to read.\n"
"Relative paths are resolved relative to the file to read or relative to the technology base path.\n"
"\n"
"The setter for this property is \\lef_files=."
) +
gsi::method ("lef_files=", &db::LEFDEFReaderOptions::set_lef_files,
gsi::method ("lef_files=", &db::LEFDEFReaderOptions::set_lef_files, gsi::arg ("lef_file_paths"),
"@brief Sets the list technology LEF files to additionally import\n"
"See \\lef_files for details."
) +

View File

@ -35,11 +35,11 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>LEF Files</string>
<string>LEF+Macro Files</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
@ -49,6 +49,69 @@
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_7">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>LEF macro geometry</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="macro_resolution_mode">
<item>
<property name="text">
<string>Produce LEF geometry or use macro layout files for LEF FOREIGN</string>
</property>
</item>
<item>
<property name="text">
<string>Always produce LEF geometry and ignore LEF FOREIGN</string>
</property>
</item>
<item>
<property name="text">
<string>Always use macro layout files (assume LEF FOREIGN)</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
@ -138,19 +201,18 @@
<property name="spacing">
<number>6</number>
</property>
<item row="1" column="1">
<widget class="QToolButton" name="del_lef_files">
<property name="toolTip">
<string>Delete selected files</string>
<item row="4" column="1">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="text">
<string>...</string>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/clear.png</normaloff>:/clear.png</iconset>
</property>
</widget>
</spacer>
</item>
<item row="0" column="0" rowspan="5">
<widget class="QListWidget" name="lef_files">
@ -179,18 +241,19 @@
</property>
</widget>
</item>
<item row="4" column="1">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
<item row="1" column="1">
<widget class="QToolButton" name="del_lef_files">
<property name="toolTip">
<string>Delete selected files</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
<property name="text">
<string>...</string>
</property>
</spacer>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/clear.png</normaloff>:/clear.png</iconset>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QToolButton" name="add_lef_file">
@ -226,6 +289,120 @@
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_8">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_31">
<property name="text">
<string>Macro Layout Files
(used instead of LEF geometry if requested, resolution priority follows order)</string>
</property>
</widget>
</item>
<item row="1" column="0" rowspan="5">
<widget class="QListWidget" name="macro_layout_files">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="add_macro_layout_file">
<property name="toolTip">
<string>Add LEF file</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/add.png</normaloff>:/add.png</iconset>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QToolButton" name="del_macro_layout_files">
<property name="toolTip">
<string>Delete selected files</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/clear.png</normaloff>:/clear.png</iconset>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QToolButton" name="move_macro_layout_files_up">
<property name="toolTip">
<string>Move selected files up</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/up.png</normaloff>:/up.png</iconset>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QToolButton" name="move_macro_layout_files_down">
<property name="toolTip">
<string>Move selected files down</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../lay/lay/layResources.qrc">
<normaloff>:/down.png</normaloff>:/down.png</iconset>
</property>
</widget>
</item>
<item row="5" column="1">
<spacer name="spacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>196</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
@ -248,30 +425,6 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Layout DBU</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="prefix_via_cellname">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QCheckBox" name="separate_groups">
<property name="text">
<string>Produce a parent cell per group</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
@ -279,23 +432,6 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>LEF import into DEF</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="dbu">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
@ -316,7 +452,54 @@
</property>
</widget>
</item>
<item row="4" column="1" colspan="3">
<item row="0" column="3" rowspan="3">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1" colspan="2">
<widget class="QCheckBox" name="separate_groups">
<property name="text">
<string>Produce a parent cell per group</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Layout DBU</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="prefix_via_cellname">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="dbu">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="3" column="1" colspan="3">
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
@ -340,38 +523,30 @@
</layout>
</widget>
</item>
<item row="0" column="3" rowspan="3">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1" colspan="3">
<widget class="QComboBox" name="macro_resolution_mode">
<item>
<property name="text">
<string>Produce LEF geometry unless FOREIGN is used</string>
</property>
</item>
<item>
<property name="text">
<string>Always produce LEF geometry and ignore FOREIGN</string>
</property>
</item>
<item>
<property name="text">
<string>Never produce LEF geometry and assume FOREIGN always</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_6">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>

View File

@ -131,68 +131,15 @@ public:
if (! db::Technologies::instance ()->has_technology (tech_name)) {
tech_name.clear (); // use default technology
}
db::LoadLayoutOptions options;
const db::Technology *tech = db::Technologies::instance ()->technology_by_name (tech_name);
db::LEFDEFReaderOptions options;
if (tech) {
const db::LEFDEFReaderOptions *tech_options = dynamic_cast<const db::LEFDEFReaderOptions *>(tech->load_layout_options ().get_options ("LEFDEF"));
if (tech_options) {
options = *tech_options;
}
options = tech->load_layout_options ();
}
db::LEFDEFReaderState state (&options, *layout);
layout->dbu (options.dbu ());
if (import_lef) {
tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Reading LEF file")));
db::LEFImporter importer;
for (std::vector<std::string>::const_iterator l = options.begin_lef_files (); l != options.end_lef_files (); ++l) {
tl::InputStream lef_stream (*l);
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l;
importer.read (lef_stream, *layout, state);
}
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << data.file;
importer.read (stream, *layout, state);
} else {
tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (QObject::tr ("Reading DEF file")));
db::DEFImporter importer;
QFileInfo def_fi (tl::to_qstring (data.file));
std::vector<std::string> lef_files;
lef_files.insert (lef_files.end (), options.begin_lef_files (), options.end_lef_files ());
lef_files.insert (lef_files.end (), data.lef_files.begin (), data.lef_files.end ());
for (std::vector<std::string>::const_iterator l = lef_files.begin (); l != lef_files.end (); ++l) {
QFileInfo fi (tl::to_qstring (*l));
if (fi.isAbsolute ()) {
tl::InputStream lef_stream (*l);
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l;
importer.read_lef (lef_stream, *layout, state);
} else {
std::string ex_l = tl::to_string (def_fi.absoluteDir ().absoluteFilePath (tl::to_qstring (*l)));
tl::InputStream lef_stream (ex_l);
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l;
importer.read_lef (lef_stream, *layout, state);
}
}
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << data.file;
importer.read (stream, *layout, state);
}
state.finish (*layout);
db::LEFDEFReader reader (stream);
reader.read_lefdef (*layout, options, import_lef);
lay::LayoutView *view = lay::LayoutView::current ();
if (! view || data.mode == 1) {

View File

@ -364,6 +364,10 @@ LEFDEFReaderOptionsEditor::LEFDEFReaderOptionsEditor (QWidget *parent)
connect (del_lef_files, SIGNAL (clicked ()), this, SLOT (del_lef_files_clicked ()));
connect (move_lef_files_up, SIGNAL (clicked ()), this, SLOT (move_lef_files_up_clicked ()));
connect (move_lef_files_down, SIGNAL (clicked ()), this, SLOT (move_lef_files_down_clicked ()));
connect (add_macro_layout_file, SIGNAL (clicked ()), this, SLOT (add_macro_layout_file_clicked ()));
connect (del_macro_layout_files, SIGNAL (clicked ()), this, SLOT (del_macro_layout_files_clicked ()));
connect (move_macro_layout_files_up, SIGNAL (clicked ()), this, SLOT (move_macro_layout_files_up_clicked ()));
connect (move_macro_layout_files_down, SIGNAL (clicked ()), this, SLOT (move_macro_layout_files_down_clicked ()));
connect (browse_mapfile, SIGNAL (clicked ()), this, SLOT (browse_mapfile_clicked ()));
lay::activate_help_links (help_label);
@ -521,6 +525,11 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con
for (int i = 0; i < lef_files->count (); ++i) {
data->push_lef_file (tl::to_string (lef_files->item (i)->text ()));
}
data->clear_macro_layout_files ();
for (int i = 0; i < macro_layout_files->count (); ++i) {
data->push_macro_layout_file (tl::to_string (macro_layout_files->item (i)->text ()));
}
}
void
@ -597,6 +606,18 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options
for (int i = 0; i < lef_files->count (); ++i) {
lef_files->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
}
macro_layout_files->clear ();
for (std::vector <std::string>::const_iterator f = data->begin_macro_layout_files (); f != data->end_macro_layout_files (); ++f) {
if (mp_tech) {
macro_layout_files->addItem (tl::to_qstring (mp_tech->correct_path (*f)));
} else {
macro_layout_files->addItem (tl::to_qstring (*f));
}
}
for (int i = 0; i < macro_layout_files->count (); ++i) {
macro_layout_files->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
}
}
void
@ -657,114 +678,171 @@ LEFDEFReaderOptionsEditor::add_lef_file_clicked ()
}
QStringList files = QFileDialog::getOpenFileNames (this, tl::to_qstring (title), tl::to_qstring (dir), tl::to_qstring (filters));
for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) {
if (mp_tech) {
lef_files->addItem (tl::to_qstring (mp_tech->correct_path (tl::to_string (*f))));
} else {
lef_files->addItem (*f);
}
}
for (int i = 0; i < lef_files->count (); ++i) {
lef_files->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
}
add_files (lef_files, files, mp_tech.get ());
}
void
LEFDEFReaderOptionsEditor::del_lef_files_clicked ()
{
QStringList files;
for (int i = 0; i < lef_files->count (); ++i) {
if (! lef_files->item (i)->isSelected ()) {
files.push_back (lef_files->item (i)->text ());
}
}
lef_files->clear ();
for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) {
lef_files->addItem (*f);
}
for (int i = 0; i < lef_files->count (); ++i) {
lef_files->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
}
del_files (lef_files);
}
void
LEFDEFReaderOptionsEditor::move_lef_files_up_clicked ()
{
std::set<QString> selected;
for (int i = 0; i < lef_files->count (); ++i) {
if (lef_files->item (i)->isSelected ()) {
selected.insert (lef_files->item (i)->text ());
}
}
QStringList files;
int j = -1;
for (int i = 0; i < lef_files->count (); ++i) {
if (lef_files->item (i)->isSelected ()) {
files.push_back (lef_files->item (i)->text ());
} else {
if (j >= 0) {
files.push_back (lef_files->item (j)->text ());
}
j = i;
}
}
if (j >= 0) {
files.push_back (lef_files->item (j)->text ());
}
lef_files->clear ();
for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) {
lef_files->addItem (*f);
if (selected.find (*f) != selected.end ()) {
lef_files->item (lef_files->count () - 1)->setSelected (true);
}
}
for (int i = 0; i < lef_files->count (); ++i) {
lef_files->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
}
move_files_up (lef_files);
}
void
LEFDEFReaderOptionsEditor::move_lef_files_down_clicked ()
{
move_files_down (lef_files);
}
void
LEFDEFReaderOptionsEditor::add_macro_layout_file_clicked ()
{
std::string title, filters;
title = tl::to_string (QObject::tr ("Add Macro Layout Files"));
filters = lay::MainWindow::instance ()->all_layout_file_formats ();
std::string dir;
if (mp_tech) {
dir = mp_tech->base_path ();
}
QStringList files = QFileDialog::getOpenFileNames (this, tl::to_qstring (title), tl::to_qstring (dir), tl::to_qstring (filters));
add_files (macro_layout_files, files, mp_tech.get ());
}
void
LEFDEFReaderOptionsEditor::del_macro_layout_files_clicked ()
{
del_files (macro_layout_files);
}
void
LEFDEFReaderOptionsEditor::move_macro_layout_files_up_clicked ()
{
move_files_up (macro_layout_files);
}
void
LEFDEFReaderOptionsEditor::move_macro_layout_files_down_clicked ()
{
move_files_down (macro_layout_files);
}
void
LEFDEFReaderOptionsEditor::add_files (QListWidget *list, const QStringList &files, const db::Technology *tech)
{
for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) {
if (tech) {
list->addItem (tl::to_qstring (tech->correct_path (tl::to_string (*f))));
} else {
list->addItem (*f);
}
}
for (int i = 0; i < list->count (); ++i) {
list->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
}
}
void
LEFDEFReaderOptionsEditor::del_files (QListWidget *list)
{
QStringList files;
for (int i = 0; i < list->count (); ++i) {
if (! list->item (i)->isSelected ()) {
files.push_back (list->item (i)->text ());
}
}
list->clear ();
for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) {
list->addItem (*f);
}
for (int i = 0; i < list->count (); ++i) {
list->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
}
}
void
LEFDEFReaderOptionsEditor::move_files_up (QListWidget *list)
{
std::set<QString> selected;
for (int i = 0; i < lef_files->count (); ++i) {
if (lef_files->item (i)->isSelected ()) {
selected.insert (lef_files->item (i)->text ());
for (int i = 0; i < list->count (); ++i) {
if (list->item (i)->isSelected ()) {
selected.insert (list->item (i)->text ());
}
}
QStringList files;
int j = -1;
for (int i = lef_files->count (); i > 0; ) {
--i;
if (lef_files->item (i)->isSelected ()) {
files.push_back (lef_files->item (i)->text ());
for (int i = 0; i < list->count (); ++i) {
if (list->item (i)->isSelected ()) {
files.push_back (list->item (i)->text ());
} else {
if (j >= 0) {
files.push_back (lef_files->item (j)->text ());
files.push_back (list->item (j)->text ());
}
j = i;
}
}
if (j >= 0) {
files.push_back (lef_files->item (j)->text ());
files.push_back (list->item (j)->text ());
}
lef_files->clear ();
for (QStringList::const_iterator f = files.end (); f != files.begin (); ) {
--f;
lef_files->addItem (*f);
list->clear ();
for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) {
list->addItem (*f);
if (selected.find (*f) != selected.end ()) {
lef_files->item (lef_files->count () - 1)->setSelected (true);
list->item (list->count () - 1)->setSelected (true);
}
}
for (int i = 0; i < lef_files->count (); ++i) {
lef_files->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
for (int i = 0; i < list->count (); ++i) {
list->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
}
}
void
LEFDEFReaderOptionsEditor::move_files_down (QListWidget *list)
{
std::set<QString> selected;
for (int i = 0; i < list->count (); ++i) {
if (list->item (i)->isSelected ()) {
selected.insert (list->item (i)->text ());
}
}
QStringList files;
int j = -1;
for (int i = list->count (); i > 0; ) {
--i;
if (list->item (i)->isSelected ()) {
files.push_back (list->item (i)->text ());
} else {
if (j >= 0) {
files.push_back (list->item (j)->text ());
}
j = i;
}
}
if (j >= 0) {
files.push_back (list->item (j)->text ());
}
list->clear ();
for (QStringList::const_iterator f = files.end (); f != files.begin (); ) {
--f;
list->addItem (*f);
if (selected.find (*f) != selected.end ()) {
list->item (list->count () - 1)->setSelected (true);
}
}
for (int i = 0; i < list->count (); ++i) {
list->item (i)->setFlags (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
}
}
}

View File

@ -98,10 +98,19 @@ private slots:
void del_lef_files_clicked ();
void move_lef_files_up_clicked ();
void move_lef_files_down_clicked ();
void add_macro_layout_file_clicked ();
void del_macro_layout_files_clicked ();
void move_macro_layout_files_up_clicked ();
void move_macro_layout_files_down_clicked ();
void browse_mapfile_clicked ();
private:
tl::weak_ptr<db::Technology> mp_tech;
static void add_files (QListWidget *list, const QStringList &files, const db::Technology *tech);
static void del_files (QListWidget *list);
static void move_files_up (QListWidget *list);
static void move_files_down (QListWidget *list);
};
}

View File

@ -373,6 +373,10 @@ class DBReaders_TestClass < TestBase
conf.lef_files = [ "u.lef", "v.lef" ]
assert_equal(conf.lef_files.join(","), "u.lef,v.lef")
assert_equal(conf.macro_layout_files.join(","), "")
conf.macro_layout_files = [ "u.gds", "v.oas" ]
assert_equal(conf.macro_layout_files.join(","), "u.gds,v.oas")
assert_equal(conf.read_lef_with_def, true)
conf.read_lef_with_def = false
assert_equal(conf.read_lef_with_def, false)