WIP: first implementation. Builds, but needs testing.

This commit is contained in:
Matthias Koefferlein 2025-05-15 23:27:03 +02:00
parent a208c6d25d
commit 271800ab94
6 changed files with 177 additions and 67 deletions

View File

@ -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);
}
}

View File

@ -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)
{

View File

@ -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 *> &macro_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);

View File

@ -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;
}

View File

@ -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. "

View File

@ -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;