WIP: implementation for GDS2 and OASIS, added tests.

This commit is contained in:
Matthias Koefferlein 2020-12-19 15:36:03 +01:00
parent f86c13689b
commit a1eb8c121b
5 changed files with 201 additions and 59 deletions

View File

@ -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

View File

@ -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);
};
/**

View File

@ -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);

View File

@ -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

BIN
testdata/gds/alm_au2.gds vendored Normal file

Binary file not shown.