mirror of https://github.com/KLayout/klayout.git
WIP: first implementation. Builds, but needs testing.
This commit is contained in:
parent
a208c6d25d
commit
271800ab94
|
|
@ -846,12 +846,16 @@ static std::vector<std::string> split_file_list (const std::string &infile)
|
|||
|
||||
void read_files (db::Layout &layout, const std::string &infile, const db::LoadLayoutOptions &options)
|
||||
{
|
||||
// enter a LEF caching context for chaining multiple DEF with the same LEF
|
||||
db::LoadLayoutOptions local_options (options);
|
||||
local_options.set_option_by_name ("lefdef_config.lef_context_enabled", true);
|
||||
|
||||
std::vector<std::string> files = split_file_list (infile);
|
||||
|
||||
for (std::vector<std::string>::const_iterator f = files.begin (); f != files.end (); ++f) {
|
||||
tl::InputStream stream (*f);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout, options);
|
||||
reader.read (layout, local_options);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -598,7 +598,8 @@ LEFDEFReaderOptions::LEFDEFReaderOptions ()
|
|||
m_map_file (),
|
||||
m_macro_resolution_mode (0),
|
||||
m_read_lef_with_def (true),
|
||||
m_paths_relative_to_cwd (false)
|
||||
m_paths_relative_to_cwd (false),
|
||||
m_lef_context_enabled (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -951,26 +952,32 @@ LEFDEFReaderOptions::special_routing_datatype_str () const
|
|||
return get_datatypes (this, &LEFDEFReaderOptions::special_routing_datatype, &LEFDEFReaderOptions::special_routing_datatype_per_mask, max_mask_number ());
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderOptions::set_lef_context_enabled (bool f)
|
||||
{
|
||||
if (f != m_lef_context_enabled) {
|
||||
mp_reader_state.reset (0);
|
||||
}
|
||||
}
|
||||
|
||||
db::LEFDEFReaderState *
|
||||
LEFDEFReaderOptions::reader_state (db::Layout &layout, const std::string &base_path, const db::LoadLayoutOptions &options) const
|
||||
{
|
||||
if (m_lef_context_enabled && ! mp_reader_state.get ()) {
|
||||
mp_reader_state.reset (new db::LEFDEFReaderState (this));
|
||||
mp_reader_state->init (layout, base_path, options);
|
||||
}
|
||||
|
||||
return mp_reader_state.get ();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// LEFDEFLayerDelegate implementation
|
||||
|
||||
LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout, const std::string &base_path)
|
||||
LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc)
|
||||
: mp_importer (0), m_create_layers (true), m_has_explicit_layer_mapping (false), m_laynum (1), mp_tech_comp (tc)
|
||||
{
|
||||
if (! tc) {
|
||||
|
||||
// use default options
|
||||
|
||||
} else if (! tc->map_file ().empty ()) {
|
||||
|
||||
read_map_file (tc->map_file (), layout, base_path);
|
||||
|
||||
} else {
|
||||
|
||||
m_layer_map = tc->layer_map ();
|
||||
m_create_layers = tc->read_all_layers ();
|
||||
|
||||
}
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
LEFDEFReaderState::~LEFDEFReaderState ()
|
||||
|
|
@ -988,6 +995,57 @@ LEFDEFReaderState::~LEFDEFReaderState ()
|
|||
m_macro_generators.clear ();
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderState::init (Layout &layout, const std::string &base_path, const LoadLayoutOptions &options)
|
||||
{
|
||||
if (! mp_tech_comp) {
|
||||
|
||||
// use default options
|
||||
|
||||
} else if (! mp_tech_comp->map_file ().empty ()) {
|
||||
|
||||
read_map_file (mp_tech_comp->map_file (), layout, base_path);
|
||||
|
||||
} else {
|
||||
|
||||
m_layer_map = mp_tech_comp->layer_map ();
|
||||
m_create_layers = mp_tech_comp->read_all_layers ();
|
||||
|
||||
}
|
||||
|
||||
if (mp_tech_comp) {
|
||||
|
||||
m_macro_layouts = mp_tech_comp->macro_layouts ();
|
||||
|
||||
// Additionally read the layouts from the given paths
|
||||
for (std::vector<std::string>::const_iterator l = mp_tech_comp->begin_macro_layout_files (); l != mp_tech_comp->end_macro_layout_files (); ++l) {
|
||||
|
||||
auto paths = correct_path (*l, layout, base_path, true);
|
||||
for (auto lp = paths.begin (); lp != paths.end (); ++lp) {
|
||||
|
||||
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);
|
||||
m_macro_layout_object_holder.push_back (new_layout);
|
||||
m_macro_layouts.push_back (new_layout);
|
||||
|
||||
db::Reader reader (macro_layout_stream);
|
||||
reader.read (*new_layout, options);
|
||||
|
||||
if (fabs (new_layout->dbu () / layout.dbu () - 1.0) > db::epsilon) {
|
||||
tl::warn << tl::sprintf (tl::to_string (tr ("DBU of macro layout file '%s' does not match reader DBU (layout DBU is %.12g, reader DBU is set to %.12g)")),
|
||||
*lp, new_layout->dbu (), layout.dbu ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderState::error (const std::string &msg)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -960,6 +960,25 @@ public:
|
|||
m_macro_layout_files = lf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A hidden attribute to enable a LEF context
|
||||
* LEF context are used for chaining DEF readers. This method must be
|
||||
* called on local copy of the importer options. With this attribute
|
||||
* set to "true", the client code can store a LEFDEFReaderState object
|
||||
* in this object.
|
||||
* Initially, this attribute is set to false.
|
||||
* Note that this attribute is not copied.
|
||||
*/
|
||||
void set_lef_context_enabled (bool context);
|
||||
|
||||
bool lef_context_enabled () const
|
||||
{
|
||||
return m_lef_context_enabled;
|
||||
}
|
||||
|
||||
// makes the reader state object if required
|
||||
db::LEFDEFReaderState *reader_state (db::Layout &layout, const std::string &base_path, const LoadLayoutOptions &options) const;
|
||||
|
||||
private:
|
||||
bool m_read_all_layers;
|
||||
db::LayerMap m_layer_map;
|
||||
|
|
@ -1028,6 +1047,8 @@ private:
|
|||
tl::weak_collection<db::Layout> m_macro_layouts;
|
||||
std::vector<std::string> m_macro_layout_files;
|
||||
bool m_paths_relative_to_cwd;
|
||||
bool m_lef_context_enabled;
|
||||
mutable std::unique_ptr<db::LEFDEFReaderState> mp_reader_state;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1247,13 +1268,18 @@ public:
|
|||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout, const std::string &base_path = std::string ());
|
||||
LEFDEFReaderState (const LEFDEFReaderOptions *tc);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~LEFDEFReaderState ();
|
||||
|
||||
/**
|
||||
* @brief Initialize with the layout and base path
|
||||
*/
|
||||
void init (db::Layout &layout, const std::string &base_path, const LoadLayoutOptions &options);
|
||||
|
||||
/**
|
||||
* @brief Attaches to or detaches from an importer
|
||||
*/
|
||||
|
|
@ -1364,6 +1390,31 @@ public:
|
|||
*/
|
||||
void warn (const std::string &msg, int warn_level = 1);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the given LEF file was already read
|
||||
*/
|
||||
bool lef_file_already_read (const std::string &fn)
|
||||
{
|
||||
return m_lef_files_read.find (fn) != m_lef_files_read.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Registers a LEF file
|
||||
* After registration, the same file will report "already_read"
|
||||
*/
|
||||
void register_lef_file (const std::string &fn)
|
||||
{
|
||||
m_lef_files_read.insert (fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the stored macro layouts
|
||||
*/
|
||||
const std::vector<db::Layout *> ¯o_layouts () const
|
||||
{
|
||||
return m_macro_layouts;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void common_reader_error (const std::string &msg) { error (msg); }
|
||||
virtual void common_reader_warn (const std::string &msg, int warn_level) { warn (msg, warn_level); }
|
||||
|
|
@ -1456,6 +1507,9 @@ private:
|
|||
std::map<MacroKey, std::pair<db::Cell *, db::Trans> > m_macro_cells;
|
||||
std::map<std::string, LEFDEFLayoutGenerator *> m_macro_generators;
|
||||
std::map<std::string, db::cell_index_type> m_foreign_cells;
|
||||
std::set<std::string> m_lef_files_read;
|
||||
std::vector<db::Layout *> m_macro_layouts;
|
||||
tl::shared_collection<db::Layout> m_macro_layout_object_holder;
|
||||
|
||||
std::set<unsigned int> open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
|
||||
db::cell_index_type foreign_cell(Layout &layout, const std::string &name);
|
||||
|
|
|
|||
|
|
@ -113,23 +113,36 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
|
|||
init (options);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
layout.dbu (effective_options.dbu ());
|
||||
|
||||
std::string base_path;
|
||||
if (! effective_options.paths_relative_to_cwd ()) {
|
||||
base_path = tl::dirname (m_stream.absolute_file_path ());
|
||||
}
|
||||
|
||||
db::LEFDEFReaderState state (&effective_options, layout, base_path);
|
||||
// If the LEF reader context (LEF caching) is enabled on the options,
|
||||
// pull the state from there, otherwise create a local state.
|
||||
db::LEFDEFReaderState local_state (&effective_options);
|
||||
db::LEFDEFReaderState *state = 0;
|
||||
if (lefdef_options) {
|
||||
state = lefdef_options->reader_state (layout, base_path, options);
|
||||
}
|
||||
if (! state) {
|
||||
local_state.init (layout, base_path, options);
|
||||
state = &local_state;
|
||||
}
|
||||
|
||||
// Configure the conflict resolution mode
|
||||
db::CommonReaderOptions common_options = options.get_options<db::CommonReaderOptions> ();
|
||||
state.set_conflict_resolution_mode (common_options.cell_conflict_resolution);
|
||||
|
||||
layout.dbu (effective_options.dbu ());
|
||||
state->set_conflict_resolution_mode (common_options.cell_conflict_resolution);
|
||||
|
||||
// Import LEF
|
||||
if (import_lef) {
|
||||
|
||||
// Always produce LEF geometry when reading LEF
|
||||
|
|
@ -145,13 +158,13 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
|
|||
for (auto lp = paths.begin (); lp != paths.end (); ++lp) {
|
||||
tl::InputStream lef_stream (*lp);
|
||||
tl::log << tl::to_string (tr ("Reading")) << " " << *lp;
|
||||
importer.read (lef_stream, layout, state);
|
||||
importer.read (lef_stream, layout, *state);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
|
||||
importer.read (m_stream, layout, state);
|
||||
importer.read (m_stream, layout, *state);
|
||||
|
||||
importer.finish_lef (layout);
|
||||
|
||||
|
|
@ -161,20 +174,21 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
|
|||
|
||||
DEFImporter importer (warn_level ());
|
||||
|
||||
std::set<std::string> lef_files_read;
|
||||
|
||||
for (std::vector<std::string>::const_iterator l = effective_options.begin_lef_files (); l != effective_options.end_lef_files (); ++l) {
|
||||
|
||||
auto paths = correct_path (*l, layout, base_path, true);
|
||||
for (auto lp = paths.begin (); lp != paths.end (); ++lp) {
|
||||
|
||||
if (lef_files_read.insert (tl::normalize_path (*lp)).second) {
|
||||
std::string norm_lp = tl::normalize_path (*lp);
|
||||
if (! state->lef_file_already_read (norm_lp)) {
|
||||
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + *lp);
|
||||
|
||||
tl::InputStream lef_stream (*lp);
|
||||
tl::InputStream lef_stream (norm_lp);
|
||||
tl::log << tl::to_string (tr ("Reading")) << " " << *lp;
|
||||
importer.read_lef (lef_stream, layout, state);
|
||||
importer.read_lef (lef_stream, layout, *state);
|
||||
|
||||
state->register_lef_file (norm_lp);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -198,13 +212,16 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
|
|||
std::string lp = tl::combine_path (input_dir, *e);
|
||||
|
||||
// skip if already read (issue-1724)
|
||||
if (lef_files_read.find (tl::normalize_path (lp)) == lef_files_read.end ()) {
|
||||
std::string norm_lp = tl::normalize_path (lp);
|
||||
if (! state->lef_file_already_read (norm_lp)) {
|
||||
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp);
|
||||
|
||||
tl::InputStream lef_stream (lp);
|
||||
tl::InputStream lef_stream (norm_lp);
|
||||
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
|
||||
importer.read_lef (lef_stream, layout, state);
|
||||
importer.read_lef (lef_stream, layout, *state);
|
||||
|
||||
state->register_lef_file (norm_lp);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -217,43 +234,14 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
|
|||
}
|
||||
|
||||
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 ();
|
||||
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 = effective_options.macro_layouts ();
|
||||
|
||||
// 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) {
|
||||
|
||||
auto paths = correct_path (*l, layout, base_path, true);
|
||||
for (auto lp = paths.begin (); lp != paths.end (); ++lp) {
|
||||
|
||||
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);
|
||||
|
||||
if (fabs (new_layout->dbu () / layout.dbu () - 1.0) > db::epsilon) {
|
||||
importer.warn (tl::sprintf (tl::to_string (tr ("DBU of macro layout file '%s' does not match reader DBU (layout DBU is %.12g, reader DBU is set to %.12g)")),
|
||||
*lp, new_layout->dbu (), layout.dbu ()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (std::vector<db::Layout *>::const_iterator m = macro_layouts.begin (); m != macro_layouts.end (); ++m) {
|
||||
for (std::vector<db::Layout *>::const_iterator m = state->macro_layouts ().begin (); m != state->macro_layouts ().end (); ++m) {
|
||||
|
||||
std::vector<db::cell_index_type> target_cells, source_cells;
|
||||
|
||||
|
|
@ -286,9 +274,9 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
|
|||
|
||||
}
|
||||
|
||||
state.finish (layout);
|
||||
state->finish (layout);
|
||||
|
||||
m_layer_map = state.layer_map ();
|
||||
m_layer_map = state->layer_map ();
|
||||
return m_layer_map;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -997,6 +997,10 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
|
|||
"See \\read_lef_with_def for details about this property.\n"
|
||||
"\n"
|
||||
"This property has been added in version 0.27.\n"
|
||||
) +
|
||||
// special attribute to implement LEF caching
|
||||
gsi::method ("lef_context_enabled=", &db::LEFDEFReaderOptions::set_lef_context_enabled,
|
||||
"@hide\n"
|
||||
),
|
||||
"@brief Detailed LEF/DEF reader options\n"
|
||||
"This class is a aggregate belonging to the \\LoadLayoutOptions class. It provides options for the LEF/DEF reader. "
|
||||
|
|
|
|||
|
|
@ -59,7 +59,9 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f
|
|||
|
||||
tl::Extractor ex (filename);
|
||||
|
||||
db::LEFDEFReaderState ld (&options, layout, fn_path);
|
||||
db::LoadLayoutOptions other_options;
|
||||
db::LEFDEFReaderState ld (&options);
|
||||
ld.init (layout, fn_path, other_options);
|
||||
ld.set_conflict_resolution_mode (cc_mode);
|
||||
|
||||
db::DEFImporter imp;
|
||||
|
|
|
|||
Loading…
Reference in New Issue