mirror of https://github.com/KLayout/klayout.git
WIP: First implementation. Needs testing.
This commit is contained in:
parent
96123c3429
commit
eb3600d620
|
|
@ -29,6 +29,279 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Common reader implementation
|
||||
|
||||
static const size_t null_id = std::numeric_limits<size_t>::max ();
|
||||
|
||||
CommonReader::CommonReader ()
|
||||
: m_cc_resolution (AddToCell)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
db::cell_index_type
|
||||
CommonReader::make_cell (db::Layout &layout, const std::string &cn)
|
||||
{
|
||||
tl_assert (! cn.empty ());
|
||||
|
||||
std::map<std::string, std::pair<size_t, db::cell_index_type> >::iterator iname = m_name_map.find (cn);
|
||||
if (iname != m_name_map.end ()) {
|
||||
|
||||
db::Cell &cell = layout.cell (iname->second.second);
|
||||
|
||||
if (! cell.is_ghost_cell ()) {
|
||||
common_reader_error (tl::sprintf (tl::to_string (tr ("A cell with name %s already exists")), cn));
|
||||
}
|
||||
|
||||
cell.set_ghost_cell (false);
|
||||
return cell.cell_index ();
|
||||
|
||||
} else {
|
||||
|
||||
db::cell_index_type ci = layout.add_cell ();
|
||||
|
||||
m_name_map [cn] = std::make_pair (null_id, ci);
|
||||
return ci;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CommonReader::has_cell (const std::string &cn) const
|
||||
{
|
||||
return m_name_map.find (cn) != m_name_map.end ();
|
||||
}
|
||||
|
||||
std::pair<bool, db::cell_index_type>
|
||||
CommonReader::cell_by_name (const std::string &cn) const
|
||||
{
|
||||
std::map<std::string, std::pair<size_t, db::cell_index_type> >::const_iterator iname = m_name_map.find (cn);
|
||||
if (iname != m_name_map.end ()) {
|
||||
return std::make_pair (true, iname->second.second);
|
||||
} else {
|
||||
return std::make_pair (false, size_t (0));
|
||||
}
|
||||
}
|
||||
|
||||
db::cell_index_type
|
||||
CommonReader::make_cell (db::Layout &layout, size_t id)
|
||||
{
|
||||
tl_assert (id != null_id);
|
||||
|
||||
std::map<size_t, std::pair<std::string, db::cell_index_type> >::iterator iid = m_id_map.find (id);
|
||||
if (iid != m_id_map.end ()) {
|
||||
|
||||
db::Cell &cell = layout.cell (iid->second.second);
|
||||
|
||||
if (! cell.is_ghost_cell ()) {
|
||||
common_reader_error (tl::sprintf (tl::to_string (tr ("A cell with ID %ld already exists")), id));
|
||||
}
|
||||
|
||||
cell.set_ghost_cell (false);
|
||||
return cell.cell_index ();
|
||||
|
||||
} else {
|
||||
|
||||
db::cell_index_type ci = layout.add_cell ();
|
||||
|
||||
m_id_map [id] = std::make_pair (std::string (), ci);
|
||||
return ci;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CommonReader::has_cell (size_t id) const
|
||||
{
|
||||
return m_id_map.find (id) != m_id_map.end ();
|
||||
}
|
||||
|
||||
std::pair<bool, db::cell_index_type>
|
||||
CommonReader::cell_by_id (size_t id) const
|
||||
{
|
||||
std::map<size_t, std::pair<std::string, db::cell_index_type> >::const_iterator iid = m_id_map.find (id);
|
||||
if (iid != m_id_map.end ()) {
|
||||
return std::make_pair (true, iid->second.second);
|
||||
} else {
|
||||
return std::make_pair (false, size_t (0));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CommonReader::rename_cell (db::Layout &layout, size_t id, const std::string &cn)
|
||||
{
|
||||
std::map<size_t, std::pair<std::string, db::cell_index_type> >::iterator iid = m_id_map.find (id);
|
||||
std::map<std::string, std::pair<size_t, db::cell_index_type> >::iterator iname = m_name_map.find (cn);
|
||||
|
||||
if (iid != m_id_map.end () && iname != m_name_map.end ()) {
|
||||
|
||||
if (iid->second.first != cn) {
|
||||
common_reader_error (tl::sprintf (tl::to_string (tr ("Cell named %s with ID %ld was already given name %s")), cn, id, iid->second.first));
|
||||
}
|
||||
|
||||
if (iname->second.second != iid->second.second) {
|
||||
|
||||
// Both cells already exist and are not identical: merge ID-declared cell into the name-declared one
|
||||
layout.force_update ();
|
||||
merge_cell (layout, iname->second.second, iid->second.second);
|
||||
iid->second.second = iname->second.second;
|
||||
|
||||
}
|
||||
|
||||
} else if (iid != m_id_map.end ()) {
|
||||
|
||||
m_name_map [cn] = std::make_pair (id, iid->second.second);
|
||||
|
||||
} else if (iname != m_name_map.end ()) {
|
||||
|
||||
m_id_map [id] = std::make_pair (cn, iname->second.second);
|
||||
|
||||
} else {
|
||||
|
||||
db::cell_index_type ci = layout.add_cell ();
|
||||
|
||||
m_id_map [id] = std::make_pair (std::string (), ci);
|
||||
m_name_map [cn] = std::make_pair (null_id, ci);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
db::cell_index_type
|
||||
CommonReader::cell_for_instance (db::Layout &layout, size_t id)
|
||||
{
|
||||
tl_assert (id != null_id);
|
||||
|
||||
std::map<size_t, std::pair<std::string, db::cell_index_type> >::iterator iid = m_id_map.find (id);
|
||||
if (iid != m_id_map.end ()) {
|
||||
|
||||
return iid->second.second;
|
||||
|
||||
} else {
|
||||
|
||||
db::cell_index_type ci = layout.add_cell ();
|
||||
layout.cell (ci).set_ghost_cell (true);
|
||||
|
||||
m_id_map [id] = std::make_pair (std::string (), ci);
|
||||
return ci;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
db::cell_index_type
|
||||
CommonReader::cell_for_instance (db::Layout &layout, const std::string &cn)
|
||||
{
|
||||
tl_assert (! cn.empty ());
|
||||
|
||||
std::map<std::string, std::pair<size_t, db::cell_index_type> >::iterator iname = m_name_map.find (cn);
|
||||
if (iname != m_name_map.end ()) {
|
||||
|
||||
return iname->second.second;
|
||||
|
||||
} else {
|
||||
|
||||
db::cell_index_type ci = layout.add_cell ();
|
||||
layout.cell (ci).set_ghost_cell (true);
|
||||
|
||||
m_name_map [cn] = std::make_pair (null_id, ci);
|
||||
return ci;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CommonReader::merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const
|
||||
{
|
||||
const db::Cell &src_cell = layout.cell (src_cell_index);
|
||||
db::Cell &target_cell = layout.cell (target_cell_index);
|
||||
|
||||
// copy over the instances
|
||||
for (db::Cell::const_iterator i = src_cell.begin (); ! i.at_end (); ++i) {
|
||||
target_cell.insert (*i);
|
||||
}
|
||||
|
||||
// copy over the shapes
|
||||
for (unsigned int l = 0; l < layout.layers (); ++l) {
|
||||
if (layout.is_valid_layer (l) && ! src_cell.shapes (l).empty ()) {
|
||||
target_cell.shapes (l).insert (src_cell.shapes (l));
|
||||
}
|
||||
}
|
||||
|
||||
// replace all instances of the new cell with the original one
|
||||
std::vector<std::pair<db::cell_index_type, db::Instance> > parents;
|
||||
for (db::Cell::parent_inst_iterator pi = src_cell.begin_parent_insts (); ! pi.at_end (); ++pi) {
|
||||
parents.push_back (std::make_pair (pi->parent_cell_index (), pi->child_inst ()));
|
||||
}
|
||||
|
||||
for (std::vector<std::pair<db::cell_index_type, db::Instance> >::const_iterator p = parents.begin (); p != parents.end (); ++p) {
|
||||
db::CellInstArray ia = p->second.cell_inst ();
|
||||
ia.object ().cell_index (target_cell.cell_index ());
|
||||
layout.cell (p->first).replace (p->second, ia);
|
||||
}
|
||||
|
||||
// finally delete the new cell
|
||||
layout.delete_cell (src_cell.cell_index ());
|
||||
}
|
||||
|
||||
void
|
||||
CommonReader::finish (db::Layout &layout)
|
||||
{
|
||||
bool any_missing = false;
|
||||
|
||||
for (std::map<size_t, std::pair<std::string, db::cell_index_type> >::const_iterator i = m_id_map.begin (); i != m_id_map.end (); ++i) {
|
||||
if (i->second.first.empty ()) {
|
||||
common_reader_warn (tl::sprintf (tl::to_string (tr ("Cell name missing for ID %ld")), i->first));
|
||||
any_missing = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (any_missing) {
|
||||
common_reader_error (tl::to_string (tr ("Some cell IDs don't have a name (see previous warnings)")));
|
||||
}
|
||||
|
||||
for (std::map<std::string, std::pair<size_t, db::cell_index_type> >::const_iterator i = m_name_map.begin (); i != m_name_map.end (); ++i) {
|
||||
|
||||
if (layout.has_cell (i->first.c_str ())) {
|
||||
|
||||
db::cell_index_type ci_org = layout.cell_by_name (i->first.c_str ()).second;
|
||||
db::cell_index_type ci_new = i->second.second;
|
||||
|
||||
if (m_cc_resolution == RenameCell || layout.cell (ci_org).is_proxy ()) {
|
||||
|
||||
// NOTE: we never reopen proxies (they are always local to their layout). Instead we
|
||||
// always rename for proxies
|
||||
layout.rename_cell (i->second.second, i->first.c_str ());
|
||||
|
||||
} else {
|
||||
|
||||
// we have a cell conflict
|
||||
layout.force_update ();
|
||||
|
||||
if (m_cc_resolution == OverwriteCell && ! layout.cell (ci_new).is_ghost_cell ()) {
|
||||
|
||||
layout.prune_subcells (ci_org);
|
||||
layout.cell (ci_org).clear_shapes ();
|
||||
|
||||
} else if (m_cc_resolution == SkipNewCell && ! layout.cell (ci_org).is_ghost_cell ()) {
|
||||
|
||||
layout.prune_subcells (ci_new);
|
||||
layout.cell (ci_new).clear_shapes ();
|
||||
|
||||
}
|
||||
|
||||
merge_cell (layout, ci_org, ci_new);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
layout.rename_cell (i->second.second, i->first.c_str ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Common format declaration
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,117 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A common reader base for GDS2 and OASIS providing common services for both readers
|
||||
*/
|
||||
class DB_PUBLIC CommonReader
|
||||
: public ReaderBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief The CellConflictResolution enum
|
||||
*/
|
||||
enum CellConflictResolution
|
||||
{
|
||||
AddToCell = 0,
|
||||
OverwriteCell = 1,
|
||||
SkipNewCell = 2,
|
||||
RenameCell = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
CommonReader ();
|
||||
|
||||
/**
|
||||
* @brief Sets the cell name conflict resolution mode
|
||||
*/
|
||||
void set_cell_conflict_resolution (CellConflictResolution cc_resolution)
|
||||
{
|
||||
m_cc_resolution = cc_resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the cell name conflict resolution mode
|
||||
*/
|
||||
CellConflictResolution cell_conflict_resolution () const
|
||||
{
|
||||
return m_cc_resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Make a cell from a name
|
||||
*/
|
||||
db::cell_index_type make_cell (db::Layout &layout, const std::string &cn);
|
||||
|
||||
/**
|
||||
* @brief Returns true, if there is a cell with the given name already
|
||||
*/
|
||||
bool has_cell (const std::string &cn) const;
|
||||
|
||||
/**
|
||||
* @brief Returns a pair with a bool (indicating whether the cell name is known) and the cell index for this name
|
||||
*/
|
||||
std::pair<bool, db::cell_index_type> cell_by_name (const std::string &name) const;
|
||||
|
||||
/**
|
||||
* @brief Make a cell from an ID (OASIS)
|
||||
*/
|
||||
db::cell_index_type make_cell (db::Layout &layout, size_t id);
|
||||
|
||||
/**
|
||||
* @brief Returns true, if there is a cell with the given ID alreay
|
||||
*/
|
||||
bool has_cell (size_t id) const;
|
||||
|
||||
/**
|
||||
* @brief Returns a pair with a bool (indicating whether the cell ID is known) and the cell index for this ID
|
||||
*/
|
||||
std::pair<bool, db::cell_index_type> cell_by_id (size_t id) const;
|
||||
|
||||
/**
|
||||
* @brief Registers a cell name for an ID
|
||||
*/
|
||||
void rename_cell (db::Layout &layout, size_t id, const std::string &cn);
|
||||
|
||||
/**
|
||||
* @brief Returns a cell reference by ID
|
||||
* If the cell does not exist, it's created. It is marked as ghost cell until
|
||||
* "make_cell" is called.
|
||||
*/
|
||||
db::cell_index_type cell_for_instance (db::Layout &layout, size_t id);
|
||||
|
||||
/**
|
||||
* @brief Returns a cell reference by name
|
||||
* Same as the previous method, but acting on cell names.
|
||||
*/
|
||||
db::cell_index_type cell_for_instance (db::Layout &layout, const std::string &cn);
|
||||
|
||||
/**
|
||||
* @brief Finishes the reading process
|
||||
*
|
||||
* This method will first check if all cells IDs got a name.
|
||||
* After this, the cells are renamed and cell conflict resolution will happen in the
|
||||
* specified way (cell_conflict_resolution attribute).
|
||||
*/
|
||||
void finish (db::Layout &layout);
|
||||
|
||||
protected:
|
||||
virtual void common_reader_error (const std::string &msg) = 0;
|
||||
virtual void common_reader_warn (const std::string &msg) = 0;
|
||||
|
||||
/**
|
||||
* @brief Merge (and delete) the src_cell into target_cell
|
||||
*/
|
||||
void merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const;
|
||||
|
||||
private:
|
||||
std::map<size_t, std::pair<std::string, db::cell_index_type> > m_id_map;
|
||||
std::map<std::string, std::pair<size_t, db::cell_index_type> > m_name_map;
|
||||
CellConflictResolution m_cc_resolution;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure that holds the GDS2 and OASIS specific options for the reader
|
||||
*/
|
||||
|
|
@ -44,7 +155,8 @@ public:
|
|||
CommonReaderOptions ()
|
||||
: create_other_layers (true),
|
||||
enable_text_objects (true),
|
||||
enable_properties (true)
|
||||
enable_properties (true),
|
||||
cell_conflict_resolution (CommonReader::AddToCell)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -83,6 +195,22 @@ public:
|
|||
*/
|
||||
bool enable_properties;
|
||||
|
||||
/**
|
||||
* @brief Specifies the cell merge behavior
|
||||
*
|
||||
* This enum controls how cells are read if a cell with the requested name already
|
||||
* exists.
|
||||
*
|
||||
* AddToCell In this mode, instances or shapes are added to any existing cell
|
||||
* OverwriteCell Overwrite existing cell. If the existing cell has children, those are removed unless used otherwise
|
||||
* SkipNewCell Ignore the new cell and it's children
|
||||
* RenameCell Rename the new cell
|
||||
*
|
||||
* If the existing opr the new cell is a ghost cell, AddToCell is applied always. In other words,
|
||||
* ghost cells are always merged.
|
||||
*/
|
||||
CommonReader::CellConflictResolution cell_conflict_resolution;
|
||||
|
||||
/**
|
||||
* @brief Implementation of FormatSpecificReaderOptions
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1065,8 +1065,7 @@ public:
|
|||
* @brief Delete the subcells of the given cells which are not used otherwise
|
||||
*
|
||||
* All subcells referenced directy or indirectly but not used otherwise
|
||||
* are deleted as well. This basically prunes the cell tree by this cell.
|
||||
* All instances of this cell are deleted as well.
|
||||
* are deleted as well.
|
||||
* This method is more efficent than calling prune_subcells for single cells multiple times.
|
||||
*
|
||||
* @param from A begin iterator delivering the cell id's to delete
|
||||
|
|
@ -1085,8 +1084,7 @@ public:
|
|||
* @brief Delete the subcells of the given cells which are not used otherwise
|
||||
*
|
||||
* All subcells referenced directy or indirectly but not used otherwise
|
||||
* are deleted as well. This basically prunes the cell tree by this cell.
|
||||
* All instances of this cell are deleted as well.
|
||||
* are deleted as well.
|
||||
* This method is more efficent than calling prune_subcells for single cells multiple times.
|
||||
*
|
||||
* @param cells A set of cell id's to prune
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "dbCommonReader.h"
|
||||
#include "dbLoadLayoutOptions.h"
|
||||
#include "gsiDecl.h"
|
||||
#include "gsiEnums.h"
|
||||
|
||||
namespace dn
|
||||
{
|
||||
|
|
@ -160,6 +161,36 @@ gsi::ClassExt<db::LoadLayoutOptions> common_reader_options (
|
|||
""
|
||||
);
|
||||
|
||||
|
||||
gsi::EnumIn<db::LoadLayoutOptions, db::CommonReader::CellConflictResolution> decl_dbCommonReader_CellConflictResolution ("db", "CellConflictResolution",
|
||||
gsi::enum_const ("AddToCell", db::CommonReader::AddToCell,
|
||||
"@brief Add content to existing cell\n"
|
||||
"This is the mode use in before version 0.27. Content of new cells is simply added to existing cells with the same name."
|
||||
) +
|
||||
gsi::enum_const ("OverwriteCell", db::CommonReader::OverwriteCell,
|
||||
"@brief The old cell is overwritten entirely (including child cells which are not used otherwise)\n"
|
||||
) +
|
||||
gsi::enum_const ("SkipNewCell", db::CommonReader::SkipNewCell,
|
||||
"@brief The new cell is skipped entirely (including child cells which are not used otherwise)\n"
|
||||
) +
|
||||
gsi::enum_const ("RenameCell", db::CommonReader::RenameCell,
|
||||
"@brief The new cell will be renamed to become unique\n"
|
||||
),
|
||||
"@brief This enum specifies how cell conflicts are handled if a layout read into another layout and a cell name conflict arises. "
|
||||
"Until version 0.26.8 and before, the mode was always 'AddToCell'. On reading, a cell was 'reopened' when encountering a cell name "
|
||||
"which already existed. This mode is still the default. The other modes are made available to support other ways of merging layouts.\n"
|
||||
"\n"
|
||||
"Proxy cells are never modified in the existing layout. Proxy cells are always local to their layout file. So if the existing cell is "
|
||||
"a proxy cell, the new cell will be renamed.\n"
|
||||
"\n"
|
||||
"If the new or existing cell is a ghost cell, both cells are merged always.\n"
|
||||
"\n"
|
||||
"This enum was introduced in version 0.27.\n"
|
||||
);
|
||||
|
||||
// Inject the NetlistCrossReference::Status declarations into NetlistCrossReference:
|
||||
gsi::ClassExt<db::LoadLayoutOptions> inject_CellConflictResolution_in_parent (decl_dbCommonReader_CellConflictResolution.defs ());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ GDS2ReaderText::read (db::Layout &layout, const db::LoadLayoutOptions &options)
|
|||
db::GDS2ReaderOptions gds2_options = options.get_options<db::GDS2ReaderOptions> ();
|
||||
db::CommonReaderOptions common_options = options.get_options<db::CommonReaderOptions> ();
|
||||
|
||||
return basic_read (layout, common_options.layer_map, common_options.create_other_layers, common_options.enable_text_objects, common_options.enable_properties, false, gds2_options.box_mode);
|
||||
return basic_read (layout, common_options.layer_map, common_options.create_other_layers, common_options.enable_text_objects, common_options.enable_properties, false, gds2_options.box_mode, common_options.cell_conflict_resolution);
|
||||
}
|
||||
|
||||
const LayerMap &
|
||||
|
|
@ -259,7 +259,7 @@ GDS2ReaderText::get_double ()
|
|||
}
|
||||
|
||||
void
|
||||
GDS2ReaderText::get_string (tl::string &s) const
|
||||
GDS2ReaderText::get_string (std::string &s) const
|
||||
{
|
||||
// TODO: get rid of this const_cast hack
|
||||
s = (const_cast<GDS2ReaderText *> (this))->reader.skip ();
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ private:
|
|||
|
||||
virtual std::string path () const;
|
||||
const char *get_string ();
|
||||
void get_string (tl::string &s) const;
|
||||
void get_string (std::string &s) const;
|
||||
int get_int ();
|
||||
short get_short ();
|
||||
unsigned short get_ushort ();
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ GDS2Reader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
|
|||
--m_recnum;
|
||||
m_reclen = 0;
|
||||
|
||||
return basic_read (layout, m_common_options.layer_map, m_common_options.create_other_layers, m_common_options.enable_text_objects, m_common_options.enable_properties, m_options.allow_multi_xy_records, m_options.box_mode);
|
||||
return basic_read (layout, m_common_options.layer_map, m_common_options.create_other_layers, m_common_options.enable_text_objects, m_common_options.enable_properties, m_options.allow_multi_xy_records, m_options.box_mode, m_common_options.cell_conflict_resolution);
|
||||
}
|
||||
|
||||
const LayerMap &
|
||||
|
|
@ -210,7 +210,7 @@ GDS2Reader::get_string ()
|
|||
}
|
||||
|
||||
void
|
||||
GDS2Reader::get_string (tl::string &s) const
|
||||
GDS2Reader::get_string (std::string &s) const
|
||||
{
|
||||
s.assign ((const char *) mp_rec_buf, 0, m_reclen);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ private:
|
|||
|
||||
virtual std::string path () const;
|
||||
virtual const char *get_string ();
|
||||
virtual void get_string (tl::string &s) const;
|
||||
virtual void get_string (std::string &s) const;
|
||||
virtual int get_int ();
|
||||
virtual short get_short ();
|
||||
virtual unsigned short get_ushort ();
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ GDS2ReaderBase::~GDS2ReaderBase ()
|
|||
}
|
||||
|
||||
const LayerMap &
|
||||
GDS2ReaderBase::basic_read (db::Layout &layout, const LayerMap &layer_map, bool create_other_layers, bool enable_text_objects, bool enable_properties, bool allow_multi_xy_records, unsigned int box_mode)
|
||||
GDS2ReaderBase::basic_read (db::Layout &layout, const LayerMap &layer_map, bool create_other_layers, bool enable_text_objects, bool enable_properties, bool allow_multi_xy_records, unsigned int box_mode, db::CommonReader::CellConflictResolution cc_resolution)
|
||||
{
|
||||
m_layer_map = layer_map;
|
||||
m_layer_map.prepare (layout);
|
||||
|
|
@ -95,9 +95,17 @@ GDS2ReaderBase::basic_read (db::Layout &layout, const LayerMap &layer_map, bool
|
|||
m_box_mode = box_mode;
|
||||
m_create_layers = create_other_layers;
|
||||
|
||||
set_cell_conflict_resolution (cc_resolution);
|
||||
|
||||
layout.start_changes ();
|
||||
do_read (layout);
|
||||
layout.end_changes ();
|
||||
try {
|
||||
do_read (layout);
|
||||
finish (layout);
|
||||
layout.end_changes ();
|
||||
} catch (...) {
|
||||
layout.end_changes ();
|
||||
throw;
|
||||
}
|
||||
|
||||
return m_layer_map;
|
||||
}
|
||||
|
|
@ -235,7 +243,6 @@ GDS2ReaderBase::do_read (db::Layout &layout)
|
|||
{
|
||||
m_cellname = "";
|
||||
m_libname = "";
|
||||
m_mapped_cellnames.clear ();
|
||||
|
||||
// read header
|
||||
if (get_record () != sHEADER) {
|
||||
|
|
@ -349,7 +356,7 @@ GDS2ReaderBase::do_read (db::Layout &layout)
|
|||
|
||||
} else {
|
||||
|
||||
db::cell_index_type cell_index = make_cell (layout, m_cellname.c_str (), false);
|
||||
db::cell_index_type cell_index = make_cell (layout, m_cellname);
|
||||
|
||||
db::Cell *cell = &layout.cell (cell_index);
|
||||
|
||||
|
|
@ -359,8 +366,6 @@ GDS2ReaderBase::do_read (db::Layout &layout)
|
|||
if (layout.recover_proxy_as (cell_index, ctx->second.begin (), ctx->second.end (), &layer_mapping)) {
|
||||
// ignore everything in that cell since it is created by the import:
|
||||
cell = 0;
|
||||
// marks the cell for begin addressed by REF's despite being a proxy:
|
||||
m_mapped_cellnames.insert (std::make_pair (m_cellname, m_cellname));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -973,54 +978,6 @@ GDS2ReaderBase::read_box (db::Layout &layout, db::Cell &cell)
|
|||
}
|
||||
}
|
||||
|
||||
db::cell_index_type
|
||||
GDS2ReaderBase::make_cell (db::Layout &layout, const char *cn, bool for_instance)
|
||||
{
|
||||
db::cell_index_type ci = 0;
|
||||
|
||||
// map to the real name which maybe a different one due to localization
|
||||
// of proxy cells (they are not to be reopened)
|
||||
bool is_mapped = false;
|
||||
if (! m_mapped_cellnames.empty ()) {
|
||||
std::map<tl::string, tl::string>::const_iterator n = m_mapped_cellnames.find (cn);
|
||||
if (n != m_mapped_cellnames.end ()) {
|
||||
cn = n->second.c_str ();
|
||||
is_mapped = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (cn);
|
||||
if (c.first && (is_mapped || ! layout.cell (c.second).is_proxy ())) {
|
||||
|
||||
// cell already there: just add instance (cell might have been created through forward reference)
|
||||
// NOTE: we don't address "reopened" proxies as proxies are always local to a layout
|
||||
|
||||
ci = c.second;
|
||||
|
||||
// mark the cell as read
|
||||
if (! for_instance) {
|
||||
layout.cell (ci).set_ghost_cell (false);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
ci = layout.add_cell (cn);
|
||||
|
||||
if (for_instance) {
|
||||
// mark this cell a "ghost cell" until it's actually read
|
||||
layout.cell (ci).set_ghost_cell (true);
|
||||
}
|
||||
|
||||
if (c.first) {
|
||||
// this cell has been given a new name: remember this name for localization
|
||||
m_mapped_cellnames.insert (std::make_pair (cn, layout.cell_name (ci)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ci;
|
||||
}
|
||||
|
||||
void
|
||||
GDS2ReaderBase::read_ref (db::Layout &layout, db::Cell & /*cell*/, bool array, tl::vector<db::CellInstArray> &instances, tl::vector<db::CellInstArrayWithProperties> &instances_with_props)
|
||||
{
|
||||
|
|
@ -1033,7 +990,7 @@ GDS2ReaderBase::read_ref (db::Layout &layout, db::Cell & /*cell*/, bool array, t
|
|||
error (tl::to_string (tr ("SNAME record expected")));
|
||||
}
|
||||
|
||||
db::cell_index_type ci = make_cell (layout, get_string (), true);
|
||||
db::cell_index_type ci = cell_for_instance (layout, get_string ());
|
||||
|
||||
bool mirror = false;
|
||||
int angle = 0;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "dbLayout.h"
|
||||
#include "dbReader.h"
|
||||
#include "dbStreamLayers.h"
|
||||
#include "dbCommonReader.h"
|
||||
|
||||
#include "tlException.h"
|
||||
#include "tlInternational.h"
|
||||
|
|
@ -49,7 +50,7 @@ struct GDS2XY
|
|||
* @brief The GDS2 format basic stream reader
|
||||
*/
|
||||
class DB_PLUGIN_PUBLIC GDS2ReaderBase
|
||||
: public ReaderBase
|
||||
: public CommonReader
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
|
@ -86,20 +87,21 @@ protected:
|
|||
* @param enable_properties A flag indicating whether to read user properties
|
||||
* @param allow_multi_xy_records If true, tries to check for multiple XY records for BOUNDARY elements
|
||||
* @param box_mode How to treat BOX records (0: ignore, 1: as rectangles, 2: as boundaries, 3: error)
|
||||
* @param cc_resolution The cell name conflict resolution mode
|
||||
* @return The LayerMap object that tells where which layer was loaded
|
||||
*/
|
||||
const LayerMap &basic_read (db::Layout &layout, const LayerMap &layer_map, bool create_other_layers, bool enable_text_objects, bool enable_properties, bool allow_multi_xy_records, unsigned int box_mode);
|
||||
const LayerMap &basic_read (db::Layout &layout, const LayerMap &layer_map, bool create_other_layers, bool enable_text_objects, bool enable_properties, bool allow_multi_xy_records, unsigned int box_mode, db::CommonReader::CellConflictResolution cc_resolution);
|
||||
|
||||
/**
|
||||
* @brief Accessor method to the current cellname
|
||||
*/
|
||||
const tl::string &cellname () const { return m_cellname; }
|
||||
const std::string &cellname () const { return m_cellname; }
|
||||
|
||||
private:
|
||||
friend class GDS2ReaderLayerMapping;
|
||||
|
||||
LayerMap m_layer_map;
|
||||
tl::string m_cellname;
|
||||
std::string m_cellname;
|
||||
std::string m_libname;
|
||||
double m_dbu, m_dbuu;
|
||||
bool m_create_layers;
|
||||
|
|
@ -109,7 +111,6 @@ private:
|
|||
unsigned int m_box_mode;
|
||||
std::map <tl::string, std::vector<std::string> > m_context_info;
|
||||
std::vector <db::Point> m_all_points;
|
||||
std::map <tl::string, tl::string> m_mapped_cellnames;
|
||||
|
||||
void read_context_info_cell ();
|
||||
void read_boundary (db::Layout &layout, db::Cell &cell, bool from_box_record);
|
||||
|
|
@ -117,7 +118,6 @@ private:
|
|||
void read_text (db::Layout &layout, db::Cell &cell);
|
||||
void read_box (db::Layout &layout, db::Cell &cell);
|
||||
void read_ref (db::Layout &layout, db::Cell &cell, bool array, tl::vector<db::CellInstArray> &instances, tl::vector<db::CellInstArrayWithProperties> &insts_wp);
|
||||
db::cell_index_type make_cell (db::Layout &layout, const char *cn, bool for_instance);
|
||||
|
||||
void do_read (db::Layout &layout);
|
||||
|
||||
|
|
@ -125,12 +125,15 @@ private:
|
|||
std::pair <bool, db::properties_id_type> finish_element (db::PropertiesRepository &rep);
|
||||
void finish_element ();
|
||||
|
||||
virtual void common_reader_error (const std::string &msg) { error (msg); }
|
||||
virtual void common_reader_warn (const std::string &msg) { warn (msg); }
|
||||
|
||||
virtual void error (const std::string &txt) = 0;
|
||||
virtual void warn (const std::string &txt) = 0;
|
||||
|
||||
virtual std::string path () const = 0;
|
||||
virtual const char *get_string () = 0;
|
||||
virtual void get_string (tl::string &s) const = 0;
|
||||
virtual void get_string (std::string &s) const = 0;
|
||||
virtual int get_int () = 0;
|
||||
virtual short get_short () = 0;
|
||||
virtual unsigned short get_ushort () = 0;
|
||||
|
|
|
|||
|
|
@ -144,9 +144,12 @@ OASISReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
|
|||
m_read_all_properties = oasis_options.read_all_properties;
|
||||
m_expect_strict_mode = oasis_options.expect_strict_mode;
|
||||
|
||||
set_cell_conflict_resolution (common_options.cell_conflict_resolution);
|
||||
|
||||
layout.start_changes ();
|
||||
try {
|
||||
do_read (layout);
|
||||
finish (layout);
|
||||
layout.end_changes ();
|
||||
} catch (...) {
|
||||
layout.end_changes ();
|
||||
|
|
@ -758,17 +761,11 @@ OASISReader::do_read (db::Layout &layout)
|
|||
id_mode propstring_id_mode = any;
|
||||
id_mode propname_id_mode = any;
|
||||
|
||||
m_cellnames.clear ();
|
||||
m_cellname_properties.clear ();
|
||||
m_textstrings.clear ();
|
||||
m_propstrings.clear ();
|
||||
m_propnames.clear ();
|
||||
m_layernames.clear ();
|
||||
m_cells_by_id.clear ();
|
||||
m_cells_by_name.clear ();
|
||||
m_defined_cells_by_id.clear ();
|
||||
m_defined_cells_by_name.clear ();
|
||||
m_mapped_cellnames.clear ();
|
||||
|
||||
m_instances.clear ();
|
||||
m_instances_with_props.clear ();
|
||||
|
|
@ -826,9 +823,7 @@ OASISReader::do_read (db::Layout &layout)
|
|||
get (id);
|
||||
}
|
||||
|
||||
if (! m_cellnames.insert (std::make_pair (id, name)).second) {
|
||||
error (tl::sprintf (tl::to_string (tr ("A CELLNAME with id %ld is present already")), id));
|
||||
}
|
||||
rename_cell (layout, id, name);
|
||||
|
||||
reset_modal_variables ();
|
||||
|
||||
|
|
@ -1150,37 +1145,11 @@ OASISReader::do_read (db::Layout &layout)
|
|||
|
||||
unsigned long id = 0;
|
||||
get (id);
|
||||
if (! m_defined_cells_by_id.insert (id).second) {
|
||||
if (has_cell (id)) {
|
||||
error (tl::sprintf (tl::to_string (tr ("A cell with id %ld is defined already")), id));
|
||||
}
|
||||
|
||||
std::map <unsigned long, db::cell_index_type>::const_iterator c = m_cells_by_id.find (id);
|
||||
if (c != m_cells_by_id.end ()) {
|
||||
|
||||
cell_index = c->second;
|
||||
layout.cell (cell_index).set_ghost_cell (false);
|
||||
|
||||
} else {
|
||||
|
||||
std::map <unsigned long, std::string>::const_iterator name = m_cellnames.find (id);
|
||||
if (name == m_cellnames.end ()) {
|
||||
|
||||
cell_index = layout.add_cell ();
|
||||
// force a cell rename to empty to avoid name clashes of the generated
|
||||
// $x names with the same inside the OASIS file.
|
||||
layout.rename_cell (cell_index, "");
|
||||
m_forward_references.insert (std::make_pair (id, cell_index));
|
||||
|
||||
} else {
|
||||
|
||||
cell_index = make_cell (layout, name->second.c_str (), false);
|
||||
m_cells_by_name.insert (std::make_pair (name->second, cell_index));
|
||||
|
||||
}
|
||||
|
||||
m_cells_by_id.insert (std::make_pair (id, cell_index));
|
||||
|
||||
}
|
||||
cell_index = make_cell (layout, id);
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -1189,22 +1158,11 @@ OASISReader::do_read (db::Layout &layout)
|
|||
}
|
||||
|
||||
std::string name = get_str ();
|
||||
if (! m_defined_cells_by_name.insert (name).second) {
|
||||
if (has_cell (name)) {
|
||||
error (tl::sprintf (tl::to_string (tr ("A cell with name %s is defined already")), name.c_str ()));
|
||||
}
|
||||
|
||||
std::map <std::string, db::cell_index_type>::const_iterator c = m_cells_by_name.find (name);
|
||||
if (c != m_cells_by_name.end ()) {
|
||||
|
||||
cell_index = c->second;
|
||||
layout.cell (cell_index).set_ghost_cell (false);
|
||||
|
||||
} else {
|
||||
|
||||
cell_index = make_cell (layout, name.c_str (), false);
|
||||
m_cells_by_name.insert (std::make_pair (name, cell_index));
|
||||
|
||||
}
|
||||
cell_index = make_cell (layout, name);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1326,72 +1284,16 @@ OASISReader::do_read (db::Layout &layout)
|
|||
|
||||
}
|
||||
|
||||
for (std::map <unsigned long, db::cell_index_type>::const_iterator fw = m_forward_references.begin (); fw != m_forward_references.end (); ++fw) {
|
||||
|
||||
std::map <unsigned long, std::string>::const_iterator cn = m_cellnames.find (fw->first);
|
||||
if (cn == m_cellnames.end ()) {
|
||||
|
||||
error (tl::sprintf (tl::to_string (tr ("No cellname defined for cell name id %ld")), fw->first));
|
||||
|
||||
} else {
|
||||
|
||||
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (cn->second.c_str ());
|
||||
if (c.first) {
|
||||
|
||||
// needed, since we have disabled updates
|
||||
layout.force_update ();
|
||||
|
||||
// add-on reading of forward-referenced cell: need to copy the new cell to the original one plus
|
||||
// change instances of the new cell and delete the new cell then.
|
||||
|
||||
const db::Cell &new_cell = layout.cell (fw->second);
|
||||
db::Cell &org_cell = layout.cell (c.second);
|
||||
|
||||
// copy over the instances
|
||||
for (db::Cell::const_iterator i = new_cell.begin (); ! i.at_end (); ++i) {
|
||||
org_cell.insert (*i);
|
||||
}
|
||||
|
||||
// copy over the shapes
|
||||
for (unsigned int l = 0; l < layout.layers (); ++l) {
|
||||
if (layout.is_valid_layer (l) && ! new_cell.shapes (l).empty ()) {
|
||||
org_cell.shapes (l).insert (new_cell.shapes (l));
|
||||
}
|
||||
}
|
||||
|
||||
// replace all instances of the new cell with the original one
|
||||
std::vector<std::pair<db::cell_index_type, db::Instance> > parents;
|
||||
for (db::Cell::parent_inst_iterator pi = new_cell.begin_parent_insts (); ! pi.at_end (); ++pi) {
|
||||
parents.push_back (std::make_pair (pi->parent_cell_index (), pi->child_inst ()));
|
||||
}
|
||||
|
||||
for (std::vector<std::pair<db::cell_index_type, db::Instance> >::const_iterator p = parents.begin (); p != parents.end (); ++p) {
|
||||
db::CellInstArray ia = p->second.cell_inst ();
|
||||
ia.object ().cell_index (org_cell.cell_index ());
|
||||
layout.cell (p->first).replace (p->second, ia);
|
||||
}
|
||||
|
||||
// finally delete the new cell
|
||||
layout.delete_cell (new_cell.cell_index ());
|
||||
|
||||
} else {
|
||||
layout.rename_cell (fw->second, cn->second.c_str ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// attach the properties found in CELLNAME to the cells (which may have other properties)
|
||||
for (std::map<unsigned long, db::properties_id_type>::const_iterator p = m_cellname_properties.begin (); p != m_cellname_properties.end (); ++p) {
|
||||
|
||||
std::map <unsigned long, db::cell_index_type>::const_iterator c = m_cells_by_id.find (p->first);
|
||||
if (c != m_cells_by_id.end ()) {
|
||||
std::pair<bool, db::cell_index_type> c = cell_by_id (p->first);
|
||||
if (c.first) {
|
||||
|
||||
db::PropertiesRepository::properties_set cnp = layout.properties_repository ().properties (p->second);
|
||||
|
||||
// Merge existing properties with the ones from CELLNAME
|
||||
db::Cell &cell = layout.cell (c->second);
|
||||
db::Cell &cell = layout.cell (c.second);
|
||||
if (cell.prop_id () != 0) {
|
||||
db::PropertiesRepository::properties_set cp = layout.properties_repository ().properties (cell.prop_id ());
|
||||
cnp.insert (cp.begin (), cp.end ());
|
||||
|
|
@ -1844,54 +1746,6 @@ OASISReader::read_repetition ()
|
|||
return mm_repetition.get ().size () > 1;
|
||||
}
|
||||
|
||||
db::cell_index_type
|
||||
OASISReader::make_cell (db::Layout &layout, const char *cn, bool for_instance)
|
||||
{
|
||||
db::cell_index_type ci = 0;
|
||||
|
||||
// map to the real name which maybe a different one due to localization
|
||||
// of proxy cells (they are not to be reopened)
|
||||
bool is_mapped = false;
|
||||
if (! m_mapped_cellnames.empty ()) {
|
||||
std::map<tl::string, tl::string>::const_iterator n = m_mapped_cellnames.find (cn);
|
||||
if (n != m_mapped_cellnames.end ()) {
|
||||
cn = n->second.c_str ();
|
||||
is_mapped = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (cn);
|
||||
if (c.first && (is_mapped || ! layout.cell (c.second).is_proxy ())) {
|
||||
|
||||
// cell already there: just add instance (cell might have been created through forward reference)
|
||||
// NOTE: we don't address "reopened" proxies as proxies are always local to a layout
|
||||
|
||||
ci = c.second;
|
||||
|
||||
// mark the cell as read
|
||||
if (! for_instance) {
|
||||
layout.cell (ci).set_ghost_cell (false);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
ci = layout.add_cell (cn);
|
||||
|
||||
if (for_instance) {
|
||||
// mark this cell a "ghost cell" until it's actually read
|
||||
layout.cell (ci).set_ghost_cell (true);
|
||||
}
|
||||
|
||||
if (c.first) {
|
||||
// this cell has been given a new name: remember this name for localization
|
||||
m_mapped_cellnames.insert (std::make_pair (cn, layout.cell_name (ci)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ci;
|
||||
}
|
||||
|
||||
void
|
||||
OASISReader::do_read_placement (unsigned char r,
|
||||
bool xy_absolute,
|
||||
|
|
@ -1909,31 +1763,8 @@ OASISReader::do_read_placement (unsigned char r,
|
|||
// cell by id
|
||||
unsigned long id;
|
||||
get (id);
|
||||
std::map <unsigned long, db::cell_index_type>::const_iterator cid = m_cells_by_id.find (id);
|
||||
if (cid == m_cells_by_id.end ()) {
|
||||
|
||||
// create the cell
|
||||
std::map <unsigned long, std::string>::const_iterator name = m_cellnames.find (id);
|
||||
if (name == m_cellnames.end ()) {
|
||||
|
||||
mm_placement_cell = layout.add_cell ();
|
||||
m_forward_references.insert (std::make_pair (id, mm_placement_cell.get ()));
|
||||
|
||||
// temporarily mark as "ghost cell"
|
||||
layout.cell (mm_placement_cell.get ()).set_ghost_cell (true);
|
||||
|
||||
} else {
|
||||
|
||||
mm_placement_cell = make_cell (layout, name->second.c_str (), true);
|
||||
m_cells_by_name.insert (std::make_pair (name->second, mm_placement_cell.get ()));
|
||||
|
||||
}
|
||||
|
||||
m_cells_by_id.insert (std::make_pair (id, mm_placement_cell.get ()));
|
||||
|
||||
} else {
|
||||
mm_placement_cell = cid->second;
|
||||
}
|
||||
mm_placement_cell = cell_for_instance (layout, id);
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -1941,15 +1772,7 @@ OASISReader::do_read_placement (unsigned char r,
|
|||
std::string name;
|
||||
get_str (name);
|
||||
|
||||
std::map <std::string, db::cell_index_type>::const_iterator cid = m_cells_by_name.find (name);
|
||||
if (cid == m_cells_by_name.end ()) {
|
||||
|
||||
mm_placement_cell = make_cell (layout, name.c_str (), true);
|
||||
m_cells_by_name.insert (std::make_pair (name, mm_placement_cell.get ()));
|
||||
|
||||
} else {
|
||||
mm_placement_cell = cid->second;
|
||||
}
|
||||
mm_placement_cell = cell_for_instance (layout, name);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "dbOASISFormat.h"
|
||||
#include "dbStreamLayers.h"
|
||||
#include "dbPropertiesRepository.h"
|
||||
#include "dbCommonReader.h"
|
||||
|
||||
#include "tlException.h"
|
||||
#include "tlInternational.h"
|
||||
|
|
@ -62,7 +63,7 @@ public:
|
|||
* @brief The OASIS format stream reader
|
||||
*/
|
||||
class DB_PLUGIN_PUBLIC OASISReader
|
||||
: public ReaderBase,
|
||||
: public CommonReader,
|
||||
public OASISDiagnostics
|
||||
{
|
||||
public:
|
||||
|
|
@ -118,6 +119,7 @@ public:
|
|||
*/
|
||||
virtual const char *format () const { return "OASIS"; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Issue an error with positional information
|
||||
*
|
||||
|
|
@ -132,6 +134,9 @@ public:
|
|||
*/
|
||||
virtual void warn (const std::string &txt);
|
||||
|
||||
virtual void common_reader_error (const std::string &msg) { error (msg); }
|
||||
virtual void common_reader_warn (const std::string &msg) { warn (msg); }
|
||||
|
||||
private:
|
||||
friend class OASISReaderLayerMapping;
|
||||
|
||||
|
|
@ -194,7 +199,6 @@ private:
|
|||
modal_variable<bool> mm_last_property_is_sprop;
|
||||
modal_variable<property_value_list> mm_last_value_list;
|
||||
|
||||
std::map <unsigned long, std::string> m_cellnames;
|
||||
std::map <unsigned long, db::properties_id_type> m_cellname_properties;
|
||||
std::map <unsigned long, std::string> m_textstrings;
|
||||
std::map <unsigned long, const db::StringRef *> m_text_forward_references;
|
||||
|
|
@ -205,18 +209,11 @@ private:
|
|||
tl::vector<db::CellInstArray> m_instances;
|
||||
tl::vector<db::CellInstArrayWithProperties> m_instances_with_props;
|
||||
|
||||
std::map <unsigned long, db::cell_index_type> m_cells_by_id;
|
||||
std::map <unsigned long, db::cell_index_type> m_forward_references;
|
||||
std::map <std::string, db::cell_index_type> m_cells_by_name;
|
||||
bool m_create_layers;
|
||||
bool m_read_texts;
|
||||
bool m_read_properties;
|
||||
bool m_read_all_properties;
|
||||
|
||||
std::set <unsigned long> m_defined_cells_by_id;
|
||||
std::set <std::string> m_defined_cells_by_name;
|
||||
std::map <tl::string, tl::string> m_mapped_cellnames;
|
||||
|
||||
std::map <unsigned long, db::property_names_id_type> m_propname_forward_references;
|
||||
std::map <unsigned long, std::string> m_propvalue_forward_references;
|
||||
db::property_names_id_type m_s_gds_property_name_id;
|
||||
|
|
@ -238,7 +235,6 @@ private:
|
|||
void do_read_trapezoid (unsigned char r, bool xy_absolute,db::cell_index_type cell_index, db::Layout &layout);
|
||||
void do_read_ctrapezoid (bool xy_absolute,db::cell_index_type cell_index, db::Layout &layout);
|
||||
void do_read_circle (bool xy_absolute,db::cell_index_type cell_index, db::Layout &layout);
|
||||
db::cell_index_type make_cell (db::Layout &layout, const char *cn, bool for_instance);
|
||||
|
||||
void reset_modal_variables ();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue