mirror of https://github.com/KLayout/klayout.git
WIP: implementation for GDS2 and OASIS, added tests.
This commit is contained in:
parent
f86c13689b
commit
a1eb8c121b
|
|
@ -32,6 +32,34 @@ namespace db
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// Common reader implementation
|
// Common reader implementation
|
||||||
|
|
||||||
|
DB_PUBLIC void
|
||||||
|
join_layer_names (std::string &s, const std::string &n)
|
||||||
|
{
|
||||||
|
if (s == n) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! s.empty ()) {
|
||||||
|
|
||||||
|
size_t i = s.find (n);
|
||||||
|
if (i != std::string::npos && (i == 0 || s.c_str ()[i - 1] == ';')) {
|
||||||
|
char after = s.c_str ()[i + n.size ()];
|
||||||
|
if (after == 0 || after == ';') {
|
||||||
|
// n is already contained in s
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s += ";";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
s += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// Common reader implementation
|
||||||
|
|
||||||
static const size_t null_id = std::numeric_limits<size_t>::max ();
|
static const size_t null_id = std::numeric_limits<size_t>::max ();
|
||||||
|
|
||||||
CommonReader::CommonReader ()
|
CommonReader::CommonReader ()
|
||||||
|
|
@ -280,7 +308,7 @@ CommonReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
|
||||||
{
|
{
|
||||||
init (options);
|
init (options);
|
||||||
|
|
||||||
m_layer_map.prepare (layout);
|
m_common_options.layer_map.prepare (layout);
|
||||||
|
|
||||||
layout.start_changes ();
|
layout.start_changes ();
|
||||||
try {
|
try {
|
||||||
|
|
@ -292,7 +320,7 @@ CommonReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_layer_map;
|
return m_layer_map_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
const db::LayerMap &
|
const db::LayerMap &
|
||||||
|
|
@ -305,12 +333,23 @@ void
|
||||||
CommonReader::init (const LoadLayoutOptions &options)
|
CommonReader::init (const LoadLayoutOptions &options)
|
||||||
{
|
{
|
||||||
m_common_options = options.get_options<db::CommonReaderOptions> ();
|
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_cc_resolution = m_common_options.cell_conflict_resolution;
|
||||||
m_create_layers = m_common_options.create_other_layers;
|
m_create_layers = m_common_options.create_other_layers;
|
||||||
|
|
||||||
|
m_layer_map_out.clear ();
|
||||||
|
m_multi_mapping_placeholders.clear ();
|
||||||
|
m_layer_cache.clear ();
|
||||||
m_layers_created.clear ();
|
m_layers_created.clear ();
|
||||||
m_layer_names.clear ();
|
m_layer_names.clear ();
|
||||||
|
|
||||||
|
// create a pseudo-multimapping for single targets
|
||||||
|
for (db::LayerMap::const_iterator_layers li = m_common_options.layer_map.begin (); li != m_common_options.layer_map.end (); ++li) {
|
||||||
|
for (db::LayerMap::const_iterator_datatypes di = li->second.begin (); di != li->second.end (); ++di) {
|
||||||
|
if (di->second.size () == 1) {
|
||||||
|
m_multi_mapping_placeholders.insert (std::make_pair (di->second, *di->second.begin ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -420,21 +459,77 @@ CommonReader::finish (db::Layout &layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolve layer multi-mapping
|
||||||
|
|
||||||
|
for (std::map<std::set<unsigned int>, unsigned int>::const_iterator i = m_multi_mapping_placeholders.begin (); i != m_multi_mapping_placeholders.end (); ++i) {
|
||||||
|
|
||||||
|
if (i->first.size () > 1) {
|
||||||
|
|
||||||
|
bool discard_layer = i->first.find (i->second) == i->first.end ();
|
||||||
|
|
||||||
|
for (std::set<unsigned int>::const_iterator l = i->first.begin (); l != i->first.end (); ++l) {
|
||||||
|
|
||||||
|
// last one? this one will get a "move"
|
||||||
|
std::set<unsigned int>::const_iterator ll = l;
|
||||||
|
if (discard_layer && ++ll == i->first.end ()) {
|
||||||
|
layout.move_layer (i->second, *l);
|
||||||
|
layout.delete_layer (i->second);
|
||||||
|
} else {
|
||||||
|
layout.copy_layer (i->second, *l);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// rename layers created before if required
|
||||||
|
|
||||||
|
for (std::set<unsigned int>::const_iterator i = m_layers_created.begin (); i != m_layers_created.end (); ++i) {
|
||||||
|
|
||||||
|
const db::LayerProperties &lp = layout.get_properties (*i);
|
||||||
|
|
||||||
|
const tl::interval_map <db::ld_type, std::string> *dtmap = layer_names ().mapped (lp.layer);
|
||||||
|
const std::string *name = 0;
|
||||||
|
if (dtmap) {
|
||||||
|
name = dtmap->mapped (lp.datatype);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
// need to rename: add a new madding to m_layer_map_out and adjust the layout's layer properties
|
||||||
|
db::LayerProperties lpp = lp;
|
||||||
|
join_layer_names (lpp.name, *name);
|
||||||
|
layout.set_properties (*i, lpp);
|
||||||
|
m_layer_map_out.map (LDPair (lp.layer, lp.datatype), *i, lpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair <bool, unsigned int>
|
std::pair <bool, unsigned int>
|
||||||
CommonReader::open_dl (db::Layout &layout, const LDPair &dl)
|
CommonReader::open_dl (db::Layout &layout, const LDPair &dl)
|
||||||
{
|
{
|
||||||
std::pair<bool, unsigned int> ll = m_layer_map.first_logical (dl, layout);
|
std::map<db::LDPair, std::pair <bool, unsigned int> >::const_iterator lc = m_layer_cache.find (dl);
|
||||||
if (ll.first) {
|
if (lc != m_layer_cache.end ()) {
|
||||||
|
return lc->second;
|
||||||
return ll;
|
|
||||||
|
|
||||||
} else if (! m_create_layers) {
|
|
||||||
|
|
||||||
return ll;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
std::pair <bool, unsigned int> res = open_dl_uncached (layout, dl);
|
||||||
|
m_layer_cache.insert (std::make_pair (dl, res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair <bool, unsigned int>
|
||||||
|
CommonReader::open_dl_uncached (db::Layout &layout, const LDPair &dl)
|
||||||
|
{
|
||||||
|
const std::set<unsigned int> &li = common_options ().layer_map.logical (dl, layout);
|
||||||
|
if (li.empty ()) {
|
||||||
|
|
||||||
|
if (! m_create_layers) {
|
||||||
|
return std::make_pair (false, (unsigned int) 0);
|
||||||
|
}
|
||||||
|
|
||||||
// and create the layer
|
// and create the layer
|
||||||
db::LayerProperties lp;
|
db::LayerProperties lp;
|
||||||
|
|
@ -450,18 +545,53 @@ CommonReader::open_dl (db::Layout &layout, const LDPair &dl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ll = layout.insert_layer (lp);
|
unsigned int nl = layout.insert_layer (lp);
|
||||||
m_layer_map.map (dl, ll, lp);
|
m_layer_map_out.map (dl, nl, lp);
|
||||||
|
|
||||||
m_layers_created.insert (ll);
|
m_layers_created.insert (nl);
|
||||||
|
|
||||||
return std::make_pair (true, ll);
|
return std::make_pair (true, nl);
|
||||||
|
|
||||||
|
} else if (li.size () == 1) {
|
||||||
|
|
||||||
|
m_layer_map_out.map (dl, *li.begin (), layout.get_properties (*li.begin ()));
|
||||||
|
|
||||||
|
return std::make_pair (true, *li.begin ());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
std::map<std::set<unsigned int>, unsigned int>::iterator mmp = m_multi_mapping_placeholders.find (li);
|
||||||
|
if (mmp == m_multi_mapping_placeholders.end ()) {
|
||||||
|
|
||||||
|
// multi-mapping: create a placeholder layer if required
|
||||||
|
|
||||||
|
for (std::set<unsigned int>::const_iterator i = li.begin (); i != li.end (); ++i) {
|
||||||
|
m_layer_map_out.mmap (dl, *i, layout.get_properties (*i));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::set<unsigned int>::const_iterator i = li.begin (); i != li.end (); ++i) {
|
||||||
|
std::set<unsigned int> sl;
|
||||||
|
sl.insert (*i);
|
||||||
|
if (m_multi_mapping_placeholders.find (sl) == m_multi_mapping_placeholders.end ()) {
|
||||||
|
// a layer not used in a single-target context can be used as a placeholder layer (but only once)
|
||||||
|
m_multi_mapping_placeholders.insert (std::make_pair (sl, *i));
|
||||||
|
mmp = m_multi_mapping_placeholders.insert (std::make_pair (li, *i)).first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mmp == m_multi_mapping_placeholders.end ()) {
|
||||||
|
// create a placeholder layer for later
|
||||||
|
mmp = m_multi_mapping_placeholders.insert (std::make_pair (li, layout.insert_layer ())).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair (true, mmp->second);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// Common format declaration
|
// Common format declaration
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,9 @@
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
||||||
|
DB_PUBLIC void
|
||||||
|
join_layer_names (std::string &s, const std::string &n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The CellConflictResolution enum
|
* @brief The CellConflictResolution enum
|
||||||
*/
|
*/
|
||||||
|
|
@ -235,14 +238,6 @@ protected:
|
||||||
return m_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
|
* @brief Gets the layer name map
|
||||||
*/
|
*/
|
||||||
|
|
@ -251,14 +246,6 @@ protected:
|
||||||
return m_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
|
* @brief Enters the a layer with a given layer/datatype
|
||||||
*/
|
*/
|
||||||
|
|
@ -271,9 +258,13 @@ private:
|
||||||
CellConflictResolution m_cc_resolution;
|
CellConflictResolution m_cc_resolution;
|
||||||
bool m_create_layers;
|
bool m_create_layers;
|
||||||
db::CommonReaderOptions m_common_options;
|
db::CommonReaderOptions m_common_options;
|
||||||
db::LayerMap m_layer_map;
|
db::LayerMap m_layer_map_out;
|
||||||
tl::interval_map <db::ld_type, tl::interval_map <db::ld_type, std::string> > m_layer_names;
|
tl::interval_map <db::ld_type, tl::interval_map <db::ld_type, std::string> > m_layer_names;
|
||||||
|
std::map<db::LDPair, std::pair <bool, unsigned int> > m_layer_cache;
|
||||||
|
std::map<std::set<unsigned int>, unsigned int> m_multi_mapping_placeholders;
|
||||||
std::set<unsigned int> m_layers_created;
|
std::set<unsigned int> m_layers_created;
|
||||||
|
|
||||||
|
std::pair <bool, unsigned int> open_dl_uncached (db::Layout &layout, const LDPair &dl);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -418,7 +418,7 @@ TEST(3_AdvancedMapping)
|
||||||
|
|
||||||
EXPECT_EQ (lm_read.to_string_file_format (),
|
EXPECT_EQ (lm_read.to_string_file_format (),
|
||||||
"1/10 : 1/0\n"
|
"1/10 : 1/0\n"
|
||||||
"2/0-9,21-*\n"
|
"2/0-1 : 2/0\n"
|
||||||
"1/0 : 1/0\n"
|
"1/0 : 1/0\n"
|
||||||
"1/1 : 1/1\n"
|
"1/1 : 1/1\n"
|
||||||
"1/20 : 1/1020\n"
|
"1/20 : 1/1020\n"
|
||||||
|
|
@ -427,16 +427,55 @@ TEST(3_AdvancedMapping)
|
||||||
"2/11 : 2/11\n"
|
"2/11 : 2/11\n"
|
||||||
"42/42 : 142/42\n"
|
"42/42 : 142/42\n"
|
||||||
"100/0 : 200/0\n"
|
"100/0 : 200/0\n"
|
||||||
"2/12-20 : */*\n"
|
|
||||||
"1/22-30 : 1/*+1000\n"
|
|
||||||
"1/2-9,11-19,31-* : */*\n"
|
|
||||||
"0/*;3-41/*;42/0-41,43-*;43-99/*;100/1-*;101-*/* : *+100/*\n"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
std::string fn_au (tl::testsrc () + "/testdata/gds/alm_au.gds");
|
std::string fn_au (tl::testsrc () + "/testdata/gds/alm_au.gds");
|
||||||
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
|
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(3_MultiMapping)
|
||||||
|
{
|
||||||
|
db::Manager m (false);
|
||||||
|
db::Layout layout (&m);
|
||||||
|
|
||||||
|
db::LoadLayoutOptions options;
|
||||||
|
db::LayerMap lm, lm_read;
|
||||||
|
|
||||||
|
unsigned int n = 0;
|
||||||
|
lm.map_expr ("*/*: */*", n++);
|
||||||
|
lm.unmap_expr ("1-2/10");
|
||||||
|
lm.mmap_expr ("1-2/10: *+100/*", n++);
|
||||||
|
lm.mmap_expr ("1/10;2/10: 12/1010", n++);
|
||||||
|
lm.mmap_expr ("1/0-1: */*+1000", n++);
|
||||||
|
options.get_options<db::CommonReaderOptions> ().layer_map = lm;
|
||||||
|
|
||||||
|
{
|
||||||
|
tl::InputStream file (tl::testsrc () + "/testdata/gds/alm.gds");
|
||||||
|
db::Reader reader (file);
|
||||||
|
lm_read = reader.read (layout, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ (lm_read.to_string_file_format (),
|
||||||
|
"+1-2/10 : 12/1010\n"
|
||||||
|
"+1/0 : 1/1000\n"
|
||||||
|
"+1/0 : 1/0\n"
|
||||||
|
"+1/1 : 1/1001\n"
|
||||||
|
"+1/1 : 1/1\n"
|
||||||
|
"+1/10 : 101/10\n"
|
||||||
|
"1/20 : 1/20\n"
|
||||||
|
"1/21 : 1/21\n"
|
||||||
|
"2/0 : 2/0\n"
|
||||||
|
"2/1 : 2/1\n"
|
||||||
|
"+2/10 : 102/10\n"
|
||||||
|
"2/11 : 2/11\n"
|
||||||
|
"42/42 : 42/42\n"
|
||||||
|
"100/0 : 100/0\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
std::string fn_au (tl::testsrc () + "/testdata/gds/alm_au2.gds");
|
||||||
|
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(4_CollectModeRename)
|
TEST(4_CollectModeRename)
|
||||||
{
|
{
|
||||||
db::Manager m (false);
|
db::Manager m (false);
|
||||||
|
|
|
||||||
|
|
@ -508,12 +508,7 @@ struct LNameJoinOp1
|
||||||
{
|
{
|
||||||
void operator() (std::string &a, const std::string &b)
|
void operator() (std::string &a, const std::string &b)
|
||||||
{
|
{
|
||||||
if (a != b) {
|
join_layer_names (a, b);
|
||||||
if (! a.empty ()) {
|
|
||||||
a += ";";
|
|
||||||
}
|
|
||||||
a += b;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -987,19 +982,6 @@ OASISReader::do_read (db::Layout &layout)
|
||||||
LNameJoinOp2 op2;
|
LNameJoinOp2 op2;
|
||||||
layer_names ().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 = 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
|
|
||||||
db::LayerProperties lpp = lp;
|
|
||||||
LNameJoinOp1 nj;
|
|
||||||
nj (lpp.name, name);
|
|
||||||
layout.set_properties (*i, lpp);
|
|
||||||
layer_map ().map (LDPair (lp.layer, lp.datatype), *i, lpp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_modal_variables ();
|
reset_modal_variables ();
|
||||||
|
|
||||||
// ignore properties attached to this name item
|
// ignore properties attached to this name item
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue