First steps: equipping the Connectivity object with soft connections

This commit is contained in:
Matthias Koefferlein 2024-03-10 23:35:56 +01:00
parent 230bacf725
commit 284a907ffb
12 changed files with 390 additions and 94 deletions

View File

@ -113,11 +113,20 @@ Connectivity::Connectivity (edge_connectivity_type ec)
// .. nothing yet ..
}
void
Connectivity::soft_connect (unsigned int la, unsigned int lb)
{
m_connected [la][lb] = -1;
m_connected [lb][la] = 1;
m_all_layers.insert (la);
m_all_layers.insert (lb);
}
void
Connectivity::connect (unsigned int la, unsigned int lb)
{
m_connected [la].insert (lb);
m_connected [lb].insert (la);
m_connected [la][lb] = 0;
m_connected [lb][la] = 0;
m_all_layers.insert (la);
m_all_layers.insert (lb);
}
@ -125,7 +134,7 @@ Connectivity::connect (unsigned int la, unsigned int lb)
void
Connectivity::connect (unsigned int l)
{
m_connected [l].insert (l);
m_connected [l][l] = 0;
m_all_layers.insert (l);
}
@ -141,6 +150,12 @@ Connectivity::connect (const db::DeepLayer &la, const db::DeepLayer &lb)
connect (la.layer (), lb.layer ());
}
void
Connectivity::soft_connect (const db::DeepLayer &la, const db::DeepLayer &lb)
{
soft_connect (la.layer (), lb.layer ());
}
Connectivity::global_nets_type s_empty_global_nets;
Connectivity::global_nets_iterator
@ -169,7 +184,16 @@ size_t
Connectivity::connect_global (unsigned int l, const std::string &gn)
{
size_t id = global_net_id (gn);
m_global_connections [l].insert (id);
m_global_connections [l][id] = 0;
m_all_layers.insert (l);
return id;
}
size_t
Connectivity::soft_connect_global (unsigned int l, const std::string &gn)
{
size_t id = global_net_id (gn);
m_global_connections [l][id] = -1;
m_all_layers.insert (l);
return id;
}
@ -180,6 +204,12 @@ Connectivity::connect_global (const db::DeepLayer &l, const std::string &gn)
return connect_global (l.layer (), gn);
}
size_t
Connectivity::soft_connect_global (const db::DeepLayer &l, const std::string &gn)
{
return soft_connect_global (l.layer (), gn);
}
const std::string &
Connectivity::global_net_name (size_t id) const
{
@ -208,13 +238,13 @@ Connectivity::global_nets () const
return m_global_net_names.size ();
}
Connectivity::layer_iterator
Connectivity::all_layer_iterator
Connectivity::begin_layers () const
{
return m_all_layers.begin ();
}
Connectivity::layer_iterator
Connectivity::all_layer_iterator
Connectivity::end_layers () const
{
return m_all_layers.end ();
@ -306,13 +336,19 @@ interaction_test (const db::Edge &a, const db::Edge &b, const db::unit_trans<C>
}
template <class T, class Trans>
bool Connectivity::interacts (const T &a, unsigned int la, const T &b, unsigned int lb, const Trans &trans) const
bool Connectivity::interacts (const T &a, unsigned int la, const T &b, unsigned int lb, const Trans &trans, int &soft) const
{
std::map<unsigned int, layers_type>::const_iterator i = m_connected.find (la);
if (i == m_connected.end () || i->second.find (lb) == i->second.end ()) {
if (i == m_connected.end ()) {
return false;
} else {
return interaction_test (a, b, trans, m_ec);
auto t = i->second.find (lb);
if (t == i->second.end () || ! interaction_test (a, b, trans, m_ec)) {
return false;
} else {
soft = t->second;
return true;
}
}
}
@ -321,7 +357,7 @@ bool Connectivity::interacts (const std::set<unsigned int> &la, const std::set<u
for (std::set<unsigned int>::const_iterator i = la.begin (); i != la.end (); ++i) {
db::Connectivity::layer_iterator je = end_connected (*i);
for (db::Connectivity::layer_iterator j = begin_connected (*i); j != je; ++j) {
if (lb.find (*j) != lb.end ()) {
if (lb.find (j->first) != lb.end ()) {
return true;
}
}
@ -335,7 +371,7 @@ bool Connectivity::interact (const db::Cell &a, const db::Cell &b) const
for (std::map<unsigned int, layers_type>::const_iterator i = m_connected.begin (); i != m_connected.end (); ++i) {
if (! a.bbox (i->first).empty ()) {
for (layers_type::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
if (! b.bbox (*j).empty ()) {
if (! b.bbox (j->first).empty ()) {
return true;
}
}
@ -353,7 +389,7 @@ bool Connectivity::interact (const db::Cell &a, const T &ta, const db::Cell &b,
if (! ba.empty ()) {
ba.transform (ta);
for (layers_type::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
db::Box bb = b.bbox (*j);
db::Box bb = b.bbox (j->first);
if (! bb.empty () && bb.transformed (tb).touches (ba)) {
return true;
}
@ -365,12 +401,12 @@ bool Connectivity::interact (const db::Cell &a, const T &ta, const db::Cell &b,
}
// explicit instantiations
template DB_PUBLIC bool Connectivity::interacts<db::NetShape> (const db::NetShape &a, unsigned int la, const db::NetShape &b, unsigned int lb, const db::UnitTrans &trans) const;
template DB_PUBLIC bool Connectivity::interacts<db::NetShape> (const db::NetShape &a, unsigned int la, const db::NetShape &b, unsigned int lb, const db::ICplxTrans &trans) const;
template DB_PUBLIC bool Connectivity::interacts<db::PolygonRef> (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::UnitTrans &trans) const;
template DB_PUBLIC bool Connectivity::interacts<db::PolygonRef> (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::ICplxTrans &trans) const;
template DB_PUBLIC bool Connectivity::interacts<db::Edge> (const db::Edge &a, unsigned int la, const db::Edge &b, unsigned int lb, const db::UnitTrans &trans) const;
template DB_PUBLIC bool Connectivity::interacts<db::Edge> (const db::Edge &a, unsigned int la, const db::Edge &b, unsigned int lb, const db::ICplxTrans &trans) const;
template DB_PUBLIC bool Connectivity::interacts<db::NetShape> (const db::NetShape &a, unsigned int la, const db::NetShape &b, unsigned int lb, const db::UnitTrans &trans, int &soft) const;
template DB_PUBLIC bool Connectivity::interacts<db::NetShape> (const db::NetShape &a, unsigned int la, const db::NetShape &b, unsigned int lb, const db::ICplxTrans &trans, int &soft) const;
template DB_PUBLIC bool Connectivity::interacts<db::PolygonRef> (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::UnitTrans &trans, int &soft) const;
template DB_PUBLIC bool Connectivity::interacts<db::PolygonRef> (const db::PolygonRef &a, unsigned int la, const db::PolygonRef &b, unsigned int lb, const db::ICplxTrans &trans, int &soft) const;
template DB_PUBLIC bool Connectivity::interacts<db::Edge> (const db::Edge &a, unsigned int la, const db::Edge &b, unsigned int lb, const db::UnitTrans &trans, int &soft) const;
template DB_PUBLIC bool Connectivity::interacts<db::Edge> (const db::Edge &a, unsigned int la, const db::Edge &b, unsigned int lb, const db::ICplxTrans &trans, int &soft) const;
template DB_PUBLIC bool Connectivity::interact<db::ICplxTrans> (const db::Cell &a, const db::ICplxTrans &ta, const db::Cell &b, const db::ICplxTrans &tb) const;
// ------------------------------------------------------------------------------
@ -496,7 +532,8 @@ public:
void add (const T *s1, unsigned int l1, const T *s2, unsigned int l2)
{
if (mp_conn->interacts (*s1, l1, *s2, l2, m_trans)) {
int soft; // @@@
if (mp_conn->interacts (*s1, l1, *s2, l2, m_trans, soft)) {
m_any = true;
}
}
@ -559,7 +596,7 @@ local_cluster<T>::interacts (const db::Cell &cell, const db::ICplxTrans &trans,
Connectivity::layer_iterator le = conn.end_connected (s->first);
for (Connectivity::layer_iterator l = conn.begin_connected (s->first); l != le; ++l) {
box += cell.bbox (*l);
box += cell.bbox (l->first); // @@@ soft connections?
}
if (! box.empty () && ! s->second.begin_touching (box.transformed (trans), bc).at_end ()) {
@ -933,7 +970,8 @@ struct cluster_building_receiver
if (m_separate_attributes && p1.second != p2.second) {
return;
}
if (! mp_conn->interacts (*s1, p1.first, *s2, p2.first)) {
int soft; // @@@
if (! mp_conn->interacts (*s1, p1.first, *s2, p2.first, soft)) {
return;
}
@ -996,12 +1034,12 @@ struct cluster_building_receiver
db::Connectivity::global_nets_iterator ge = mp_conn->end_global_connections (p.first);
for (db::Connectivity::global_nets_iterator g = mp_conn->begin_global_connections (p.first); g != ge; ++g) {
typename std::map<size_t, typename std::list<cluster_value>::iterator>::iterator icg = m_global_to_clusters.find (*g);
typename std::map<size_t, typename std::list<cluster_value>::iterator>::iterator icg = m_global_to_clusters.find (g->first); // @@@ soft connections
if (icg == m_global_to_clusters.end ()) {
ic->second->second.insert (*g);
m_global_to_clusters.insert (std::make_pair (*g, ic->second));
ic->second->second.insert (g->first); // @@@ soft connections?
m_global_to_clusters.insert (std::make_pair (g->first, ic->second)); // @@@ soft connections?
} else if (ic->second != icg->second) {
@ -1110,7 +1148,7 @@ local_clusters<T>::build_clusters (const db::Cell &cell, const db::Connectivity
attr_accessor<T> attr;
db::ShapeIterator::flags_type shape_flags = get_shape_flags<T> () ();
for (db::Connectivity::layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
for (db::Connectivity::all_layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
const db::Shapes &shapes = cell.shapes (*l);
for (db::Shapes::shape_iterator s = shapes.begin (shape_flags); ! s.at_end (); ++s) {
bs.insert (heap (*s), std::make_pair (*l, attr (*s)));
@ -1643,13 +1681,13 @@ private:
// reject the pair
bool any = false;
for (db::Connectivity::layer_iterator la = mp_conn->begin_layers (); la != mp_conn->end_layers () && ! any; ++la) {
for (db::Connectivity::all_layer_iterator la = mp_conn->begin_layers (); la != mp_conn->end_layers () && ! any; ++la) {
db::box_convert<db::CellInst, true> bca (*mp_layout, *la);
box_type bb1 = i1.cell_inst ().bbox (bca).transformed (t1);
if (! bb1.empty ()) {
db::Connectivity::layer_iterator lbe = mp_conn->end_connected (*la);
for (db::Connectivity::layer_iterator lb = mp_conn->begin_connected (*la); lb != lbe && ! any; ++lb) {
db::box_convert<db::CellInst, true> bcb (*mp_layout, *lb);
db::box_convert<db::CellInst, true> bcb (*mp_layout, lb->first); // @@@ soft connections?
box_type bb2 = i2.cell_inst ().bbox (bcb).transformed (t2);
any = bb1.touches (bb2);
}
@ -2186,6 +2224,10 @@ hier_clusters<T>::propagate_cluster_inst (const db::Layout &layout, const db::Ce
if (child_cc.is_root (id)) {
std::set<std::pair<db::cell_index_type, ClusterInstance> > seen; // to avoid duplicate connections
if (! with_self) {
// don't include the instance we came up with initially
seen.insert (std::make_pair (cell.cell_index (), ci));
}
const db::Cell &child_cell = layout.cell (ci.inst_cell_index ());
for (db::Cell::parent_inst_iterator pi = child_cell.begin_parent_insts (); ! pi.at_end (); ++pi) {
@ -2196,7 +2238,7 @@ hier_clusters<T>::propagate_cluster_inst (const db::Layout &layout, const db::Ce
for (db::CellInstArray::iterator pii = child_inst.begin (); ! pii.at_end (); ++pii) {
ClusterInstance ci2 (id, child_inst.cell_index (), child_inst.complex_trans (*pii), child_inst.prop_id ());
if ((with_self || cell.cell_index () != pi->parent_cell_index () || ci != ci2) && seen.find (std::make_pair (pi->parent_cell_index (), ci2)) == seen.end ()) {
if (seen.find (std::make_pair (pi->parent_cell_index (), ci2)) == seen.end ()) {
size_t id_dummy;

View File

@ -60,9 +60,11 @@ class DeepLayer;
class DB_PUBLIC Connectivity
{
public:
typedef std::set<unsigned int> layers_type;
typedef std::set<unsigned int> all_layers_type;
typedef all_layers_type::const_iterator all_layer_iterator;
typedef std::map<unsigned int, int> layers_type;
typedef layers_type::const_iterator layer_iterator;
typedef std::set<size_t> global_nets_type;
typedef std::map<unsigned int, int> global_nets_type;
typedef global_nets_type::const_iterator global_nets_iterator;
/**
@ -101,11 +103,26 @@ public:
*/
void connect (unsigned int la, unsigned int lb);
/**
* @brief Adds inter-layer connectivity of the soft type
*
* Soft connections are directed and are reported during "interacts"
* by the "soft" output argument. "la" is the "upper" layer and "lb" is the lower layer.
*/
void soft_connect (unsigned int la, unsigned int lb);
/**
* @brief Adds a connection to a global net
*/
size_t connect_global (unsigned int l, const std::string &gn);
/**
* @brief Adds a soft connection to a global net
*
* The global net is always the "lower" layer.
*/
size_t soft_connect_global (unsigned int l, const std::string &gn);
/**
* @brief Adds intra-layer connectivity for layer l
* This is a convenience method that takes a db::DeepLayer object.
@ -120,11 +137,28 @@ public:
*/
void connect (const db::DeepLayer &la, const db::DeepLayer &lb);
/**
* @brief Adds inter-layer connectivity
* This is a convenience method that takes a db::DeepLayer object.
* It is assumed that all those layers originate from the same deep shape store.
*
* Soft connections are directed and are reported during "interacts"
* by the "soft" output argument. "la" is the "upper" layer and "lb" is the lower layer.
*/
void soft_connect (const db::DeepLayer &la, const db::DeepLayer &lb);
/**
* @brief Adds a connection to a global net
*/
size_t connect_global (const db::DeepLayer &la, const std::string &gn);
/**
* @brief Adds a soft connection to a global net
*
* The global net is always the "lower" layer.
*/
size_t soft_connect_global (const db::DeepLayer &la, const std::string &gn);
/**
* @brief Gets the global net name per ID
*/
@ -143,15 +177,19 @@ public:
/**
* @brief Begin iterator for the layers involved
*/
layer_iterator begin_layers () const;
all_layer_iterator begin_layers () const;
/**
* @brief End iterator for the layers involved
*/
layer_iterator end_layers () const;
all_layer_iterator end_layers () const;
/**
* @brief Begin iterator for the layers connected to a specific layer
*
* The iterator returned is over a map of target layers and soft mode
* (an int, being 0 for a hard connection, +1 for an upward soft connection
* and -1 for a downward soft connection).
*/
layer_iterator begin_connected (unsigned int layer) const;
@ -162,6 +200,10 @@ public:
/**
* @brief Begin iterator for the global connections for a specific layer
*
* The iterator returned is over a map of global net ID and soft mode
* (an int, being 0 for a hard connection, +1 for an upward soft connection
* and -1 for a downward soft connection).
*/
global_nets_iterator begin_global_connections (unsigned int layer) const;
@ -175,17 +217,21 @@ public:
*
* This method accepts a transformation. This transformation is applied
* to the b shape before checking against a.
*
* The "soft" output argument will deliver the soft mode that applies
* to the connection - 0: hard connection, -1: a is the lower layer, +1: a is
* the upper layer.
*/
template <class T, class Trans>
bool interacts (const T &a, unsigned int la, const T &b, unsigned int lb, const Trans &trans) const;
bool interacts (const T &a, unsigned int la, const T &b, unsigned int lb, const Trans &trans, int &soft) const;
/**
* @brief Returns true, if the given shapes on the given layers interact
*/
template <class T>
bool interacts (const T &a, unsigned int la, const T &b, unsigned int lb) const
bool interacts (const T &a, unsigned int la, const T &b, unsigned int lb, int &soft) const
{
return interacts (a, la, b, lb, UnitTrans ());
return interacts (a, la, b, lb, UnitTrans (), soft);
}
/**
@ -195,17 +241,21 @@ public:
/**
* @brief Returns true, if two cells basically (without considering transformation) interact
*
* This is a pretty basic check based on the cell's bounding boxes
*/
bool interact (const db::Cell &a, const db::Cell &b) const;
/**
* @brief Returns true, if two cells with the given transformations interact
*
* This is a pretty basic check based on the cell's bounding boxes
*/
template <class T>
bool interact (const db::Cell &a, const T &ta, const db::Cell &b, const T &tb) const;
private:
layers_type m_all_layers;
all_layers_type m_all_layers;
std::map<unsigned int, layers_type> m_connected;
std::vector<std::string> m_global_net_names;
std::map<unsigned int, global_nets_type> m_global_connections;

View File

@ -298,6 +298,26 @@ void LayoutToNetlist::connect_impl (const db::ShapeCollection &a, const db::Shap
m_conn.connect (dla.layer (), dlb.layer ());
}
void LayoutToNetlist::soft_connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b)
{
reset_extracted ();
if (! is_persisted (a)) {
register_layer (a);
}
if (! is_persisted (b)) {
register_layer (b);
}
// we need to keep a reference, so we can safely delete the region
db::DeepLayer dla = deep_layer_of (a);
db::DeepLayer dlb = deep_layer_of (b);
m_dlrefs.insert (dla);
m_dlrefs.insert (dlb);
m_conn.soft_connect (dla.layer (), dlb.layer ());
}
size_t LayoutToNetlist::connect_global_impl (const db::ShapeCollection &l, const std::string &gn)
{
reset_extracted ();
@ -313,6 +333,21 @@ size_t LayoutToNetlist::connect_global_impl (const db::ShapeCollection &l, const
return m_conn.connect_global (dl.layer (), gn);
}
size_t LayoutToNetlist::soft_connect_global_impl (const db::ShapeCollection &l, const std::string &gn)
{
reset_extracted ();
if (! is_persisted (l)) {
register_layer (l);
}
// we need to keep a reference, so we can safely delete the region
db::DeepLayer dl = deep_layer_of (l);
m_dlrefs.insert (dl);
return m_conn.soft_connect_global (dl.layer (), gn);
}
const std::string &LayoutToNetlist::global_net_name (size_t id) const
{
return m_conn.global_net_name (id);
@ -360,6 +395,24 @@ void LayoutToNetlist::join_nets (const tl::GlobPattern &cell, const std::set<std
m_joined_nets_per_cell.push_back (std::make_pair (cell, gp));
}
// @@@
static bool check_many_pins (const db::Netlist *netlist)
{
bool ok = true;
for (auto c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
const db::Circuit &circuit = *c;
for (auto n = circuit.begin_nets (); n != circuit.end_nets (); ++n) {
const db::Net &net = *n;
if (net.pin_count () > 1) {
ok = false;
tl::error << "Many pins on net " << net.expanded_name () << " in circuit " << circuit.name ();
}
}
}
return ok;
}
// @@@
void LayoutToNetlist::extract_netlist ()
{
if (m_netlist_extracted) {
@ -371,7 +424,10 @@ void LayoutToNetlist::extract_netlist ()
netex.set_include_floating_subcircuits (m_include_floating_subcircuits);
netex.extract_nets (dss (), m_layout_index, m_conn, *mp_netlist, m_net_clusters);
// @@@ NOTE: can we have multiple pins on a net? Will this happen later maybe?
// @@@ do_soft_connections ()
do_join_nets ();
tl_assert (check_many_pins (mp_netlist.get ())); // @@@
if (tl::verbosity () >= 41) {
MemStatisticsCollector m (false);
@ -870,7 +926,7 @@ LayoutToNetlist::create_layermap (db::Layout &target_layout, int ln) const
std::set<unsigned int> layers_to_copy;
const db::Connectivity &conn = connectivity ();
for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
for (db::Connectivity::all_layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
layers_to_copy.insert (*layer);
}

View File

@ -494,6 +494,39 @@ public:
connect_impl (b, a);
}
/**
* @brief Defines an inter-layer soft connection for the given layers.
* The conditions mentioned with intra-layer "connect" apply for this method too.
* The "a" layer is the "upper" and the "b" layer the "lower" layer of the
* soft connection.
*/
void soft_connect (const db::Region &a, const db::Region &b)
{
soft_connect_impl (a, b);
}
/**
* @brief Defines an inter-layer connection for the given layers.
* As one layer is a texts layer, this connection will basically add net labels.
* The "a" layer is the "upper" and the "b" layer the "lower" layer of the
* soft connection.
*/
void soft_connect (const db::Region &a, const db::Texts &b)
{
soft_connect_impl (a, b);
}
/**
* @brief Defines an inter-layer connection for the given layers.
* As one layer is a texts layer, this connection will basically add net labels.
* The "a" layer is the "upper" and the "b" layer the "lower" layer of the
* soft connection.
*/
void soft_connect (const db::Texts &a, const db::Region &b)
{
soft_connect_impl (b, a);
}
/**
* @brief Connects the given layer with a global net with the given name
* Returns the global net ID
@ -512,6 +545,26 @@ public:
return connect_global_impl (l, gn);
}
/**
* @brief Soft-connects the given layer with a global net with the given name
* Returns the global net ID.
* The global layer is the "lower" layer of the soft connection.
*/
size_t soft_connect_global (const db::Region &l, const std::string &gn)
{
return soft_connect_global_impl (l, gn);
}
/**
* @brief Soft-connects the given text layer with a global net with the given name
* Returns the global net ID.
* The global layer is the "lower" layer of the soft connection.
*/
size_t soft_connect_global (const db::Texts &l, const std::string &gn)
{
return soft_connect_global_impl (l, gn);
}
/**
* @brief Gets the global net name for a given global net ID
*/
@ -1035,6 +1088,8 @@ private:
db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector<const db::Net *> *nets, bool with_device_cells);
void connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b);
size_t connect_global_impl (const db::ShapeCollection &l, const std::string &gn);
void soft_connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b);
size_t soft_connect_global_impl (const db::ShapeCollection &l, const std::string &gn);
bool is_persisted_impl (const db::ShapeCollection &coll) const;
void do_join_nets (db::Circuit &c, const std::vector<Net *> &nets);
void do_join_nets ();

View File

@ -39,7 +39,9 @@ namespace l2n_std_format
DB_PUBLIC std::string LongKeys::layer_key ("layer");
DB_PUBLIC std::string LongKeys::class_key ("class");
DB_PUBLIC std::string LongKeys::connect_key ("connect");
DB_PUBLIC std::string LongKeys::softconnect_key ("softconnect");
DB_PUBLIC std::string LongKeys::global_key ("global");
DB_PUBLIC std::string LongKeys::softglobal_key ("softglobal");
DB_PUBLIC std::string LongKeys::circuit_key ("circuit");
DB_PUBLIC std::string LongKeys::net_key ("net");
DB_PUBLIC std::string LongKeys::name_key ("name");
@ -72,7 +74,9 @@ namespace l2n_std_format
DB_PUBLIC std::string ShortKeys::layer_key ("L");
DB_PUBLIC std::string ShortKeys::class_key ("K");
DB_PUBLIC std::string ShortKeys::connect_key ("C");
DB_PUBLIC std::string ShortKeys::softconnect_key ("CS");
DB_PUBLIC std::string ShortKeys::global_key ("G");
DB_PUBLIC std::string ShortKeys::softglobal_key ("GS");
DB_PUBLIC std::string ShortKeys::circuit_key ("X");
DB_PUBLIC std::string ShortKeys::net_key ("N");
DB_PUBLIC std::string ShortKeys::name_key ("I");

View File

@ -66,11 +66,14 @@ namespace db
*
* [connect]:
* connect(<layer1> <name> ...) - connects layer1 with the following layers [short key: C]
* softconnect(<upper> <lower> ...)
* - specifies soft connection between lower and upper layer [short key: CS]
*
* [global]:
* global(<layer> <net-name> ...)
* - connects the shapes of the layer with the given global
* nets [short key: G]
* - connects the shapes of the layer with the given global nets [short key: G]
* softglobal(<layer> <net-name> ...)
* - soft-connects the shapes of the layer with the given global net [shoft key: GS]
*
* [circuit]:
* circuit(<name> [circuit-def]) - circuit (cell) [short key: X]
@ -222,7 +225,9 @@ namespace l2n_std_format
static std::string layer_key;
static std::string class_key;
static std::string connect_key;
static std::string softconnect_key;
static std::string global_key;
static std::string softglobal_key;
static std::string circuit_key;
static std::string net_key;
static std::string name_key;
@ -261,7 +266,9 @@ namespace l2n_std_format
static std::string layer_key;
static std::string class_key;
static std::string connect_key;
static std::string softconnect_key;
static std::string global_key;
static std::string softglobal_key;
static std::string circuit_key;
static std::string net_key;
static std::string name_key;

View File

@ -462,12 +462,17 @@ void LayoutToNetlistStandardReader::read_netlist (db::Netlist *netlist, db::Layo
}
br.done ();
} else if (l2n && (test (skeys::message_key) || test (lkeys::message_key))) {
} else if (l2n && (test (skeys::softconnect_key) || test (lkeys::softconnect_key))) {
db::LogEntryData data;
read_message_entry (data);
l2n->log_entry (data);
Brace br (this);
std::string l1;
read_word_or_quoted (l1);
while (br) {
std::string l2;
read_word_or_quoted (l2);
l2n->soft_connect (layer_by_name (l2n, l1), layer_by_name (l2n, l2));
}
br.done ();
} else if (l2n && (test (skeys::global_key) || test (lkeys::global_key))) {
@ -481,6 +486,25 @@ void LayoutToNetlistStandardReader::read_netlist (db::Netlist *netlist, db::Layo
}
br.done ();
} else if (l2n && (test (skeys::softglobal_key) || test (lkeys::softglobal_key))) {
Brace br (this);
std::string l1;
read_word_or_quoted (l1);
while (br) {
std::string g;
read_word_or_quoted (g);
l2n->soft_connect_global (layer_by_name (l2n, l1), g);
}
br.done ();
} else if (l2n && (test (skeys::message_key) || test (lkeys::message_key))) {
db::LogEntryData data;
read_message_entry (data);
l2n->log_entry (data);
} else if (test (skeys::circuit_key) || test (lkeys::circuit_key)) {
Brace br (this);

View File

@ -351,7 +351,7 @@ void std_writer_impl<Keys>::write (bool nested, TokenizedOutput &stream, std::ma
if (! Keys::is_short ()) {
stream << endl << "# Mask layers" << endl;
}
for (db::Connectivity::layer_iterator l = mp_l2n->connectivity ().begin_layers (); l != mp_l2n->connectivity ().end_layers (); ++l) {
for (db::Connectivity::all_layer_iterator l = mp_l2n->connectivity ().begin_layers (); l != mp_l2n->connectivity ().end_layers (); ++l) {
TokenizedOutput out (stream, Keys::layer_key);
out << name_for_layer (mp_l2n, *l);
db::LayerProperties lp = ly->get_properties (*l);
@ -364,15 +364,32 @@ void std_writer_impl<Keys>::write (bool nested, TokenizedOutput &stream, std::ma
if (! Keys::is_short ()) {
stream << endl << "# Mask layer connectivity" << endl;
}
for (db::Connectivity::layer_iterator l = mp_l2n->connectivity ().begin_layers (); l != mp_l2n->connectivity ().end_layers (); ++l) {
for (db::Connectivity::all_layer_iterator l = mp_l2n->connectivity ().begin_layers (); l != mp_l2n->connectivity ().end_layers (); ++l) {
db::Connectivity::layer_iterator ce = mp_l2n->connectivity ().end_connected (*l);
db::Connectivity::layer_iterator cb = mp_l2n->connectivity ().begin_connected (*l);
if (cb != ce) {
TokenizedOutput out (stream, Keys::connect_key);
out << name_for_layer (mp_l2n, *l);
for (db::Connectivity::layer_iterator c = mp_l2n->connectivity ().begin_connected (*l); c != ce; ++c) {
out << name_for_layer (mp_l2n, *c);
bool any_soft = false;
{
TokenizedOutput out (stream, Keys::connect_key);
out << name_for_layer (mp_l2n, *l);
for (db::Connectivity::layer_iterator c = mp_l2n->connectivity ().begin_connected (*l); c != ce; ++c) {
if (c->second < 0) {
any_soft = true;
}
out << name_for_layer (mp_l2n, c->first);
}
}
// add soft connections in addition and as overrides to stay backward compatible with older versions
// (these will ignore these statements)
if (any_soft) {
TokenizedOutput out (stream, Keys::softconnect_key);
out << name_for_layer (mp_l2n, *l);
for (db::Connectivity::layer_iterator c = mp_l2n->connectivity ().begin_connected (*l); c != ce; ++c) {
if (c->second < 0) {
out << name_for_layer (mp_l2n, c->first);
}
}
}
m_progress.set (mp_stream->pos ());
}
@ -380,7 +397,7 @@ void std_writer_impl<Keys>::write (bool nested, TokenizedOutput &stream, std::ma
}
any = false;
for (db::Connectivity::layer_iterator l = mp_l2n->connectivity ().begin_layers (); l != mp_l2n->connectivity ().end_layers (); ++l) {
for (db::Connectivity::all_layer_iterator l = mp_l2n->connectivity ().begin_layers (); l != mp_l2n->connectivity ().end_layers (); ++l) {
db::Connectivity::global_nets_iterator ge = mp_l2n->connectivity ().end_global_connections (*l);
db::Connectivity::global_nets_iterator gb = mp_l2n->connectivity ().begin_global_connections (*l);
@ -391,10 +408,27 @@ void std_writer_impl<Keys>::write (bool nested, TokenizedOutput &stream, std::ma
}
any = true;
}
TokenizedOutput out (stream, Keys::global_key);
out << name_for_layer (mp_l2n, *l);
for (db::Connectivity::global_nets_iterator g = gb; g != ge; ++g) {
out << tl::to_word_or_quoted_string (mp_l2n->connectivity ().global_net_name (*g));
bool any_soft = false;
{
TokenizedOutput out (stream, Keys::global_key);
out << name_for_layer (mp_l2n, *l);
for (db::Connectivity::global_nets_iterator g = gb; g != ge; ++g) {
if (g->second < 0) {
any_soft = true;
}
out << tl::to_word_or_quoted_string (mp_l2n->connectivity ().global_net_name (g->first));
}
}
// add soft connections in addition and as overrides to stay backward compatible with older versions
// (these will ignore these statements)
if (any_soft) {
TokenizedOutput out (stream, Keys::softglobal_key);
out << name_for_layer (mp_l2n, *l);
for (db::Connectivity::global_nets_iterator g = gb; g != ge; ++g) {
if (g->second < 0) {
out << tl::to_word_or_quoted_string (mp_l2n->connectivity ().global_net_name (g->first));
}
}
}
m_progress.set (mp_stream->pos ());
}
@ -634,7 +668,7 @@ void std_writer_impl<Keys>::write (TokenizedOutput &stream, const db::Net &net,
reset_geometry_ref ();
for (db::Connectivity::layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
for (db::Connectivity::all_layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
db::cell_index_type cci = circuit->cell_index ();
db::cell_index_type prev_ci = cci;
@ -757,7 +791,7 @@ void std_writer_impl<Keys>::write (TokenizedOutput &stream, const db::DeviceAbst
bool any = false;
for (db::Connectivity::layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
for (db::Connectivity::all_layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
size_t cid = device_abstract.cluster_id_for_terminal (t->id ());
if (cid == 0) {

View File

@ -36,6 +36,23 @@ static std::string l2s (db::Connectivity::layer_iterator b, db::Connectivity::la
{
std::string s;
for (db::Connectivity::layer_iterator i = b; i != e; ++i) {
if (! s.empty ()) {
s += ",";
}
s += tl::to_string (i->first);
if (i->second < 0) {
s += "-S";
} else if (i->second > 0) {
s += "+S";
}
}
return s;
}
static std::string al2s (db::Connectivity::all_layer_iterator b, db::Connectivity::all_layer_iterator e)
{
std::string s;
for (db::Connectivity::all_layer_iterator i = b; i != e; ++i) {
if (! s.empty ()) {
s += ",";
}
@ -51,7 +68,12 @@ static std::string gn2s (db::Connectivity::global_nets_iterator b, db::Connectiv
if (! s.empty ()) {
s += ",";
}
s += tl::to_string (*i);
s += tl::to_string (i->first);
if (i->second < 0) {
s += "-S";
} else if (i->second > 0) {
s += "+S";
}
}
return s;
}
@ -60,15 +82,15 @@ TEST(1_Connectivity)
{
db::Connectivity conn;
EXPECT_EQ (l2s (conn.begin_layers (), conn.end_layers ()), "");
EXPECT_EQ (al2s (conn.begin_layers (), conn.end_layers ()), "");
conn.connect (0);
EXPECT_EQ (l2s (conn.begin_layers (), conn.end_layers ()), "0");
EXPECT_EQ (al2s (conn.begin_layers (), conn.end_layers ()), "0");
EXPECT_EQ (l2s (conn.begin_connected (0), conn.end_connected (0)), "0");
EXPECT_EQ (l2s (conn.begin_connected (1), conn.end_connected (1)), "");
conn.connect (0, 1);
EXPECT_EQ (l2s (conn.begin_layers (), conn.end_layers ()), "0,1");
EXPECT_EQ (al2s (conn.begin_layers (), conn.end_layers ()), "0,1");
EXPECT_EQ (l2s (conn.begin_connected (0), conn.end_connected (0)), "0,1");
EXPECT_EQ (l2s (conn.begin_connected (1), conn.end_connected (1)), "0");
@ -121,18 +143,19 @@ TEST(2_ShapeInteractions)
db::ICplxTrans t3 (db::Trans (db::Vector (0, 2000)));
db::PolygonRef ref3 (poly.transformed (t3), repo);
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 0), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t2), true); // t2*ref1 == ref2
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 1), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 1, t2), true);
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 0), true);
EXPECT_EQ (conn.interacts (ref1, 1, ref1, 0, t2), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 0), false);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t3), false); // t3*ref1 == ref3
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 1), false);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 1, t3), false);
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 2), false);
EXPECT_EQ (conn.interacts (ref1, 1, ref1, 2, t2), false);
int soft = std::numeric_limits<int>::max ();
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 0, soft), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t2, soft), true); // t2*ref1 == ref2
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 1, soft), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 1, t2, soft), true);
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 0, soft), true);
EXPECT_EQ (conn.interacts (ref1, 1, ref1, 0, t2, soft), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 0, soft), false);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t3, soft), false); // t3*ref1 == ref3
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 1, soft), false);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 1, t3, soft), false);
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 2, soft), false);
EXPECT_EQ (conn.interacts (ref1, 1, ref1, 2, t2, soft), false);
}
TEST(2_ShapeInteractionsRealPolygon)
@ -154,20 +177,21 @@ TEST(2_ShapeInteractionsRealPolygon)
db::ICplxTrans t4 (db::Trans (db::Vector (0, 1500)));
db::PolygonRef ref4 (poly.transformed (t4), repo);
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 0), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t2), true); // t2*ref1 == ref2
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 1), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 1, t2), true);
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 0), true);
EXPECT_EQ (conn.interacts (ref1, 1, ref1, 0, t2), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 0), false);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t3), false);
EXPECT_EQ (conn.interacts (ref1, 0, ref4, 0), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t4), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 1), false);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 1, t3), false);
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 2), false);
EXPECT_EQ (conn.interacts (ref1, 1, ref1, 2, t2), false);
int soft = std::numeric_limits<int>::max ();
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 0, soft), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t2, soft), true); // t2*ref1 == ref2
EXPECT_EQ (conn.interacts (ref1, 0, ref2, 1, soft), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 1, t2, soft), true);
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 0, soft), true);
EXPECT_EQ (conn.interacts (ref1, 1, ref1, 0, t2, soft), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 0, soft), false);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t3, soft), false);
EXPECT_EQ (conn.interacts (ref1, 0, ref4, 0, soft), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 0, t4, soft), true);
EXPECT_EQ (conn.interacts (ref1, 0, ref3, 1, soft), false);
EXPECT_EQ (conn.interacts (ref1, 0, ref1, 1, t3, soft), false);
EXPECT_EQ (conn.interacts (ref1, 1, ref2, 2, soft), false);
EXPECT_EQ (conn.interacts (ref1, 1, ref1, 2, t2, soft), false);
}
TEST(10_LocalClusterBasic)
@ -286,7 +310,7 @@ template <class T>
static std::string local_cluster_to_string (const db::local_cluster<T> &cluster, const db::Connectivity &conn)
{
std::string res;
for (db::Connectivity::layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
for (db::Connectivity::all_layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
for (typename db::local_cluster<T>::shape_iterator s = cluster.begin (*l); ! s.at_end (); ++s) {
if (! res.empty ()) {
res += ";";
@ -920,7 +944,7 @@ static void copy_cluster_shapes (const std::string *&attrs, db::Shapes &out, db:
const db::local_cluster<db::PolygonRef> &lc = clusters.cluster_by_id (cluster_id);
// copy the shapes from this cell
for (db::Connectivity::layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
for (db::Connectivity::all_layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
for (db::local_cluster<db::PolygonRef>::shape_iterator s = lc.begin (*l); ! s.at_end (); ++s) {
db::Polygon poly = s->obj ().transformed (trans * db::ICplxTrans (s->trans ()));
out.insert (db::PolygonWithProperties (poly, cell_and_attr_pid > 0 ? cell_and_attr_pid : cell_pid));

View File

@ -100,7 +100,7 @@ size_t count_shapes (db::LayoutToNetlist *l2ndb, db::Net *net)
size_t n = 0;
const db::Connectivity &conn = l2ndb->connectivity ();
for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
for (db::Connectivity::all_layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
n += count_shapes (l2ndb, net, *layer);
}
@ -276,7 +276,7 @@ void NetInfoDialog::update_info_text ()
bool incomplete = false;
const db::Connectivity &conn = mp_l2ndb->connectivity ();
for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
for (db::Connectivity::all_layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
std::string l = layer_string (mp_l2ndb.get (), *layer);

View File

@ -306,7 +306,7 @@ NetlistBrowserDialog::probe_net (const db::DPoint &p, bool trace_path)
std::vector<db::Region *> regions;
const db::Connectivity &conn = l2ndb->connectivity ();
for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
for (db::Connectivity::all_layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
db::LayerProperties lp = l2ndb->internal_layout ()->get_properties (*layer);
if (! lp.is_null ()) {
db::Region *region = l2ndb->layer_by_index (*layer);

View File

@ -1421,7 +1421,7 @@ NetlistBrowserPage::adjust_view ()
size_t cluster_id = net->cluster_id ();
const db::Connectivity &conn = mp_database->connectivity ();
for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
for (db::Connectivity::all_layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
db::Box layer_bbox;
db::recursive_cluster_shape_iterator<db::NetShape> shapes (mp_database->net_clusters (), *layer, cell_index, cluster_id);
@ -1580,7 +1580,7 @@ NetlistBrowserPage::produce_highlights_for_net (const db::Net *net, size_t &n_ma
tl::Color fallback_color = make_valid_color (m_colorizer.marker_color ());
const db::Connectivity &conn = mp_database->connectivity ();
for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
for (db::Connectivity::all_layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
db::LayerProperties lp = layout->get_properties (*layer);
std::map<db::LayerProperties, lay::LayerPropertiesConstIterator>::const_iterator display = display_by_lp.find (lp);