mirror of https://github.com/KLayout/klayout.git
Added a configuration option for providing macro substitution layouts (not through UI, only scripting so far)
This commit is contained in:
parent
9a4cd629fc
commit
a6e750b088
|
|
@ -517,6 +517,7 @@ LEFDEFReaderOptions &LEFDEFReaderOptions::operator= (const LEFDEFReaderOptions &
|
||||||
m_macro_resolution_mode = d.m_macro_resolution_mode;
|
m_macro_resolution_mode = d.m_macro_resolution_mode;
|
||||||
m_lef_files = d.m_lef_files;
|
m_lef_files = d.m_lef_files;
|
||||||
m_read_lef_with_def = d.m_read_lef_with_def;
|
m_read_lef_with_def = d.m_read_lef_with_def;
|
||||||
|
set_macro_layouts (d.macro_layouts ());
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -1358,6 +1359,20 @@ LEFDEFReaderState::macro_generator (const std::string &mn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db::cell_index_type
|
||||||
|
LEFDEFReaderState::foreign_cell (Layout &layout, const std::string &name)
|
||||||
|
{
|
||||||
|
std::map<std::string, db::cell_index_type>::const_iterator c = m_foreign_cells.find (name);
|
||||||
|
if (c != m_foreign_cells.end ()) {
|
||||||
|
return c->second;
|
||||||
|
} else {
|
||||||
|
db::cell_index_type ci = layout.add_cell (name.c_str ());
|
||||||
|
layout.cell (ci).set_ghost_cell (true);
|
||||||
|
m_foreign_cells.insert (std::make_pair (name, ci));
|
||||||
|
return ci;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<db::Cell *, db::Trans>
|
std::pair<db::Cell *, db::Trans>
|
||||||
LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std::vector<std::string> &maskshift_layers, const std::vector<unsigned int> &masks, const MacroDesc ¯o_desc, const LEFDEFNumberOfMasks *nm)
|
LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std::vector<std::string> &maskshift_layers, const std::vector<unsigned int> &masks, const MacroDesc ¯o_desc, const LEFDEFNumberOfMasks *nm)
|
||||||
{
|
{
|
||||||
|
|
@ -1386,15 +1401,7 @@ LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std:
|
||||||
|
|
||||||
if (! macro_desc.foreign_name.empty ()) {
|
if (! macro_desc.foreign_name.empty ()) {
|
||||||
|
|
||||||
db::cell_index_type ci;
|
db::cell_index_type ci = foreign_cell (layout, macro_desc.foreign_name);
|
||||||
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (macro_desc.foreign_name.c_str ());
|
|
||||||
if (c.first) {
|
|
||||||
ci = c.second;
|
|
||||||
} else {
|
|
||||||
ci = layout.add_cell (macro_desc.foreign_name.c_str ());
|
|
||||||
layout.cell (ci).set_ghost_cell (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
db::Cell *foreign_cell = &layout.cell (ci);
|
db::Cell *foreign_cell = &layout.cell (ci);
|
||||||
|
|
||||||
if (macro_desc.foreign_name != mn) {
|
if (macro_desc.foreign_name != mn) {
|
||||||
|
|
@ -1415,15 +1422,7 @@ LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std:
|
||||||
|
|
||||||
// create a ghost cell always
|
// create a ghost cell always
|
||||||
|
|
||||||
db::cell_index_type ci;
|
db::cell_index_type ci = foreign_cell (layout, mn);
|
||||||
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (mn.c_str ());
|
|
||||||
if (c.first) {
|
|
||||||
ci = c.second;
|
|
||||||
} else {
|
|
||||||
ci = layout.add_cell (mn.c_str ());
|
|
||||||
layout.cell (ci).set_ghost_cell (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
cell = &layout.cell (ci);
|
cell = &layout.cell (ci);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -791,6 +791,24 @@ public:
|
||||||
m_macro_resolution_mode = m;
|
m_macro_resolution_mode = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_macro_layouts (const std::vector<db::Layout *> &layouts)
|
||||||
|
{
|
||||||
|
for (std::vector<db::Layout *>::const_iterator l = layouts.begin (); l != layouts.end (); ++l) {
|
||||||
|
m_macro_layouts.push_back (*l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<db::Layout *> macro_layouts () const
|
||||||
|
{
|
||||||
|
std::vector<db::Layout *> res;
|
||||||
|
for (tl::weak_collection<db::Layout>::const_iterator m = m_macro_layouts.begin (); m != m_macro_layouts.end (); ++m) {
|
||||||
|
if (m.operator-> ()) {
|
||||||
|
res.push_back (const_cast<db::Layout *> (m.operator-> ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_read_all_layers;
|
bool m_read_all_layers;
|
||||||
db::LayerMap m_layer_map;
|
db::LayerMap m_layer_map;
|
||||||
|
|
@ -847,6 +865,7 @@ private:
|
||||||
unsigned int m_macro_resolution_mode;
|
unsigned int m_macro_resolution_mode;
|
||||||
bool m_read_lef_with_def;
|
bool m_read_lef_with_def;
|
||||||
std::vector<std::string> m_lef_files;
|
std::vector<std::string> m_lef_files;
|
||||||
|
tl::weak_collection<db::Layout> m_macro_layouts;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1088,6 +1107,14 @@ public:
|
||||||
return mp_tech_comp;
|
return mp_tech_comp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets a map of foreign cells vs. name
|
||||||
|
*/
|
||||||
|
const std::map<std::string, db::cell_index_type> &foreign_cells () const
|
||||||
|
{
|
||||||
|
return m_foreign_cells;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief A key for the via cache
|
* @brief A key for the via cache
|
||||||
|
|
@ -1171,9 +1198,11 @@ private:
|
||||||
std::map<std::string, LEFDEFLayoutGenerator *> m_via_generators;
|
std::map<std::string, LEFDEFLayoutGenerator *> m_via_generators;
|
||||||
std::map<MacroKey, std::pair<db::Cell *, db::Trans> > m_macro_cells;
|
std::map<MacroKey, std::pair<db::Cell *, db::Trans> > m_macro_cells;
|
||||||
std::map<std::string, LEFDEFLayoutGenerator *> m_macro_generators;
|
std::map<std::string, LEFDEFLayoutGenerator *> m_macro_generators;
|
||||||
|
std::map<std::string, db::cell_index_type> m_foreign_cells;
|
||||||
|
|
||||||
std::pair <bool, unsigned int> open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
|
std::pair <bool, unsigned int> open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
|
||||||
void map_layer_explicit (const std::string &n, LayerPurpose purpose, const LayerProperties &lp, unsigned int layer, unsigned int mask);
|
void map_layer_explicit (const std::string &n, LayerPurpose purpose, const LayerProperties &lp, unsigned int layer, unsigned int mask);
|
||||||
|
db::cell_index_type foreign_cell(Layout &layout, const std::string &name);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include "dbLEFDEFImporter.h"
|
#include "dbLEFDEFImporter.h"
|
||||||
#include "dbLayoutUtils.h"
|
#include "dbLayoutUtils.h"
|
||||||
#include "dbTechnology.h"
|
#include "dbTechnology.h"
|
||||||
|
#include "dbCellMapping.h"
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
@ -192,6 +193,35 @@ private:
|
||||||
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
|
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
|
||||||
importer.read (m_stream, layout, state);
|
importer.read (m_stream, layout, state);
|
||||||
|
|
||||||
|
// Resolve unresolved COMPONENT cells
|
||||||
|
|
||||||
|
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::Layout *> macro_layouts = lefdef_options->macro_layouts ();
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.finish (layout);
|
state.finish (layout);
|
||||||
|
|
|
||||||
|
|
@ -775,11 +775,14 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
|
||||||
"are three modes available:\n"
|
"are three modes available:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"@ul\n"
|
"@ul\n"
|
||||||
" @li 0: propduce LEF geometry unless a FOREIGN cell is specified (default) @/li\n"
|
" @li 0: produce LEF geometry unless a FOREIGN cell is specified (default) @/li\n"
|
||||||
" @li 1: produce LEF geometry always and ignore FOREIGN @/li\n"
|
" @li 1: produce LEF geometry always and ignore FOREIGN @/li\n"
|
||||||
" @li 2: produce a placeholder cell always (even if FOREIGN isn't given) @/li\n"
|
" @li 2: Never produce LEF geometry @/li\n"
|
||||||
"@/ul\n"
|
"@/ul\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"If substitution layouts are specified with \\macro_layouts, these are used to provide "
|
||||||
|
"macro layouts in case no LEF geometry is taken.\n"
|
||||||
|
"\n"
|
||||||
"This property has been added in version 0.27.\n"
|
"This property has been added in version 0.27.\n"
|
||||||
) +
|
) +
|
||||||
gsi::method ("macro_resolution_mode=", &db::LEFDEFReaderOptions::set_macro_resolution_mode, gsi::arg ("mode"),
|
gsi::method ("macro_resolution_mode=", &db::LEFDEFReaderOptions::set_macro_resolution_mode, gsi::arg ("mode"),
|
||||||
|
|
@ -788,6 +791,25 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
|
||||||
"\n"
|
"\n"
|
||||||
"This property has been added in version 0.27.\n"
|
"This property has been added in version 0.27.\n"
|
||||||
) +
|
) +
|
||||||
|
gsi::method ("macro_layouts", &db::LEFDEFReaderOptions::macro_layouts,
|
||||||
|
"@brief Gets the layout objects used for resolving LEF macros in the DEF reader.\n"
|
||||||
|
"The DEF reader can either use LEF geometry or use a separate source of layouts for the "
|
||||||
|
"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"
|
||||||
|
"\n"
|
||||||
|
"This property has been added in version 0.27.\n"
|
||||||
|
) +
|
||||||
|
gsi::method ("macro_layouts=", &db::LEFDEFReaderOptions::set_macro_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"
|
||||||
|
"Layout objects specified in the array for this property are not owned by the \\LEFDEFReaderConfiguration object. "
|
||||||
|
"Be sure to keep some other reference to these Layout objects if you are storing away the LEF/DEF reader configuration object.\n"
|
||||||
|
"\n"
|
||||||
|
"This property has been added in version 0.27.\n"
|
||||||
|
) +
|
||||||
gsi::method ("lef_files", &db::LEFDEFReaderOptions::lef_files,
|
gsi::method ("lef_files", &db::LEFDEFReaderOptions::lef_files,
|
||||||
"@brief Gets the list technology LEF files to additionally import\n"
|
"@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. "
|
"Returns a list of path names for technology LEF files to read in addition to the primary file. "
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue