/* KLayout Layout Viewer Copyright (C) 2006-2018 Matthias Koefferlein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "dbNetTracerIO.h" #include "dbTechnology.h" #include "tlClassRegistry.h" namespace db { std::string net_tracer_component_name () { return std::string ("connectivity"); } // ----------------------------------------------------------------------------------------- // NetTracerLayerExpressionInfo implementation NetTracerLayerExpressionInfo::NetTracerLayerExpressionInfo () : mp_a (0), mp_b (0), m_op (NetTracerLayerExpression::OPNone) { // .. nothing yet .. } NetTracerLayerExpressionInfo::~NetTracerLayerExpressionInfo () { delete mp_a; mp_a = 0; delete mp_b; mp_b = 0; } NetTracerLayerExpressionInfo::NetTracerLayerExpressionInfo (const NetTracerLayerExpressionInfo &other) : m_expression (other.m_expression), m_a (other.m_a), m_b (other.m_b), mp_a (0), mp_b (0), m_op (other.m_op) { if (other.mp_a) { mp_a = new NetTracerLayerExpressionInfo (*other.mp_a); } if (other.mp_b) { mp_b = new NetTracerLayerExpressionInfo (*other.mp_b); } } NetTracerLayerExpressionInfo & NetTracerLayerExpressionInfo::operator= (const NetTracerLayerExpressionInfo &other) { if (this != &other) { m_expression = other.m_expression; delete mp_a; mp_a = 0; delete mp_b; mp_b = 0; m_a = other.m_a; m_b = other.m_b; m_op = other.m_op; if (other.mp_a) { mp_a = new NetTracerLayerExpressionInfo (*other.mp_a); } if (other.mp_b) { mp_b = new NetTracerLayerExpressionInfo (*other.mp_b); } } return *this; } void NetTracerLayerExpressionInfo::merge (NetTracerLayerExpression::Operator op, const NetTracerLayerExpressionInfo &other) { if (m_op != NetTracerLayerExpression::OPNone) { NetTracerLayerExpressionInfo *e = new NetTracerLayerExpressionInfo (*this); *this = NetTracerLayerExpressionInfo (); mp_a = e; } m_op = op; if (other.m_op == NetTracerLayerExpression::OPNone) { if (other.mp_a) { mp_b = new NetTracerLayerExpressionInfo (*other.mp_a); } else { m_b = other.m_a; } } else { mp_b = new NetTracerLayerExpressionInfo (other); } } NetTracerLayerExpressionInfo NetTracerLayerExpressionInfo::parse_add (tl::Extractor &ex) { NetTracerLayerExpressionInfo e = parse_mult (ex); while (true) { if (ex.test ("+")) { NetTracerLayerExpressionInfo ee = parse_mult (ex); e.merge (NetTracerLayerExpression::OPOr, ee); } else if (ex.test ("-")) { NetTracerLayerExpressionInfo ee = parse_mult (ex); e.merge (NetTracerLayerExpression::OPNot, ee); } else { break; } } return e; } NetTracerLayerExpressionInfo NetTracerLayerExpressionInfo::parse_mult (tl::Extractor &ex) { NetTracerLayerExpressionInfo e = parse_atomic (ex); while (true) { if (ex.test ("*")) { NetTracerLayerExpressionInfo ee = parse_atomic (ex); e.merge (NetTracerLayerExpression::OPAnd, ee); } else if (ex.test ("^")) { NetTracerLayerExpressionInfo ee = parse_atomic (ex); e.merge (NetTracerLayerExpression::OPXor, ee); } else { break; } } return e; } NetTracerLayerExpressionInfo NetTracerLayerExpressionInfo::parse_atomic (tl::Extractor &ex) { NetTracerLayerExpressionInfo e; if (ex.test ("(")) { e = parse_add (ex); ex.expect (")"); } else { e.m_a.read (ex); } return e; } NetTracerLayerExpressionInfo NetTracerLayerExpressionInfo::parse (tl::Extractor &ex) { const char *start = ex.skip (); NetTracerLayerExpressionInfo e = parse_add (ex); e.m_expression = std::string (start, ex.get () - start); return e; } NetTracerLayerExpressionInfo NetTracerLayerExpressionInfo::compile (const std::string &s) { tl::Extractor ex (s.c_str ()); const char *start = ex.skip (); NetTracerLayerExpressionInfo e = parse_add (ex); e.m_expression = std::string (start, ex.get () - start); ex.expect_end (); return e; } NetTracerLayerExpression * NetTracerLayerExpressionInfo::get_expr (const db::LayerProperties &lp, const db::Layout &layout, const NetTracerTechnologyComponent &tech, const std::set &used_symbols) const { for (NetTracerTechnologyComponent::const_symbol_iterator s = tech.begin_symbols (); s != tech.end_symbols (); ++s) { if (s->symbol ().log_equal (lp)) { std::set us = used_symbols; if (! us.insert (s->symbol ().to_string ()).second) { throw tl::Exception (tl::to_string (tr ("Recursive expression through symbol %s")), s->symbol ()); } return NetTracerLayerExpressionInfo::compile (s->expression ()).get (layout, tech, us); } } for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers (); ++l) { if ((*l).second->log_equal (lp)) { return new NetTracerLayerExpression ((*l).first); } } return new NetTracerLayerExpression (-1); } NetTracerLayerExpression * NetTracerLayerExpressionInfo::get (const db::Layout &layout, const NetTracerTechnologyComponent &tech) const { std::set us; return get (layout, tech, us); } NetTracerLayerExpression * NetTracerLayerExpressionInfo::get (const db::Layout &layout, const NetTracerTechnologyComponent &tech, const std::set &used_symbols) const { NetTracerLayerExpression *e = 0; if (mp_a) { e = mp_a->get (layout, tech, used_symbols); } else { e = get_expr (m_a, layout, tech, used_symbols); } if (m_op != NetTracerLayerExpression::OPNone) { if (mp_b) { e->merge (m_op, mp_b->get (layout, tech, used_symbols)); } else { e->merge (m_op, get_expr (m_b, layout, tech, used_symbols)); } } return e; } // ----------------------------------------------------------------------------------- // NetTracerConnectionInfo implementation NetTracerConnectionInfo::NetTracerConnectionInfo () { // .. nothing yet .. } NetTracerConnectionInfo::NetTracerConnectionInfo (const NetTracerLayerExpressionInfo &la, const NetTracerLayerExpressionInfo &lb) : m_la (la), m_via (), m_lb (lb) { // .. nothing yet .. } NetTracerConnectionInfo::NetTracerConnectionInfo (const NetTracerLayerExpressionInfo &la, const NetTracerLayerExpressionInfo &via, const NetTracerLayerExpressionInfo &lb) : m_la (la), m_via (via), m_lb (lb) { // .. nothing yet .. } static int get_layer_id (const NetTracerLayerExpressionInfo &e, const db::Layout &layout, const NetTracerTechnologyComponent &tech, NetTracerData *data) { std::auto_ptr expr_in (NetTracerLayerExpressionInfo::compile (e.to_string ()).get (layout, tech)); int l = expr_in->alias_for (); if (l < 0 && data) { l = data->find_symbol (e.to_string ()); if (l < 0) { return int (data->register_logical_layer (expr_in.release (), 0)); } } return l; } NetTracerConnection NetTracerConnectionInfo::get (const db::Layout &layout, const NetTracerTechnologyComponent &tech, NetTracerData &data) const { int la = get_layer_id (m_la, layout, tech, &data); int lb = get_layer_id (m_lb, layout, tech, &data); if (! m_via.to_string ().empty ()) { int via = get_layer_id (m_via, layout, tech, &data); return NetTracerConnection (la, via, lb); } else { return NetTracerConnection (la, lb); } } std::string NetTracerConnectionInfo::to_string () const { std::string res; res += m_la.to_string (); res += ","; res += m_via.to_string (); res += ","; res += m_lb.to_string (); return res; } void NetTracerConnectionInfo::parse (tl::Extractor &ex) { m_la = NetTracerLayerExpressionInfo::parse (ex); ex.expect (","); m_via = NetTracerLayerExpressionInfo::parse (ex); ex.expect (","); m_lb = NetTracerLayerExpressionInfo::parse (ex); } // ----------------------------------------------------------------------------------- // NetTracerSymbolInfo implementation NetTracerSymbolInfo::NetTracerSymbolInfo () { // .. nothing yet .. } NetTracerSymbolInfo::NetTracerSymbolInfo (const db::LayerProperties &symbol, const std::string &expression) : m_symbol (symbol), m_expression (expression) { // .. nothing yet .. } std::string NetTracerSymbolInfo::to_string () const { std::string res; res += m_symbol.to_string (); res += "="; res += tl::to_quoted_string(m_expression); return res; } void NetTracerSymbolInfo::parse (tl::Extractor &ex) { m_symbol.read (ex); ex.expect ("="); ex.read_word_or_quoted (m_expression); } // ----------------------------------------------------------------------------------- // Net implementation Net::Net () : m_dbu (0.001), m_incomplete (true), m_trace_path (false) { // .. nothing yet .. } Net::Net (const NetTracer &tracer, const db::ICplxTrans &trans, const db::Layout &layout, db::cell_index_type cell_index, const std::string &layout_filename, const std::string &layout_name, const NetTracerData &data) : m_name (tracer.name ()), m_incomplete (tracer.incomplete ()), m_trace_path (false) { m_dbu = layout.dbu (); m_top_cell_name = layout.cell_name (cell_index); m_layout_filename = layout_filename; m_layout_name = layout_name; size_t n = 0; for (NetTracer::iterator s = tracer.begin (); s != tracer.end (); ++s) { ++n; } m_net_shapes.reserve (n); for (NetTracer::iterator s = tracer.begin (); s != tracer.end (); ++s) { // TODO: should reset propery ID: tl::ident_map pm; db::Shape new_shape = m_shapes.insert (s->shape (), trans, pm); m_net_shapes.push_back (*s); m_net_shapes.back ().shape (new_shape); if (m_cell_names.find (s->cell_index ()) == m_cell_names.end ()) { m_cell_names.insert (std::make_pair (s->cell_index (), layout.cell_name (s->cell_index ()))); } if (m_layers.find (s->layer ()) == m_layers.end ()) { unsigned int l = s->layer (); db::LayerProperties lp; db::LayerProperties lprep; if (layout.is_valid_layer (l)) { lp = layout.get_properties (l); lprep = lp; } else { int lrep = data.expression (l).representative_layer (); if (layout.is_valid_layer (lrep)) { lprep = layout.get_properties (lrep); } for (std::map::const_iterator sy = data.symbols ().begin (); sy != data.symbols ().end (); ++sy) { if (sy->second == l) { tl::Extractor ex (sy->first.c_str ()); lp.read (ex); break; } } } define_layer (l, lp, lprep); } } } std::vector Net::export_net (db::Layout &layout, db::Cell &export_cell) { std::vector new_layers; std::map layer_map; for (iterator net_shape = begin (); net_shape != end (); ++net_shape) { if (net_shape->is_pseudo ()) { continue; } std::map::const_iterator lm = layer_map.find (net_shape->layer ()); if (lm == layer_map.end ()) { int layer_index = -1; for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers (); ++l) { if ((*l).second->log_equal (representative_layer_for (net_shape->layer ()))) { layer_index = int ((*l).first); break; } } if (layer_index < 0) { layer_index = int (layout.insert_layer (representative_layer_for (net_shape->layer ()))); new_layers.push_back (layer_index); } lm = layer_map.insert (std::make_pair (net_shape->layer (), (unsigned int)layer_index)).first; } tl::ident_map pm; export_cell.shapes (lm->second).insert (net_shape->shape (), db::ICplxTrans (net_shape->trans ()), pm); } return new_layers; } const std::string & Net::cell_name (db::cell_index_type cell_index) const { std::map ::const_iterator cn = m_cell_names.find (cell_index); if (cn != m_cell_names.end ()) { return cn->second; } else { static std::string n; return n; } } db::LayerProperties Net::representative_layer_for (unsigned int log_layer) const { std::map >::const_iterator l = m_layers.find (log_layer); if (l != m_layers.end ()) { return l->second.second; } else { return db::LayerProperties (); } } db::LayerProperties Net::layer_for (unsigned int log_layer) const { std::map >::const_iterator l = m_layers.find (log_layer); if (l != m_layers.end ()) { return l->second.first; } else { return db::LayerProperties (); } } void Net::define_layer (unsigned int l, const db::LayerProperties &lp, const db::LayerProperties &lp_representative) { m_layers.insert (std::make_pair (l, std::make_pair (lp, lp_representative))); } // ----------------------------------------------------------------------------------- // NetTracerTechnologyComponent implementation NetTracerTechnologyComponent::NetTracerTechnologyComponent () : db::TechnologyComponent (net_tracer_component_name (), tl::to_string (tr ("Connectivity"))) { // .. nothing yet .. } NetTracerTechnologyComponent::NetTracerTechnologyComponent (const NetTracerTechnologyComponent &d) : db::TechnologyComponent (net_tracer_component_name (), tl::to_string (tr ("Connectivity"))) { m_connections = d.m_connections; m_symbols = d.m_symbols; } NetTracerData NetTracerTechnologyComponent::get_tracer_data (const db::Layout &layout) const { // test run on the expressions to verify their syntax int n = 1; for (NetTracerTechnologyComponent::const_iterator c = begin (); c != end (); ++c, ++n) { if (c->layer_a ().to_string ().empty ()) { throw tl::Exception (tl::to_string (tr ("Missing first layer specification on connectivity specification #%d")), n); } if (c->layer_b ().to_string ().empty ()) { throw tl::Exception (tl::to_string (tr ("Missing second layer specification on connectivity specification #%d")), n); } } n = 1; for (NetTracerTechnologyComponent::const_symbol_iterator s = begin_symbols (); s != end_symbols (); ++s, ++n) { if (s->symbol ().to_string ().empty ()) { throw tl::Exception (tl::to_string (tr ("Missing symbol name on symbol specification #%d")), n); } if (s->expression ().empty ()) { throw tl::Exception (tl::to_string (tr ("Missing expression on symbol specification #%d")), n); } try { std::auto_ptr expr_in (NetTracerLayerExpressionInfo::compile (s->expression ()).get (layout, *this)); } catch (tl::Exception &ex) { throw tl::Exception (tl::to_string (tr ("Error compiling expression '%s' (symbol #%d): %s")), s->expression (), n, ex.msg ()); } } NetTracerData data; // register a logical layer for each original one as alias and one for each expression with a new ID for (db::NetTracerTechnologyComponent::const_symbol_iterator s = begin_symbols (); s != end_symbols (); ++s) { db::NetTracerLayerExpression *expr = db::NetTracerLayerExpressionInfo::compile (s->expression ()).get (layout, *this); data.register_logical_layer (expr, s->symbol ().to_string ().c_str ()); } for (db::NetTracerTechnologyComponent::const_iterator c = begin (); c != end (); ++c) { data.add_connection (c->get (layout, *this, data)); } return data; } }