WIP: some refactoring to simplify multi-mapping implementation

This commit is contained in:
Matthias Koefferlein 2020-12-19 13:21:33 +01:00
parent dda2724d0c
commit f86c13689b
12 changed files with 308 additions and 468 deletions

View File

@ -35,7 +35,7 @@ namespace db
static const size_t null_id = std::numeric_limits<size_t>::max ();
CommonReader::CommonReader ()
: m_cc_resolution (AddToCell)
: m_cc_resolution (AddToCell), m_create_layers (false)
{
// .. nothing yet ..
}
@ -275,6 +275,44 @@ CommonReader::merge_cell_without_instances (db::Layout &layout, db::cell_index_t
layout.delete_cell (src_cell.cell_index ());
}
const db::LayerMap &
CommonReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
{
init (options);
m_layer_map.prepare (layout);
layout.start_changes ();
try {
do_read (layout);
finish (layout);
layout.end_changes ();
} catch (...) {
layout.end_changes ();
throw;
}
return m_layer_map;
}
const db::LayerMap &
CommonReader::read (db::Layout &layout)
{
return read (layout, db::LoadLayoutOptions ());
}
void
CommonReader::init (const LoadLayoutOptions &options)
{
m_common_options = options.get_options<db::CommonReaderOptions> ();
m_layer_map = m_common_options.layer_map;
m_cc_resolution = m_common_options.cell_conflict_resolution;
m_create_layers = m_common_options.create_other_layers;
m_layers_created.clear ();
m_layer_names.clear ();
}
void
CommonReader::finish (db::Layout &layout)
{
@ -384,6 +422,46 @@ CommonReader::finish (db::Layout &layout)
}
}
std::pair <bool, unsigned int>
CommonReader::open_dl (db::Layout &layout, const LDPair &dl)
{
std::pair<bool, unsigned int> ll = m_layer_map.first_logical (dl, layout);
if (ll.first) {
return ll;
} else if (! m_create_layers) {
return ll;
} else {
// and create the layer
db::LayerProperties lp;
lp.layer = dl.layer;
lp.datatype = dl.datatype;
// resolve OASIS name if possible
const tl::interval_map <db::ld_type, std::string> *names_dmap = m_layer_names.mapped (dl.layer);
if (names_dmap != 0) {
const std::string *name = names_dmap->mapped (dl.datatype);
if (name != 0) {
lp.name = *name;
}
}
unsigned int ll = layout.insert_layer (lp);
m_layer_map.map (dl, ll, lp);
m_layers_created.insert (ll);
return std::make_pair (true, ll);
}
}
// ---------------------------------------------------------------
// Common format declaration

View File

@ -31,6 +31,104 @@
namespace db
{
/**
* @brief The CellConflictResolution enum
*/
enum CellConflictResolution
{
AddToCell = 0,
OverwriteCell = 1,
SkipNewCell = 2,
RenameCell = 3
};
/**
* @brief Structure that holds the GDS2 and OASIS specific options for the reader
*/
class DB_PUBLIC CommonReaderOptions
: public FormatSpecificReaderOptions
{
public:
/**
* @brief The constructor
*/
CommonReaderOptions ()
: create_other_layers (true),
enable_text_objects (true),
enable_properties (true),
cell_conflict_resolution (CellConflictResolution::AddToCell)
{
// .. nothing yet ..
}
/**
* @brief Specifies a layer mapping
*
* If a layer mapping is specified, only the given layers are read.
* Otherwise, all layers are read.
* Setting "create_other_layers" to true will make the reader
* create other layers for all layers not given in the layer map.
* Setting an empty layer map and create_other_layers to true effectively
* enables all layers for reading.
*/
db::LayerMap layer_map;
/**
* @brief A flag indicating that a new layers shall be created
*
* If this flag is set to true, layers not listed in the layer map a created
* too.
*/
bool create_other_layers;
/**
* @brief A flag indicating whether to read text objects
*
* If this flag is set to true, text objects are read. Otherwise they are ignored.
*/
bool enable_text_objects;
/**
* @brief A flag indicating whether to read user properties
*
* If this flag is set to true, user properties are read. Otherwise they are ignored.
*/
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.
*/
CellConflictResolution cell_conflict_resolution;
/**
* @brief Implementation of FormatSpecificReaderOptions
*/
virtual FormatSpecificReaderOptions *clone () const
{
return new CommonReaderOptions (*this);
}
/**
* @brief Implementation of FormatSpecificReaderOptions
*/
virtual const std::string &format_name () const
{
static const std::string n ("Common");
return n;
}
};
/**
* @brief A common reader base for GDS2 and OASIS providing common services for both readers
*/
@ -38,38 +136,13 @@ class DB_PUBLIC CommonReader
: public ReaderBase
{
public:
/**
* @brief The CellConflictResolution enum
*/
enum CellConflictResolution
{
AddToCell = 0,
OverwriteCell = 1,
SkipNewCell = 2,
RenameCell = 3
};
typedef tl::interval_map <db::ld_type, tl::interval_map <db::ld_type, std::string> > layer_name_map;
/**
* @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
*/
@ -132,9 +205,17 @@ public:
*/
void finish (db::Layout &layout);
// Reimplementation of the ReaderBase interace
virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options);
virtual const db::LayerMap &read (db::Layout &layout);
protected:
friend class CommonReaderLayerMapping;
virtual void common_reader_error (const std::string &msg) = 0;
virtual void common_reader_warn (const std::string &msg) = 0;
virtual void do_read (db::Layout &layout) = 0;
virtual void init (const LoadLayoutOptions &options);
/**
* @brief Merge (and delete) the src_cell into target_cell
@ -146,98 +227,81 @@ protected:
*/
void merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const;
/**
* @brief Gets the common options
*/
db::CommonReaderOptions &common_options ()
{
return m_common_options;
}
/**
* @brief Gets the layer map
*/
db::LayerMap &layer_map ()
{
return m_layer_map;
}
/**
* @brief Gets the layer name map
*/
layer_name_map &layer_names ()
{
return m_layer_names;
}
/**
* @brief Gets the list of layers which have been created
*/
std::set<unsigned int> &layers_created ()
{
return m_layers_created;
}
/**
* @brief Enters the a layer with a given layer/datatype
*/
std::pair <bool, unsigned int> open_dl (db::Layout &layout, const LDPair &dl);
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;
std::map<size_t, std::string> m_name_for_id;
CellConflictResolution m_cc_resolution;
bool m_create_layers;
db::CommonReaderOptions m_common_options;
db::LayerMap m_layer_map;
tl::interval_map <db::ld_type, tl::interval_map <db::ld_type, std::string> > m_layer_names;
std::set<unsigned int> m_layers_created;
};
/**
* @brief Structure that holds the GDS2 and OASIS specific options for the reader
* @brief A utility class that maps the layers for the proxy cell recovery
*/
class DB_PUBLIC CommonReaderOptions
: public FormatSpecificReaderOptions
class CommonReaderLayerMapping
: public db::ImportLayerMapping
{
public:
/**
* @brief The constructor
*/
CommonReaderOptions ()
: create_other_layers (true),
enable_text_objects (true),
enable_properties (true),
cell_conflict_resolution (CommonReader::AddToCell)
CommonReaderLayerMapping (db::CommonReader *reader, db::Layout *layout)
: mp_reader (reader), mp_layout (layout)
{
// .. nothing yet ..
}
/**
* @brief Specifies a layer mapping
*
* If a layer mapping is specified, only the given layers are read.
* Otherwise, all layers are read.
* Setting "create_other_layers" to true will make the reader
* create other layers for all layers not given in the layer map.
* Setting an empty layer map and create_other_layers to true effectively
* enables all layers for reading.
*/
db::LayerMap layer_map;
/**
* @brief A flag indicating that a new layers shall be created
*
* If this flag is set to true, layers not listed in the layer map a created
* too.
*/
bool create_other_layers;
/**
* @brief A flag indicating whether to read text objects
*
* If this flag is set to true, text objects are read. Otherwise they are ignored.
*/
bool enable_text_objects;
/**
* @brief A flag indicating whether to read user properties
*
* If this flag is set to true, user properties are read. Otherwise they are ignored.
*/
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
*/
virtual FormatSpecificReaderOptions *clone () const
std::pair<bool, unsigned int> map_layer (const db::LayerProperties &lprops)
{
return new CommonReaderOptions (*this);
// named layers that are imported from a library are ignored
if (lprops.is_named ()) {
return std::make_pair (false, 0);
} else {
return mp_reader->open_dl (*mp_layout, LDPair (lprops.layer, lprops.datatype));
}
}
/**
* @brief Implementation of FormatSpecificReaderOptions
*/
virtual const std::string &format_name () const
{
static const std::string n ("Common");
return n;
}
private:
db::CommonReader *mp_reader;
db::Layout *mp_layout;
};
}

View File

@ -85,12 +85,12 @@ static void set_properties_enabled (db::LoadLayoutOptions *options, bool l)
options->get_options<db::CommonReaderOptions> ().enable_properties = l;
}
static db::CommonReader::CellConflictResolution get_cell_conflict_resolution (const db::LoadLayoutOptions *options)
static db::CellConflictResolution get_cell_conflict_resolution (const db::LoadLayoutOptions *options)
{
return options->get_options<db::CommonReaderOptions> ().cell_conflict_resolution;
}
static void set_cell_conflict_resolution (db::LoadLayoutOptions *options, db::CommonReader::CellConflictResolution cc)
static void set_cell_conflict_resolution (db::LoadLayoutOptions *options, db::CellConflictResolution cc)
{
options->get_options<db::CommonReaderOptions> ().cell_conflict_resolution = cc;
}
@ -188,18 +188,18 @@ 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,
gsi::EnumIn<db::LoadLayoutOptions, db::CellConflictResolution> decl_dbCommonReader_CellConflictResolution ("db", "CellConflictResolution",
gsi::enum_const ("AddToCell", db::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,
gsi::enum_const ("OverwriteCell", db::OverwriteCell,
"@brief The old cell is overwritten entirely (including child cells which are not used otherwise)\n"
) +
gsi::enum_const ("SkipNewCell", db::CommonReader::SkipNewCell,
gsi::enum_const ("SkipNewCell", db::SkipNewCell,
"@brief The new cell is skipped entirely (including child cells which are not used otherwise)\n"
) +
gsi::enum_const ("RenameCell", db::CommonReader::RenameCell,
gsi::enum_const ("RenameCell", db::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. "

View File

@ -51,23 +51,11 @@ GDS2ReaderText::~GDS2ReaderText()
// .. nothing yet ..
}
const LayerMap &
GDS2ReaderText::read (db::Layout &layout, const db::LoadLayoutOptions &options)
void
GDS2ReaderText::init (const db::LoadLayoutOptions &options)
{
GDS2ReaderBase::init (options);
storedRecId = 0;
// HINT: reuse the standard GDS2 reader options for the text reader.
// However, the allow_big_records and allow_multi_xy_records options are ignored.
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, common_options.cell_conflict_resolution);
}
const LayerMap &
GDS2ReaderText::read (db::Layout &layout)
{
return read (layout, db::LoadLayoutOptions ());
}
void

View File

@ -64,43 +64,14 @@ public:
*/
~GDS2ReaderText();
/**
* @brief The basic read method
*
* This method will read the stream data and translate this to
* insert calls into the layout object. This will not do much
* on the layout object beside inserting the objects.
* It can be given a couple of options specified with the
* LoadLayoutOptions object.
* The returned map will contain all layers, the passed
* ones and the newly created ones.
*
* @param layout The layout object to write to
* @param options The generic reader options
* @return The LayerMap object that tells where which layer was loaded
*/
virtual const LayerMap &read (db::Layout &layout, const LoadLayoutOptions &options);
/**
* @brief The basic read method (without mapping)
*
* This method will read the stream data and translate this to
* insert calls into the layout object. This will not do much
* on the layout object beside inserting the objects.
* This version will read all input layers and return a map
* which tells which GDS2 layer has been read into which logical
* layer.
*
* @param layout The layout object to write to
* @return The LayerMap object
*/
virtual const LayerMap &read (db::Layout &layout);
/**
* @brief Format
*/
const char *format () const { return "GDS2Text"; }
protected:
virtual void init (const LoadLayoutOptions &options);
private:
tl::TextInputStream sStream;
std::string sExtractedValue;

View File

@ -43,6 +43,7 @@ GDS2Reader::GDS2Reader (tl::InputStream &s)
m_recptr (0),
mp_rec_buf (0),
m_stored_rec (0),
m_allow_big_records (true),
m_progress (tl::to_string (tr ("Reading GDS2 file")), 10000)
{
m_progress.set_format (tl::to_string (tr ("%.0f MB")));
@ -54,23 +55,16 @@ GDS2Reader::~GDS2Reader ()
// .. nothing yet ..
}
const LayerMap &
GDS2Reader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
void
GDS2Reader::init (const db::LoadLayoutOptions &options)
{
m_options = options.get_options<db::GDS2ReaderOptions> ();
m_common_options = options.get_options<db::CommonReaderOptions> ();
GDS2ReaderBase::init (options);
m_allow_big_records = options.get_options<db::GDS2ReaderOptions> ().allow_big_records;
m_recnum = 0;
--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, m_common_options.cell_conflict_resolution);
}
const LayerMap &
GDS2Reader::read (db::Layout &layout)
{
return read (layout, db::LoadLayoutOptions ());
}
void
@ -108,7 +102,7 @@ GDS2Reader::get_record ()
error (tl::to_string (tr ("Invalid record length (less than 4)")));
}
if (m_reclen >= 0x8000) {
if (m_options.allow_big_records) {
if (m_allow_big_records) {
warn (tl::to_string (tr ("Record length larger than 0x8000 encountered: interpreting as unsigned")));
} else {
error (tl::to_string (tr ("Record length larger than 0x8000 encountered (reader is configured not to allow such records)")));

View File

@ -72,43 +72,14 @@ public:
*/
~GDS2Reader ();
/**
* @brief The basic read method
*
* This method will read the stream data and translate this to
* insert calls into the layout object. This will not do much
* on the layout object beside inserting the objects.
* It can be given a couple of options specified with the
* LoadLayoutOptions object.
* The returned map will contain all layers, the passed
* ones and the newly created ones.
*
* @param layout The layout object to write to
* @param options The generic reader options
* @return The LayerMap object that tells where which layer was loaded
*/
virtual const LayerMap &read (db::Layout &layout, const LoadLayoutOptions &options);
/**
* @brief The basic read method (without mapping)
*
* This method will read the stream data and translate this to
* insert calls into the layout object. This will not do much
* on the layout object beside inserting the objects.
* This version will read all input layers and return a map
* which tells which GDS2 layer has been read into which logical
* layer.
*
* @param layout The layout object to write to
* @return The LayerMap object
*/
virtual const LayerMap &read (db::Layout &layout);
/**
* @brief Format
*/
virtual const char *format () const { return "GDS2"; }
protected:
virtual void init (const LoadLayoutOptions &options);
private:
tl::InputStream &m_stream;
size_t m_recnum;
@ -117,8 +88,7 @@ private:
unsigned char *mp_rec_buf;
tl::string m_string_buf;
short m_stored_rec;
db::GDS2ReaderOptions m_options;
db::CommonReaderOptions m_common_options;
bool m_allow_big_records;
tl::AbsoluteProgress m_progress;
virtual void error (const std::string &txt);

View File

@ -22,6 +22,7 @@
#include "dbGDS2ReaderBase.h"
#include "dbGDS2Format.h"
#include "dbGDS2.h"
#include "dbArray.h"
@ -34,42 +35,12 @@ namespace db
// ---------------------------------------------------------------
/**
* @brief A utility class that maps the layers for the proxy cell recovery
*/
class GDS2ReaderLayerMapping
: public db::ImportLayerMapping
{
public:
GDS2ReaderLayerMapping (db::GDS2ReaderBase *reader, db::Layout *layout, bool create)
: mp_reader (reader), mp_layout (layout), m_create (create)
{
// .. nothing yet ..
}
std::pair<bool, unsigned int> map_layer (const db::LayerProperties &lprops)
{
// named layers that are imported from a library are ignored
if (lprops.is_named ()) {
return std::make_pair (false, 0);
} else {
return mp_reader->open_dl (*mp_layout, LDPair (lprops.layer, lprops.datatype), m_create);
}
}
private:
db::GDS2ReaderBase *mp_reader;
db::Layout *mp_layout;
bool m_create;
};
// ---------------------------------------------------------------
// GDS2ReaderBase
GDS2ReaderBase::GDS2ReaderBase ()
: m_dbu (0.001),
m_dbuu (1.0),
m_create_layers (true),
m_read_texts (true),
m_read_properties (true),
m_allow_multi_xy_records (false),
@ -83,31 +54,18 @@ GDS2ReaderBase::~GDS2ReaderBase ()
// .. nothing yet ..
}
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, db::CommonReader::CellConflictResolution cc_resolution)
void
GDS2ReaderBase::init (const db::LoadLayoutOptions &options)
{
m_layer_map = layer_map;
m_layer_map.prepare (layout);
m_read_texts = enable_text_objects;
m_read_properties = enable_properties;
CommonReader::init (options);
m_allow_multi_xy_records = allow_multi_xy_records;
m_box_mode = box_mode;
m_create_layers = create_other_layers;
db::GDS2ReaderOptions gds2_options = options.get_options<db::GDS2ReaderOptions> ();
set_cell_conflict_resolution (cc_resolution);
m_read_texts = common_options ().enable_text_objects;
m_read_properties = common_options ().enable_properties;
layout.start_changes ();
try {
do_read (layout);
finish (layout);
layout.end_changes ();
} catch (...) {
layout.end_changes ();
throw;
}
return m_layer_map;
m_allow_multi_xy_records = gds2_options.allow_multi_xy_records;
m_box_mode = gds2_options.box_mode;
}
void
@ -181,34 +139,6 @@ GDS2ReaderBase::finish_element (db::PropertiesRepository &rep)
}
std::pair <bool, unsigned int>
GDS2ReaderBase::open_dl (db::Layout &layout, const LDPair &dl, bool create)
{
std::pair<bool, unsigned int> ll = m_layer_map.first_logical (dl, layout);
if (ll.first) {
return ll;
} else if (! create) {
// layer not mapped and no layer create is requested
return ll;
} else {
// and create the layer
db::LayerProperties lp;
lp.layer = dl.layer;
lp.datatype = dl.datatype;
unsigned int ll = layout.insert_layer (lp);
m_layer_map.map (dl, ll, lp);
return std::make_pair (true, ll);
}
}
inline db::Point
pt_conv (const GDS2XY &p)
{
@ -362,7 +292,7 @@ GDS2ReaderBase::do_read (db::Layout &layout)
std::map <tl::string, std::vector <std::string> >::const_iterator ctx = m_context_info.find (m_cellname);
if (ctx != m_context_info.end ()) {
GDS2ReaderLayerMapping layer_mapping (this, &layout, m_create_layers);
CommonReaderLayerMapping layer_mapping (this, &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;
@ -553,7 +483,7 @@ GDS2ReaderBase::read_boundary (db::Layout &layout, db::Cell &cell, bool from_box
unsigned int xy_length = 0;
GDS2XY *xy_data = get_xy_data (xy_length);
std::pair<bool, unsigned int> ll = open_dl (layout, ld, m_create_layers);
std::pair<bool, unsigned int> ll = open_dl (layout, ld);
if (ll.first) {
// create a box object if possible
@ -734,7 +664,7 @@ GDS2ReaderBase::read_path (db::Layout &layout, db::Cell &cell)
unsigned int xy_length = 0;
GDS2XY *xy_data = get_xy_data (xy_length);
std::pair<bool, unsigned int> ll = open_dl (layout, ld, m_create_layers);
std::pair<bool, unsigned int> ll = open_dl (layout, ld);
if (ll.first) {
// this will copy the path:
@ -825,7 +755,7 @@ GDS2ReaderBase::read_text (db::Layout &layout, db::Cell &cell)
std::pair<bool, unsigned int> ll (false, 0);
if (m_read_texts) {
ll = open_dl (layout, ld, m_create_layers);
ll = open_dl (layout, ld);
}
rec_id = get_record ();
@ -947,7 +877,7 @@ GDS2ReaderBase::read_box (db::Layout &layout, db::Cell &cell)
}
ld.datatype = get_ushort ();
std::pair<bool, unsigned int> ll = open_dl (layout, ld, m_create_layers);
std::pair<bool, unsigned int> ll = open_dl (layout, ld);
if (get_record () != sXY) {
error (tl::to_string (tr ("XY record expected")));

View File

@ -69,42 +69,20 @@ public:
const std::string &libname () const { return m_libname; }
protected:
/**
* @brief The basic read method
*
* This method will read the stream data and translate this to
* insert calls into the layout object. This will not do much
* on the layout object beside inserting the objects.
* It can be given a couple of options specified with the
* LoadLayoutOptions object.
* The returned map will contain all layers, the passed
* ones and the newly created ones.
*
* @param layout The layout object to write to
* @param layer_map The layer mapping on input
* @param create_other_layer A flag indicating whether to read all other layers
* @param enable_text_objects A flag indicating whether to read text objects
* @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, db::CommonReader::CellConflictResolution cc_resolution);
/**
* @brief Accessor method to the current cellname
*/
const std::string &cellname () const { return m_cellname; }
virtual void do_read (db::Layout &layout);
virtual void init (const LoadLayoutOptions &options);
private:
friend class GDS2ReaderLayerMapping;
LayerMap m_layer_map;
std::string m_cellname;
std::string m_libname;
double m_dbu, m_dbuu;
bool m_create_layers;
bool m_read_texts;
bool m_read_properties;
bool m_allow_multi_xy_records;
@ -119,9 +97,6 @@ private:
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);
void do_read (db::Layout &layout);
std::pair <bool, unsigned int> open_dl (db::Layout &layout, const LDPair &dl, bool create);
std::pair <bool, db::properties_id_type> finish_element (db::PropertiesRepository &rep);
void finish_element ();

View File

@ -443,7 +443,7 @@ TEST(4_CollectModeRename)
db::Layout layout (&m);
db::LoadLayoutOptions options;
options.get_options<db::CommonReaderOptions> ().cell_conflict_resolution = db::CommonReader::RenameCell;
options.get_options<db::CommonReaderOptions> ().cell_conflict_resolution = db::RenameCell;
{
tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_basic.gds");
@ -467,7 +467,7 @@ TEST(4_CollectModeOverwrite)
db::Layout layout (&m);
db::LoadLayoutOptions options;
options.get_options<db::CommonReaderOptions> ().cell_conflict_resolution = db::CommonReader::OverwriteCell;
options.get_options<db::CommonReaderOptions> ().cell_conflict_resolution = db::OverwriteCell;
{
tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_basic.gds");
@ -491,7 +491,7 @@ TEST(4_CollectModeSkip)
db::Layout layout (&m);
db::LoadLayoutOptions options;
options.get_options<db::CommonReaderOptions> ().cell_conflict_resolution = db::CommonReader::SkipNewCell;
options.get_options<db::CommonReaderOptions> ().cell_conflict_resolution = db::SkipNewCell;
{
tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_basic.gds");
@ -515,7 +515,7 @@ TEST(4_CollectModeAdd)
db::Layout layout (&m);
db::LoadLayoutOptions options;
options.get_options<db::CommonReaderOptions> ().cell_conflict_resolution = db::CommonReader::AddToCell;
options.get_options<db::CommonReaderOptions> ().cell_conflict_resolution = db::AddToCell;
{
tl::InputStream file (tl::testsrc () + "/testdata/gds/collect_basic.gds");

View File

@ -38,35 +38,6 @@ namespace db
// ---------------------------------------------------------------
/**
* @brief A utility class that maps the layers for the proxy cell recovery
*/
class OASISReaderLayerMapping
: public db::ImportLayerMapping
{
public:
OASISReaderLayerMapping (db::OASISReader *reader, db::Layout *layout, bool create)
: mp_reader (reader), mp_layout (layout), m_create (create)
{
// .. nothing yet ..
}
std::pair<bool, unsigned int> map_layer (const db::LayerProperties &lprops)
{
// named layers that are imported from a library are ignored
if (lprops.is_named ()) {
return std::make_pair (false, 0);
} else {
return mp_reader->open_dl (*mp_layout, LDPair (lprops.layer, lprops.datatype), m_create);
}
}
private:
db::OASISReader *mp_reader;
db::Layout *mp_layout;
bool m_create;
};
// ---------------------------------------------------------------
// OASISReader
@ -101,7 +72,6 @@ OASISReader::OASISReader (tl::InputStream &s)
mm_last_property_name (this, "last-property-name"),
mm_last_property_is_sprop (this, "last-property-is-stdprop"),
mm_last_value_list(this, "last-value-list"),
m_create_layers (false),
m_read_texts (true),
m_read_properties (true),
m_read_all_properties (false),
@ -129,40 +99,17 @@ OASISReader::~OASISReader ()
// .. nothing yet ..
}
const LayerMap &
OASISReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
void
OASISReader::init (const db::LoadLayoutOptions &options)
{
db::OASISReaderOptions oasis_options = options.get_options<db::OASISReaderOptions> ();
db::CommonReaderOptions common_options = options.get_options<db::CommonReaderOptions> ();
CommonReader::init (options);
m_layer_map = common_options.layer_map;
m_layer_map.prepare (layout);
m_layers_created.clear ();
m_read_texts = common_options.enable_text_objects;
m_read_properties = common_options.enable_properties;
m_create_layers = common_options.create_other_layers;
m_read_texts = common_options ().enable_text_objects;
m_read_properties = common_options ().enable_properties;
db::OASISReaderOptions oasis_options = options.get_options<db::OASISReaderOptions> ();
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 ();
throw;
}
return m_layer_map;
}
const LayerMap &
OASISReader::read (db::Layout &layout)
{
return read (layout, db::LoadLayoutOptions ());
}
inline long long
@ -554,44 +501,6 @@ OASISReader::warn (const std::string &msg)
}
}
std::pair <bool, unsigned int>
OASISReader::open_dl (db::Layout &layout, const LDPair &dl, bool create)
{
std::pair<bool, unsigned int> ll = m_layer_map.first_logical (dl, layout);
if (ll.first) {
return ll;
} else if (! create) {
return ll;
} else {
// and create the layer
db::LayerProperties lp;
lp.layer = dl.layer;
lp.datatype = dl.datatype;
// resolve OASIS name if possible
const tl::interval_map <db::ld_type, std::string> *names_dmap = m_layernames.mapped (dl.layer);
if (names_dmap != 0) {
const std::string *name = names_dmap->mapped (dl.datatype);
if (name != 0) {
lp.name = *name;
}
}
unsigned int ll = layout.insert_layer (lp);
m_layer_map.map (dl, ll, lp);
m_layers_created.insert (ll);
return std::make_pair (true, ll);
}
}
/**
* @brief A helper class to join two datatype layer name map members
*/
@ -765,7 +674,6 @@ OASISReader::do_read (db::Layout &layout)
m_textstrings.clear ();
m_propstrings.clear ();
m_propnames.clear ();
m_layernames.clear ();
m_instances.clear ();
m_instances_with_props.clear ();
@ -1077,10 +985,10 @@ OASISReader::do_read (db::Layout &layout)
LNameJoinOp1 op1;
dt_map.add (dt1, dt2 + 1, name, op1);
LNameJoinOp2 op2;
m_layernames.add (l1, l2 + 1, dt_map, op2);
layer_names ().add (l1, l2 + 1, dt_map, op2);
// rename layers created before if required
for (std::set<unsigned int>::const_iterator i = m_layers_created.begin (); i != m_layers_created.end (); ++i) {
for (std::set<unsigned int>::const_iterator i = layers_created ().begin (); i != layers_created ().end (); ++i) {
const db::LayerProperties &lp = layout.get_properties (*i);
if (lp.layer >= l1 && lp.layer <= l2 && lp.datatype >= dt1 && lp.datatype <= dt2 && lp.name != name) {
// need to rename: add a new madding to m_layer_map and adjust the layout's layer properties
@ -1088,7 +996,7 @@ OASISReader::do_read (db::Layout &layout)
LNameJoinOp1 nj;
nj (lpp.name, name);
layout.set_properties (*i, lpp);
m_layer_map.map (LDPair (lp.layer, lp.datatype), *i, lpp);
layer_map ().map (LDPair (lp.layer, lp.datatype), *i, lpp);
}
}
@ -2038,7 +1946,7 @@ OASISReader::do_read_text (bool xy_absolute,
std::pair<bool, unsigned int> ll (false, 0);
if (m_read_texts) {
ll = open_dl (layout, LDPair (mm_textlayer.get (), mm_texttype.get ()), m_create_layers);
ll = open_dl (layout, LDPair (mm_textlayer.get (), mm_texttype.get ()));
}
if ((m & 0x4) && read_repetition ()) {
@ -2180,7 +2088,7 @@ OASISReader::do_read_rectangle (bool xy_absolute,
db::Box box (db::Point (mm_geometry_x.get (), mm_geometry_y.get ()),
db::Point (mm_geometry_x.get () + mm_geometry_w.get (), mm_geometry_y.get () + mm_geometry_h.get ()));
std::pair<bool, unsigned int> ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()), m_create_layers);
std::pair<bool, unsigned int> ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()));
if ((m & 0x4) && read_repetition ()) {
@ -2294,7 +2202,7 @@ OASISReader::do_read_polygon (bool xy_absolute, db::cell_index_type cell_index,
db::Vector pos (mm_geometry_x.get (), mm_geometry_y.get ());
std::pair<bool, unsigned int> ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()), m_create_layers);
std::pair<bool, unsigned int> ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()));
if ((m & 0x4) && read_repetition ()) {
@ -2461,7 +2369,7 @@ OASISReader::do_read_path (bool xy_absolute, db::cell_index_type cell_index, db:
db::Vector pos (mm_geometry_x.get (), mm_geometry_y.get ());
std::pair<bool, unsigned int> ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()), m_create_layers);
std::pair<bool, unsigned int> ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()));
if ((m & 0x4) && read_repetition ()) {
@ -2620,7 +2528,7 @@ OASISReader::do_read_trapezoid (unsigned char r, bool xy_absolute,db::cell_index
db::Vector pos (mm_geometry_x.get (), mm_geometry_y.get ());
std::pair<bool, unsigned int> ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()), m_create_layers);
std::pair<bool, unsigned int> ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()));
db::Point pts [4];
@ -2775,7 +2683,7 @@ OASISReader::do_read_ctrapezoid (bool xy_absolute,db::cell_index_type cell_index
db::Vector pos (mm_geometry_x.get (), mm_geometry_y.get ());
std::pair<bool, unsigned int> ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()), m_create_layers);
std::pair<bool, unsigned int> ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()));
db::Point pts [4];
@ -3126,7 +3034,7 @@ OASISReader::do_read_circle (bool xy_absolute, db::cell_index_type cell_index, d
db::Vector pos (mm_geometry_x.get (), mm_geometry_y.get ());
std::pair<bool, unsigned int> ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()), m_create_layers);
std::pair<bool, unsigned int> ll = open_dl (layout, LDPair (mm_layer.get (), mm_datatype.get ()));
// ignore this circle if the radius is zero
if (mm_circle_radius.get () <= 0) {
@ -3444,7 +3352,7 @@ OASISReader::do_read_cell (db::cell_index_type cell_index, db::Layout &layout)
// Restore proxy cell (link to PCell or Library)
if (has_context) {
OASISReaderLayerMapping layer_mapping (this, &layout, m_create_layers);
CommonReaderLayerMapping layer_mapping (this, &layout);
layout.recover_proxy_as (cell_index, context_strings.begin (), context_strings.end (), &layer_mapping);
}

View File

@ -81,39 +81,6 @@ public:
*/
~OASISReader ();
/**
* @brief The basic read method
*
* This method will read the stream data and translate this to
* insert calls into the layout object. This will not do much
* on the layout object beside inserting the objects.
* A set of options can be specified with the LoadLayoutOptions
* object.
* The returned map will contain all layers, the passed
* ones and the newly created ones.
*
* @param layout The layout object to write to
* @param map The LayerMap object
* @param create true, if new layers should be created
* @return The LayerMap object that tells where which layer was loaded
*/
virtual const LayerMap &read (db::Layout &layout, const LoadLayoutOptions &options);
/**
* @brief The basic read method (without mapping)
*
* This method will read the stream data and translate this to
* insert calls into the layout object. This will not do much
* on the layout object beside inserting the objects.
* This version will read all input layers and return a map
* which tells which OASIS layer has been read into which logical
* layer.
*
* @param layout The layout object to write to
* @return The LayerMap object
*/
virtual const LayerMap &read (db::Layout &layout);
/**
* @brief Format
*/
@ -136,6 +103,8 @@ protected:
virtual void common_reader_error (const std::string &msg) { error (msg); }
virtual void common_reader_warn (const std::string &msg) { warn (msg); }
virtual void init (const LoadLayoutOptions &options);
virtual void do_read (db::Layout &layout);
private:
friend class OASISReaderLayerMapping;
@ -153,8 +122,6 @@ private:
};
tl::InputStream &m_stream;
LayerMap m_layer_map;
std::set<unsigned int> m_layers_created;
tl::AbsoluteProgress m_progress;
std::string m_cellname;
double m_dbu;
@ -204,12 +171,10 @@ private:
std::map <unsigned long, const db::StringRef *> m_text_forward_references;
std::map <unsigned long, std::string> m_propstrings;
std::map <unsigned long, std::string> m_propnames;
tl::interval_map <db::ld_type, tl::interval_map <db::ld_type, std::string> > m_layernames;
tl::vector<db::CellInstArray> m_instances;
tl::vector<db::CellInstArrayWithProperties> m_instances_with_props;
bool m_create_layers;
bool m_read_texts;
bool m_read_properties;
bool m_read_all_properties;
@ -219,7 +184,6 @@ private:
db::property_names_id_type m_s_gds_property_name_id;
db::property_names_id_type m_klayout_context_property_name_id;
void do_read (db::Layout &layout);
void do_read_cell (db::cell_index_type cell_index, db::Layout &layout);
void do_read_placement (unsigned char r,
@ -310,8 +274,6 @@ private:
db::Coord get_coord (long grid = 1);
db::Coord get_ucoord (unsigned long grid = 1);
distance_type get_ucoord_as_distance (unsigned long grid = 1);
std::pair <bool, unsigned int> open_dl (db::Layout &layout, const LDPair &dl, bool create);
};
}