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
|
||||
|
||||
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 ();
|
||||
|
||||
CommonReader::CommonReader ()
|
||||
|
|
@ -280,7 +308,7 @@ CommonReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
|
|||
{
|
||||
init (options);
|
||||
|
||||
m_layer_map.prepare (layout);
|
||||
m_common_options.layer_map.prepare (layout);
|
||||
|
||||
layout.start_changes ();
|
||||
try {
|
||||
|
|
@ -292,7 +320,7 @@ CommonReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
|
|||
throw;
|
||||
}
|
||||
|
||||
return m_layer_map;
|
||||
return m_layer_map_out;
|
||||
}
|
||||
|
||||
const db::LayerMap &
|
||||
|
|
@ -305,12 +333,23 @@ 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_layer_map_out.clear ();
|
||||
m_multi_mapping_placeholders.clear ();
|
||||
m_layer_cache.clear ();
|
||||
m_layers_created.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
|
||||
|
|
@ -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>
|
||||
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;
|
||||
|
||||
std::map<db::LDPair, std::pair <bool, unsigned int> >::const_iterator lc = m_layer_cache.find (dl);
|
||||
if (lc != m_layer_cache.end ()) {
|
||||
return lc->second;
|
||||
} 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
|
||||
db::LayerProperties lp;
|
||||
|
|
@ -450,18 +545,53 @@ CommonReader::open_dl (db::Layout &layout, const LDPair &dl)
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int ll = layout.insert_layer (lp);
|
||||
m_layer_map.map (dl, ll, lp);
|
||||
unsigned int nl = layout.insert_layer (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
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
DB_PUBLIC void
|
||||
join_layer_names (std::string &s, const std::string &n);
|
||||
|
||||
/**
|
||||
* @brief The CellConflictResolution enum
|
||||
*/
|
||||
|
|
@ -235,14 +238,6 @@ protected:
|
|||
return m_common_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the layer map
|
||||
*/
|
||||
db::LayerMap &layer_map ()
|
||||
{
|
||||
return m_layer_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the layer name map
|
||||
*/
|
||||
|
|
@ -251,14 +246,6 @@ protected:
|
|||
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
|
||||
*/
|
||||
|
|
@ -271,9 +258,13 @@ private:
|
|||
CellConflictResolution m_cc_resolution;
|
||||
bool m_create_layers;
|
||||
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;
|
||||
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::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 (),
|
||||
"1/10 : 1/0\n"
|
||||
"2/0-9,21-*\n"
|
||||
"2/0-1 : 2/0\n"
|
||||
"1/0 : 1/0\n"
|
||||
"1/1 : 1/1\n"
|
||||
"1/20 : 1/1020\n"
|
||||
|
|
@ -427,16 +427,55 @@ TEST(3_AdvancedMapping)
|
|||
"2/11 : 2/11\n"
|
||||
"42/42 : 142/42\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");
|
||||
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)
|
||||
{
|
||||
db::Manager m (false);
|
||||
|
|
|
|||
|
|
@ -508,12 +508,7 @@ struct LNameJoinOp1
|
|||
{
|
||||
void operator() (std::string &a, const std::string &b)
|
||||
{
|
||||
if (a != b) {
|
||||
if (! a.empty ()) {
|
||||
a += ";";
|
||||
}
|
||||
a += b;
|
||||
}
|
||||
join_layer_names (a, b);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -987,19 +982,6 @@ OASISReader::do_read (db::Layout &layout)
|
|||
LNameJoinOp2 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 ();
|
||||
|
||||
// ignore properties attached to this name item
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue