WIP: first draft of implementation

This commit is contained in:
Matthias Koefferlein 2020-12-14 23:55:04 +01:00
parent b5c0193a0a
commit 1106a52688
2 changed files with 262 additions and 75 deletions

View File

@ -40,10 +40,9 @@ namespace db
/// A helper class to join two datatype map members
struct LmapJoinOp1
{
void operator() (unsigned int &a, unsigned int b)
void operator() (std::set<unsigned int> &a, const std::set<unsigned int> &b)
{
// TODO: could also do?: throw an exception ..
a = b;
a.insert (b.begin (), b.end ());
}
};
@ -58,7 +57,27 @@ struct LmapJoinOp2
}
};
/// Utility typedefs for the expression parser
/// A helper class to implement the unmap operation
struct LmapEraseDatatypeInterval
{
LmapEraseDatatypeInterval (unsigned int dfrom, unsigned int dto)
: m_dfrom (dfrom), m_dto (dto)
{ }
void operator() (LayerMap::datatype_map &a, const LayerMap::datatype_map &)
{
if (is_static_ld (m_dfrom) && is_static_ld (m_dto)) {
a.erase (m_dfrom, m_dto);
} else {
a.clear ();
}
}
private:
unsigned int m_dfrom, m_dto;
};
/// Utility typedefs for the expression parser
typedef std::pair<ld_type, ld_type> ld_interval;
/// Utility typedefs for the expression parser
@ -71,70 +90,70 @@ LayerMap::LayerMap ()
// .. nothing yet ..
}
std::pair<bool, unsigned int>
std::set<unsigned int>
LayerMap::logical (const LDPair &p) const
{
return logical_internal (p, false);
}
std::pair<bool, unsigned int>
std::set<unsigned int>
LayerMap::logical (const std::string &n) const
{
return logical_internal (n, false);
}
std::pair<bool, unsigned int>
std::set<unsigned int>
LayerMap::logical (const db::LayerProperties &p) const
{
return logical_internal (p, false);
}
std::pair<bool, unsigned int>
std::set<unsigned int>
LayerMap::logical_internal (const LDPair &p, bool allow_placeholder) const
{
const datatype_map *dm = m_ld_map.mapped (p.layer);
if (dm) {
const unsigned int *l = dm->mapped (p.datatype);
const std::set<unsigned int> *l = dm->mapped (p.datatype);
if (l && (allow_placeholder || ! is_placeholder (*l))) {
return std::make_pair (true, *l);
return *l;
}
}
return std::make_pair (false, 0);
return std::set<unsigned int> ();
}
std::pair<bool, unsigned int>
std::set<unsigned int>
LayerMap::logical_internal (const std::string &n, bool allow_placeholder) const
{
std::map<std::string, unsigned int>::const_iterator m = m_name_map.find (n);
std::map<std::string, std::set<unsigned int> >::const_iterator m = m_name_map.find (n);
if (m != m_name_map.end () && (allow_placeholder || ! is_placeholder (m->second))) {
return std::make_pair (true, m->second);
return m->second;
} else {
return std::make_pair (false, 0);
return std::set<unsigned int> ();
}
}
std::pair<bool, unsigned int>
std::set<unsigned int>
LayerMap::logical_internal (const db::LayerProperties &p, bool allow_placeholder) const
{
std::set<unsigned int> m;
if (p.layer >= 0 && p.datatype >= 0) {
std::pair<bool, unsigned int> m = logical_internal (db::LDPair (p.layer, p.datatype), allow_placeholder);
if (m.first) {
return m;
}
m = logical_internal (db::LDPair (p.layer, p.datatype), allow_placeholder);
}
if (! p.name.empty ()) {
std::pair<bool, unsigned int> m = logical_internal (p.name, allow_placeholder);
if (m.first) {
return m;
}
if (m.empty () && ! p.name.empty ()) {
m = logical_internal (p.name, allow_placeholder);
}
return std::make_pair (false, 0);
return m;
}
bool
LayerMap::is_placeholder (unsigned int l) const
LayerMap::is_placeholder (const std::set<unsigned int> &m) const
{
return (m_placeholders.size () > std::numeric_limits<unsigned int>::max () - l);
for (std::set<unsigned int>::const_iterator i = m.begin (); i != m.end (); ++i) {
if (m_placeholders.size () > std::numeric_limits<unsigned int>::max () - *i) {
return true;
}
}
return false;
}
const db::LayerProperties *
@ -148,39 +167,52 @@ LayerMap::target (unsigned int l) const
}
}
std::pair<bool, unsigned int>
std::set<unsigned int>
LayerMap::logical (const db::LayerProperties &p, db::Layout &layout) const
{
std::pair<bool, unsigned int> l = logical_internal (p, true);
if (l.first && is_placeholder (l.second)) {
return const_cast<LayerMap *> (this)->substitute_placeholder (p, l.second, layout);
std::set<unsigned int> l = logical_internal (p, true);
if (is_placeholder (l)) {
return const_cast<LayerMap *> (this)->substitute_placeholder (p, l, layout);
} else {
return l;
}
}
std::pair<bool, unsigned int>
std::set<unsigned int>
LayerMap::logical (const db::LDPair &p, db::Layout &layout) const
{
std::pair<bool, unsigned int> l = logical_internal (p, true);
if (l.first && is_placeholder (l.second)) {
return const_cast<LayerMap *> (this)->substitute_placeholder (db::LayerProperties (p.layer, p.datatype), l.second, layout);
std::set<unsigned int> l = logical_internal (p, true);
if (is_placeholder (l)) {
return const_cast<LayerMap *> (this)->substitute_placeholder (db::LayerProperties (p.layer, p.datatype), l, layout);
} else {
return l;
}
}
std::pair<bool, unsigned int>
LayerMap::substitute_placeholder (const db::LayerProperties &p, unsigned int ph, db::Layout &layout)
std::set<unsigned int>
LayerMap::substitute_placeholder (const db::LayerProperties &p, const std::set<unsigned int> &m, db::Layout &layout)
{
const db::LayerProperties &lp_ph = m_placeholders [std::numeric_limits<unsigned int>::max () - ph];
db::LayerProperties lp_new = p;
lp_new.layer = db::ld_combine (p.layer, lp_ph.layer);
lp_new.datatype = db::ld_combine (p.datatype, lp_ph.datatype);
std::set<unsigned int> res;
for (std::set<unsigned int>::const_iterator i = m.begin (); i != m.end (); ++i) {
unsigned int l_new = layout.insert_layer (lp_new);
map (p, l_new, lp_new);
return std::make_pair (true, l_new);
if (m_placeholders.size () > std::numeric_limits<unsigned int>::max () - *i) {
const db::LayerProperties &lp_ph = m_placeholders [std::numeric_limits<unsigned int>::max () - *i];
db::LayerProperties lp_new = p;
lp_new.layer = db::ld_combine (p.layer, lp_ph.layer);
lp_new.datatype = db::ld_combine (p.datatype, lp_ph.datatype);
unsigned int l_new = layout.insert_layer (lp_new);
map (p, l_new, lp_new);
res.insert (l_new);
} else {
res.insert (*i);
}
}
return res;
}
static std::string format_interval (ld_type l1, ld_type l2)
@ -206,7 +238,7 @@ LayerMap::mapping_str (unsigned int ll) const
bool f2 = true;
for (datatype_map::const_iterator d = l->second.begin (); d != l->second.end (); ++d) {
if (d->second == ll) {
if (d->second.find (ll) != d->second.end ()) {
// create a string representation
if (!f2) {
@ -232,8 +264,9 @@ LayerMap::mapping_str (unsigned int ll) const
}
for (std::map <std::string, unsigned int>::const_iterator l = m_name_map.begin (); l != m_name_map.end (); ++l) {
if (l->second == ll) {
for (std::map <std::string, std::set<unsigned int> >::const_iterator l = m_name_map.begin (); l != m_name_map.end (); ++l) {
if (l->second.find (ll) != l->second.end ()) {
if (!f1) {
s += ";";
@ -243,6 +276,7 @@ LayerMap::mapping_str (unsigned int ll) const
s += tl::to_word_or_quoted_string (l->first);
}
}
std::map<unsigned int, LayerProperties>::const_iterator t = m_target_layers.find (ll);
@ -300,11 +334,19 @@ LayerMap::prepare (db::Layout &layout)
// Now remap the indexes
for (ld_map::iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) {
for (datatype_map::iterator d = l->second.begin (); d != l->second.end (); ++d) {
d->second = real_layers [d->second];
std::set<unsigned int> dn;
for (std::set<unsigned int>::const_iterator i = d->second.begin (); i != d->second.end (); ++i) {
dn.insert (real_layers [*i]);
}
d->second = dn;
}
}
for (std::map<std::string, unsigned int>::iterator n = m_name_map.begin (); n != m_name_map.end (); ++n) {
n->second = real_layers [n->second];
for (std::map<std::string, std::set<unsigned int> >::iterator n = m_name_map.begin (); n != m_name_map.end (); ++n) {
std::set<unsigned int> dn;
for (std::set<unsigned int>::const_iterator i = n->second.begin (); i != n->second.end (); ++i) {
dn.insert (real_layers [*i]);
}
n->second = dn;
}
std::map<unsigned int, LayerProperties> old_target_layers;
@ -329,11 +371,11 @@ LayerMap::get_layers () const
for (ld_map::const_iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) {
for (datatype_map::const_iterator d = l->second.begin (); d != l->second.end (); ++d) {
layers.insert (d->second);
layers.insert (d->second.begin (), d->second.end ());
}
}
for (const_iterator_names n = m_name_map.begin (); n != m_name_map.end (); ++n) {
layers.insert(n->second);
layers.insert(n->second.begin (), n->second.end ());
}
return std::vector<unsigned int> (layers.begin (), layers.end ());
@ -358,7 +400,7 @@ LayerMap::mapping (unsigned int ll) const
// no mapping is given. Use the lowest layer and datatype
for (ld_map::const_iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) {
for (datatype_map::const_iterator d = l->second.begin (); d != l->second.end (); ++d) {
if (d->second == ll) {
if (d->second.find (ll) != d->second.end ()) {
p.layer = l->first.first;
p.datatype = d->first.first;
break;
@ -373,7 +415,7 @@ LayerMap::mapping (unsigned int ll) const
// no mapping is given. Use the lowest layer and datatype
for (ld_map::const_iterator l = m_ld_map.begin (); l != m_ld_map.end (); ++l) {
for (datatype_map::const_iterator d = l->second.begin (); d != l->second.end (); ++d) {
if (d->second == ll) {
if (d->second.find (ll) != d->second.end ()) {
p.layer = l->first.first;
p.datatype = d->first.first;
break;
@ -384,8 +426,8 @@ LayerMap::mapping (unsigned int ll) const
}
if (p.name.empty ()) {
for (std::map <std::string, unsigned int>::const_iterator l = m_name_map.begin (); l != m_name_map.end (); ++l) {
if (l->second == ll) {
for (std::map <std::string, std::set<unsigned int> >::const_iterator l = m_name_map.begin (); l != m_name_map.end (); ++l) {
if (l->second.find (ll) != l->second.end ()) {
p.name = l->first;
break;
}
@ -515,7 +557,7 @@ LayerMap::map_expr (tl::Extractor &ex, unsigned int l)
ld_type n;
if (! ex.try_read (n) && ex.try_read_word_or_quoted (name)) {
m_name_map.insert (std::make_pair (name, l));
m_name_map [name].insert (l);
} else {
@ -533,7 +575,9 @@ LayerMap::map_expr (tl::Extractor &ex, unsigned int l)
datatype_map dm;
for (ld_interval_vector::const_iterator di = vd.begin (); di != vd.end (); ++di) {
LmapJoinOp1 op1;
dm.add (di->first, di->second + 1, l, op1);
std::set<unsigned int> single;
single.insert (l);
dm.add (di->first, di->second + 1, single, op1);
}
for (ld_interval_vector::const_iterator li = vl.begin (); li != vl.end (); ++li) {
LmapJoinOp2 op2;
@ -566,7 +610,7 @@ LayerMap::insert (const std::string &name, unsigned int l, const LayerProperties
m_target_layers[l] = *target;
}
m_name_map.insert (std::make_pair (name, l));
m_name_map [name].insert (l);
if (l >= m_next_index) {
m_next_index = l + 1;
@ -580,13 +624,16 @@ LayerMap::insert (const LDPair &p1, const LDPair &p2, unsigned int l, const Laye
m_target_layers[l] = *target;
}
std::set<unsigned int> single;
single.insert (l);
// create a single-interval list for the datatype range
LayerMap::datatype_map dt;
LmapJoinOp1 op1;
if (db::is_static_ld (p1.datatype) && db::is_static_ld (p2.datatype)) {
dt.add (p1.datatype, p2.datatype + 1, l, op1);
dt.add (p1.datatype, p2.datatype + 1, single, op1);
} else {
dt.add (0, std::numeric_limits<ld_type>::max (), l, op1);
dt.add (0, std::numeric_limits<ld_type>::max (), single, op1);
}
// add this to the layers using the special join operator that
@ -603,6 +650,103 @@ LayerMap::insert (const LDPair &p1, const LDPair &p2, unsigned int l, const Laye
}
}
void
LayerMap::unmap (const LDPair &f)
{
unmap (f, f);
}
void
LayerMap::unmap (const std::string &name)
{
m_name_map.erase (name);
}
void
LayerMap::unmap (const LayerProperties &f)
{
if (f.name.empty () || is_static_ld (f.layer) || is_static_ld (f.datatype)) {
unmap (db::LDPair (f.layer, f.datatype));
}
if (! f.name.empty ()) {
unmap (f.name);
}
}
void
LayerMap::unmap (const LDPair &p1, const LDPair &p2)
{
if (m_ld_map.begin () == m_ld_map.end ()) {
return;
}
LmapEraseDatatypeInterval op (p1.datatype, p2.datatype);
if (db::is_static_ld (p1.layer) && db::is_static_ld (p2.layer)) {
m_ld_map.add (p1.layer, p1.layer + 1, LayerMap::datatype_map (), op);
} else {
m_ld_map.add (m_ld_map.begin ()->first.first, m_ld_map.end ()->first.second, LayerMap::datatype_map (), op);
}
}
void
LayerMap::unmap_expr (const std::string &expr)
{
tl::Extractor ex (expr.c_str ());
unmap_expr (ex);
ex.expect_end ();
}
void
LayerMap::unmap_expr (tl::Extractor &ex)
{
try {
do {
tl::Extractor ex_saved = ex;
std::string name;
ld_type n;
if (! ex.try_read (n) && ex.try_read_word_or_quoted (name)) {
m_name_map.erase (name);
} else {
ex = ex_saved;
ld_interval_vector vl, vd;
parse_intervals (ex, vl);
if (ex.test ("/")) {
parse_intervals (ex, vd);
} else {
vd.push_back (ld_interval (0, 0));
}
for (ld_interval_vector::const_iterator li = vl.begin (); li != vl.end (); ++li) {
for (ld_interval_vector::const_iterator di = vd.begin (); di != vd.end (); ++di) {
unmap (LDPair (li->first, di->first), LDPair (li->second, di->second));
}
}
}
} while (ex.test (";") || ex.test (","));
if (ex.test (":")) {
// ignore target layers
LayerProperties lp;
lp.read (ex, true);
}
} catch (...) {
throw LayerSpecFormatException (ex.skip ());
}
}
void
LayerMap::clear ()
{

View File

@ -35,6 +35,7 @@
#include <map>
#include <limits>
#include <set>
namespace db
{
@ -161,6 +162,15 @@ struct DB_PUBLIC LDPair
* and effectively rename a layer or add layer name information to
* a GDS layer/datatype layer.
*
* "Unmapping" can be used to create "holes" in ranges of layers.
* For example, by first mapping layers 1 to 100, datatype 0 and then
* unmapping layer 50, datatype 0, the layers 1 to 49 and 51 to 100, datatype 0
* are mapped.
*
* The layer map supports multi-mapping. That is, one input layer is
* mapped to multiple target layers. It also supports merging but
* mapping different input layers to a single target layer.
*
* A layer map object can be used as a standalone object or in
* conjunction with a layout object. As a standalone object, the
* logical layers (indexes) are simply consecutive numbers.
@ -178,11 +188,11 @@ class DB_PUBLIC LayerMap
: public gsi::ObjectBase
{
public:
typedef tl::interval_map<ld_type, unsigned int> datatype_map;
typedef tl::interval_map<ld_type, std::set<unsigned int> > datatype_map;
typedef tl::interval_map<ld_type, datatype_map> ld_map;
typedef ld_map::const_iterator const_iterator_layers;
typedef datatype_map::const_iterator const_iterator_datatypes;
typedef std::map<std::string, unsigned int>::const_iterator const_iterator_names;
typedef std::map<std::string, std::set<unsigned int> >::const_iterator const_iterator_names;
/**
* @brief The constructor for an empty map
@ -195,7 +205,7 @@ public:
* @return A pair telling if the layer is mapped (first=true) and
* the logical layer mapped (second) if this is the case.
*/
std::pair<bool, unsigned int> logical (const LDPair &p) const;
std::set<unsigned int> logical (const LDPair &p) const;
/**
* @brief Query a layer mapping from a name
@ -203,7 +213,7 @@ public:
* @return A pair telling if the layer is mapped (first=true) and
* the logical layer mapped (second) if this is the case.
*/
std::pair<bool, unsigned int> logical (const std::string &name) const;
std::set<unsigned int> logical (const std::string &name) const;
/**
* @brief Query a layer mapping from a name or LDPair
@ -213,7 +223,7 @@ public:
*
* @param p The layer that is looked for
*/
std::pair<bool, unsigned int> logical (const db::LayerProperties &p) const;
std::set<unsigned int> logical (const db::LayerProperties &p) const;
/**
* @brief Query or install a layer mapping from a name or LDPair
@ -227,14 +237,14 @@ public:
* the logical layers are placeholder values which will be replaced by
* true layers during this method if a new layer is requested.
*/
std::pair<bool, unsigned int> logical (const db::LayerProperties &p, db::Layout &layout) const;
std::set<unsigned int> logical (const db::LayerProperties &p, db::Layout &layout) const;
/**
* @brief Query or install a layer mapping from a LDPair
*
* See the version for LayerProperties about details.
*/
std::pair<bool, unsigned int> logical (const db::LDPair &p, db::Layout &layout) const;
std::set<unsigned int> logical (const db::LDPair &p, db::Layout &layout) const;
/**
* @brief Gets the target layer for a given logical layer
@ -371,6 +381,39 @@ public:
*/
void map_expr (tl::Extractor &ex, unsigned int l);
/**
* @brief Unmaps a LDPair
*/
void unmap (const LDPair &f);
/**
* @brief Unmaps the layer with the given name
*/
void unmap (const std::string &name);
/**
* @brief Unmaps a layer with the given layer properties
*/
void unmap (const LayerProperties &f);
/**
* @brief Removes any mapping for a range of ldpair's
*
* The range is given by two pairs p1,p2. The layers
* between [p1.l,p2.l] and with datatypes between [p1.d,p2.d] are unmapped.
*/
void unmap (const LDPair &p1, const LDPair &p2);
/**
* @brief Removes any mapping for the layers given by the expression
*/
void unmap_expr (const std::string &expr);
/**
* @brief Removes any mapping for the layers given by the expression
*/
void unmap_expr (tl::Extractor &ex);
/**
* @brief Prepares a layer mapping object for reading
*
@ -454,7 +497,7 @@ public:
private:
ld_map m_ld_map;
std::map<std::string, unsigned int> m_name_map;
std::map<std::string, std::set<unsigned int> > m_name_map;
std::map<unsigned int, LayerProperties> m_target_layers;
std::vector<LayerProperties> m_placeholders;
unsigned int m_next_index;
@ -462,12 +505,12 @@ private:
void insert (const LDPair &p1, const LDPair &p2, unsigned int l, const LayerProperties *t);
void insert (const std::string &name, unsigned int l, const LayerProperties *t);
std::pair<bool, unsigned int> logical_internal (const LDPair &p, bool allow_placeholder) const;
std::pair<bool, unsigned int> logical_internal (const std::string &name, bool allow_placeholder) const;
std::pair<bool, unsigned int> logical_internal (const db::LayerProperties &p, bool allow_placeholder) const;
std::set<unsigned int> logical_internal (const LDPair &p, bool allow_placeholder) const;
std::set<unsigned int> logical_internal (const std::string &name, bool allow_placeholder) const;
std::set<unsigned int> logical_internal (const db::LayerProperties &p, bool allow_placeholder) const;
std::pair<bool, unsigned int> substitute_placeholder (const db::LayerProperties &p, unsigned int ph, db::Layout &layout);
bool is_placeholder (unsigned int l) const;
std::set<unsigned int> substitute_placeholder (const db::LayerProperties &p, const std::set<unsigned int> &ph, db::Layout &layout);
bool is_placeholder (const std::set<unsigned int> &l) const;
};
}