mirror of https://github.com/KLayout/klayout.git
Debugging and bug fixes. The 'big example' from issue 2014 now works
This commit is contained in:
parent
1b98efd7a8
commit
5c27fedfe5
|
|
@ -314,8 +314,13 @@ CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_ind
|
|||
}
|
||||
|
||||
void
|
||||
CommonReaderBase::init ()
|
||||
CommonReaderBase::start ()
|
||||
{
|
||||
m_id_map.clear ();
|
||||
m_name_map.clear ();
|
||||
m_temp_cells.clear ();
|
||||
m_name_for_id.clear ();
|
||||
|
||||
m_layer_map_out.clear ();
|
||||
m_multi_mapping_placeholders.clear ();
|
||||
m_layer_cache.clear ();
|
||||
|
|
@ -621,7 +626,7 @@ void
|
|||
CommonReader::init (const LoadLayoutOptions &options)
|
||||
{
|
||||
ReaderBase::init (options);
|
||||
CommonReaderBase::init ();
|
||||
CommonReaderBase::start ();
|
||||
|
||||
db::CommonReaderOptions common_options = options.get_options<db::CommonReaderOptions> ();
|
||||
set_conflict_resolution_mode (common_options.cell_conflict_resolution);
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ public:
|
|||
/**
|
||||
* @brief Re-initialize: clears the tables and caches
|
||||
*/
|
||||
void init ();
|
||||
void start ();
|
||||
|
||||
/**
|
||||
* @brief Sets a value indicating whether to create layers
|
||||
|
|
|
|||
|
|
@ -53,24 +53,11 @@ struct DEFImporterGroup
|
|||
};
|
||||
|
||||
DEFImporter::DEFImporter (int warn_level)
|
||||
: LEFDEFImporter (warn_level),
|
||||
m_lef_importer (warn_level)
|
||||
: LEFDEFImporter (warn_level)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
DEFImporter::read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state)
|
||||
{
|
||||
m_lef_importer.read (stream, layout, state);
|
||||
}
|
||||
|
||||
void
|
||||
DEFImporter::finish_lef (db::Layout &layout)
|
||||
{
|
||||
m_lef_importer.finish_lef (layout);
|
||||
}
|
||||
|
||||
void
|
||||
DEFImporter::read_polygon (db::Polygon &poly, double scale)
|
||||
{
|
||||
|
|
@ -112,7 +99,7 @@ DEFImporter::read_rect (db::Polygon &poly, double scale)
|
|||
std::pair<db::Coord, db::Coord>
|
||||
DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::string &ln, double dbu)
|
||||
{
|
||||
std::pair<double, double> wxy = m_lef_importer.layer_width (ln, rulename);
|
||||
std::pair<double, double> wxy = reader_state ()->lef_importer ().layer_width (ln, rulename);
|
||||
db::Coord wx = db::coord_traits<db::Coord>::rounded (wxy.first / dbu);
|
||||
db::Coord wy = db::coord_traits<db::Coord>::rounded (wxy.second / dbu);
|
||||
|
||||
|
|
@ -127,7 +114,7 @@ DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::st
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<double, double> min_wxy = m_lef_importer.min_layer_width (ln);
|
||||
std::pair<double, double> min_wxy = reader_state ()->lef_importer ().min_layer_width (ln);
|
||||
db::Coord min_wx = db::coord_traits<db::Coord>::rounded (min_wxy.first / dbu);
|
||||
db::Coord min_wy = db::coord_traits<db::Coord>::rounded (min_wxy.second / dbu);
|
||||
|
||||
|
|
@ -769,7 +756,7 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C
|
|||
unsigned int mask_cut = (mask / 10) % 10;
|
||||
unsigned int mask_bottom = mask % 10;
|
||||
|
||||
db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer);
|
||||
db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &reader_state ()->lef_importer ());
|
||||
if (cell) {
|
||||
if (nx <= 1 && ny <= 1) {
|
||||
design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ()))));
|
||||
|
|
@ -953,7 +940,7 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool
|
|||
|
||||
std::map<std::string, ViaDesc>::const_iterator vd = m_via_desc.find (vn);
|
||||
if (vd != m_via_desc.end ()) {
|
||||
db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer);
|
||||
db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &reader_state ()->lef_importer ());
|
||||
if (cell) {
|
||||
design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), pt)));
|
||||
}
|
||||
|
|
@ -1130,7 +1117,7 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale)
|
|||
|
||||
std::string ln = get ();
|
||||
|
||||
if (m_lef_importer.is_routing_layer (ln)) {
|
||||
if (reader_state ()->lef_importer ().is_routing_layer (ln)) {
|
||||
|
||||
if (seen_layers.find (ln) == seen_layers.end ()) {
|
||||
|
||||
|
|
@ -1145,7 +1132,7 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale)
|
|||
|
||||
}
|
||||
|
||||
} else if (m_lef_importer.is_cut_layer (ln)) {
|
||||
} else if (reader_state ()->lef_importer ().is_cut_layer (ln)) {
|
||||
|
||||
geo_based_vg->set_maskshift_layer (1, ln);
|
||||
has_cut_geometry = true;
|
||||
|
|
@ -1336,7 +1323,7 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale)
|
|||
std::map<std::string, ViaDesc>::const_iterator vd = m_via_desc.find (vn);
|
||||
if (vd != m_via_desc.end ()) {
|
||||
std::string nondefaultrule;
|
||||
db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer);
|
||||
db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &reader_state ()->lef_importer ());
|
||||
if (cell) {
|
||||
design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (pt)));
|
||||
}
|
||||
|
|
@ -1549,7 +1536,7 @@ DEFImporter::read_fills (db::Layout &layout, db::Cell &design, double scale)
|
|||
std::map<std::string, ViaDesc>::const_iterator vd = m_via_desc.find (vn);
|
||||
if (vd != m_via_desc.end ()) {
|
||||
std::string nondefaultrule;
|
||||
db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer);
|
||||
db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &reader_state ()->lef_importer ());
|
||||
if (cell) {
|
||||
ensure_fill_cell (layout, design, fill_cell).insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (pt)));
|
||||
}
|
||||
|
|
@ -1613,8 +1600,8 @@ DEFImporter::read_components (db::Layout &layout, std::list<std::pair<std::strin
|
|||
bool is_placed = false;
|
||||
std::string maskshift;
|
||||
|
||||
std::map<std::string, MacroDesc>::const_iterator m = m_lef_importer.macros ().find (model);
|
||||
if (m == m_lef_importer.macros ().end ()) {
|
||||
std::map<std::string, MacroDesc>::const_iterator m = reader_state ()->lef_importer ().macros ().find (model);
|
||||
if (m == reader_state ()->lef_importer ().macros ().end ()) {
|
||||
error (tl::to_string (tr ("Macro not found in LEF file: ")) + model);
|
||||
}
|
||||
|
||||
|
|
@ -1660,7 +1647,7 @@ DEFImporter::read_components (db::Layout &layout, std::list<std::pair<std::strin
|
|||
|
||||
if (is_placed) {
|
||||
|
||||
std::pair<db::Cell *, db::Trans> ct = reader_state ()->macro_cell (model, layout, m_component_maskshift, string2masks (maskshift), m->second, &m_lef_importer);
|
||||
std::pair<db::Cell *, db::Trans> ct = reader_state ()->macro_cell (model, layout, m_component_maskshift, string2masks (maskshift), m->second, &reader_state ()->lef_importer ());
|
||||
if (ct.first) {
|
||||
db::CellInstArray inst (db::CellInst (ct.first->cell_index ()), db::Trans (ft.rot (), d) * ct.second);
|
||||
instances.push_back (std::make_pair (inst_name, inst));
|
||||
|
|
@ -1684,7 +1671,7 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
std::list<DEFImporterGroup> groups;
|
||||
std::list<std::pair<std::string, db::CellInstArray> > instances;
|
||||
|
||||
m_via_desc = m_lef_importer.vias ();
|
||||
m_via_desc = reader_state ()->lef_importer ().vias ();
|
||||
m_styles.clear ();
|
||||
m_design_name.clear ();
|
||||
|
||||
|
|
|
|||
|
|
@ -48,26 +48,12 @@ public:
|
|||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
DEFImporter (int warn_level = 1);
|
||||
|
||||
/**
|
||||
* @brief Read the given LEF file prior to the DEF file
|
||||
*
|
||||
* This method reads the layout specified into the given layout.
|
||||
* Multiple LEF files can be read.
|
||||
*/
|
||||
void read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state);
|
||||
|
||||
/**
|
||||
* @brief Provided for test purposes
|
||||
*/
|
||||
void finish_lef (Layout &layout);
|
||||
DEFImporter (int warn_level);
|
||||
|
||||
protected:
|
||||
void do_read (db::Layout &layout);
|
||||
|
||||
private:
|
||||
LEFImporter m_lef_importer;
|
||||
std::map<std::string, std::map<std::string, db::Coord> > m_nondefault_widths;
|
||||
std::map<std::string, ViaDesc> m_via_desc;
|
||||
std::map<int, db::Polygon> m_styles;
|
||||
|
|
|
|||
|
|
@ -22,9 +22,11 @@
|
|||
|
||||
|
||||
#include "dbLEFDEFImporter.h"
|
||||
#include "dbLEFImporter.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "dbTechnology.h"
|
||||
#include "dbShapeProcessor.h"
|
||||
#include "dbCellMapping.h"
|
||||
|
||||
#include "tlStream.h"
|
||||
#include "tlProgress.h"
|
||||
|
|
@ -958,6 +960,7 @@ LEFDEFReaderOptions::set_lef_context_enabled (bool f)
|
|||
{
|
||||
if (f != m_lef_context_enabled) {
|
||||
mp_reader_state.reset (0);
|
||||
m_lef_context_enabled = f;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1036,8 +1039,8 @@ LEFDEFReaderState::init (Layout &layout, const std::string &base_path, const Loa
|
|||
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 ());
|
||||
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 ()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1063,6 +1066,33 @@ LEFDEFReaderState::warn (const std::string &msg, int warn_level)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderState::ensure_lef_importer (int warn_level)
|
||||
{
|
||||
if (! mp_lef_importer.get ()) {
|
||||
mp_lef_importer.reset (new db::LEFImporter (warn_level));
|
||||
}
|
||||
}
|
||||
|
||||
db::LEFImporter &
|
||||
LEFDEFReaderState::lef_importer ()
|
||||
{
|
||||
tl_assert (mp_lef_importer.get () != 0);
|
||||
return *mp_lef_importer;
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderState::read_lef (tl::InputStream &stream, db::Layout &layout)
|
||||
{
|
||||
lef_importer ().read (stream, layout, *this);
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderState::finish_lef (db::Layout &layout)
|
||||
{
|
||||
lef_importer ().finish_lef (layout);
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderState::register_layer (const std::string &ln)
|
||||
{
|
||||
|
|
@ -1774,11 +1804,56 @@ std::set<unsigned int> LEFDEFReaderState::open_layer_uncached(db::Layout &layout
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderState::start ()
|
||||
{
|
||||
CommonReaderBase::start ();
|
||||
|
||||
m_foreign_cells.clear ();
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderState::finish (db::Layout &layout)
|
||||
{
|
||||
CommonReaderBase::finish (layout);
|
||||
|
||||
// Resolve unresolved COMPONENT cells
|
||||
|
||||
db::cell_index_type seen = std::numeric_limits<db::cell_index_type>::max ();
|
||||
|
||||
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 = m_foreign_cells.begin (); f != m_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);
|
||||
|
||||
}
|
||||
|
||||
// Warn about cells that could not be resolved
|
||||
for (std::map<std::string, db::cell_index_type>::iterator f = m_foreign_cells.begin (); f != m_foreign_cells.end (); ++f) {
|
||||
if (f->second != seen && layout.cell (f->second).is_ghost_cell ()) {
|
||||
warn (tl::sprintf (tl::to_string (tr ("Could not find a substitution layout for foreign cell '%s'")),
|
||||
f->first));
|
||||
}
|
||||
}
|
||||
|
||||
// Create the layers
|
||||
|
||||
int lnum = 0;
|
||||
|
||||
std::set<int> used_numbers;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ namespace db
|
|||
|
||||
class LEFDEFReaderState;
|
||||
class LEFDEFImporter;
|
||||
class LEFImporter;
|
||||
struct MacroDesc;
|
||||
|
||||
/**
|
||||
|
|
@ -1325,8 +1326,15 @@ public:
|
|||
*/
|
||||
void register_layer (const std::string &l);
|
||||
|
||||
/**
|
||||
* @brief Start reading a file
|
||||
* After the file is read, "finish" needs to be called.
|
||||
*/
|
||||
void start ();
|
||||
|
||||
/**
|
||||
* @brief Finish, i.e. assign GDS layer numbers to the layers
|
||||
* This is the counterpart for "start".
|
||||
*/
|
||||
void finish (db::Layout &layout);
|
||||
|
||||
|
|
@ -1390,6 +1398,28 @@ public:
|
|||
*/
|
||||
void warn (const std::string &msg, int warn_level = 1);
|
||||
|
||||
/**
|
||||
* @brief Ensures the LEF importer for DEF reading is available
|
||||
*/
|
||||
void ensure_lef_importer (int warn_level);
|
||||
|
||||
/**
|
||||
* @brief Gets the LEF importer for DEF reading
|
||||
*/
|
||||
db::LEFImporter &lef_importer ();
|
||||
|
||||
/**
|
||||
* @brief Reads a LEF file into the LEF importer
|
||||
*
|
||||
* Multiple LEF files can be read.
|
||||
*/
|
||||
void read_lef (tl::InputStream &stream, db::Layout &layout);
|
||||
|
||||
/**
|
||||
* @brief Provided for test purposes
|
||||
*/
|
||||
void finish_lef (db::Layout &layout);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the given LEF file was already read
|
||||
*/
|
||||
|
|
@ -1510,6 +1540,7 @@ private:
|
|||
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::unique_ptr<db::LEFImporter> mp_lef_importer;
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -138,6 +138,9 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
|
|||
state = &local_state;
|
||||
}
|
||||
|
||||
state->ensure_lef_importer (warn_level ());
|
||||
state->start ();
|
||||
|
||||
// Configure the conflict resolution mode
|
||||
db::CommonReaderOptions common_options = options.get_options<db::CommonReaderOptions> ();
|
||||
state->set_conflict_resolution_mode (common_options.cell_conflict_resolution);
|
||||
|
|
@ -186,7 +189,7 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
|
|||
|
||||
tl::InputStream lef_stream (norm_lp);
|
||||
tl::log << tl::to_string (tr ("Reading")) << " " << *lp;
|
||||
importer.read_lef (lef_stream, layout, *state);
|
||||
state->read_lef (lef_stream, layout);
|
||||
|
||||
state->register_lef_file (norm_lp);
|
||||
|
||||
|
|
@ -219,7 +222,7 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
|
|||
|
||||
tl::InputStream lef_stream (norm_lp);
|
||||
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
|
||||
importer.read_lef (lef_stream, layout, *state);
|
||||
state->read_lef (lef_stream, layout);
|
||||
|
||||
state->register_lef_file (norm_lp);
|
||||
|
||||
|
|
@ -236,42 +239,6 @@ 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);
|
||||
|
||||
// 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 ();
|
||||
|
||||
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;
|
||||
|
||||
// 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);
|
||||
|
||||
}
|
||||
|
||||
// Warn about cells that could not be resolved
|
||||
for (std::map<std::string, db::cell_index_type>::iterator f = foreign_cells.begin (); f != foreign_cells.end (); ++f) {
|
||||
if (f->second != seen && layout.cell (f->second).is_ghost_cell ()) {
|
||||
importer.warn (tl::sprintf (tl::to_string (tr ("Could not find a substitution layout for foreign cell '%s'")),
|
||||
f->first));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
state->finish (layout);
|
||||
|
|
|
|||
|
|
@ -61,10 +61,11 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f
|
|||
|
||||
db::LoadLayoutOptions other_options;
|
||||
db::LEFDEFReaderState ld (&options);
|
||||
ld.ensure_lef_importer (1);
|
||||
ld.init (layout, fn_path, other_options);
|
||||
ld.set_conflict_resolution_mode (cc_mode);
|
||||
|
||||
db::DEFImporter imp;
|
||||
db::DEFImporter imp (1);
|
||||
bool any_def = false;
|
||||
bool any_lef = false;
|
||||
|
||||
|
|
@ -95,7 +96,7 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f
|
|||
fn += f;
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
imp.read_lef (stream, layout, ld);
|
||||
ld.read_lef (stream, layout);
|
||||
|
||||
any_lef = true;
|
||||
|
||||
|
|
@ -136,7 +137,7 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f
|
|||
}
|
||||
|
||||
if (! any_def && any_lef) {
|
||||
imp.finish_lef (layout);
|
||||
ld.finish_lef (layout);
|
||||
}
|
||||
|
||||
ld.finish (layout);
|
||||
|
|
|
|||
Loading…
Reference in New Issue