mirror of https://github.com/KLayout/klayout.git
WIP: debugging, tests.
This commit is contained in:
parent
bc10bb6b14
commit
f83cd61843
|
|
@ -373,7 +373,7 @@ PropertiesRepository::prop_name_id (const tl::Variant &name)
|
|||
}
|
||||
}
|
||||
|
||||
property_names_id_type
|
||||
property_values_id_type
|
||||
PropertiesRepository::prop_value_id (const tl::Variant &value)
|
||||
{
|
||||
tl::MutexLocker locker (&m_lock);
|
||||
|
|
@ -383,9 +383,9 @@ PropertiesRepository::prop_value_id (const tl::Variant &value)
|
|||
m_property_values_heap.push_back (value);
|
||||
const tl::Variant &new_value = m_property_values_heap.back ();
|
||||
m_propvalues.insert (&new_value);
|
||||
return property_names_id_type (&new_value);
|
||||
return property_values_id_type (&new_value);
|
||||
} else {
|
||||
return property_names_id_type (*pi);
|
||||
return property_values_id_type (*pi);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ public:
|
|||
* This method will assign a new ID to the given value if required and
|
||||
* return the ID associated with it.
|
||||
*/
|
||||
property_names_id_type prop_value_id (const tl::Variant &name);
|
||||
property_values_id_type prop_value_id (const tl::Variant &name);
|
||||
|
||||
/**
|
||||
* @brief Get the ID for a name
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "dbRegionProcessors.h"
|
||||
#include "dbCompoundOperation.h"
|
||||
#include "dbPolygonNeighborhood.h"
|
||||
#include "dbPropertiesRepository.h"
|
||||
|
||||
namespace pex
|
||||
{
|
||||
|
|
@ -121,10 +122,11 @@ class ViaAggregationVisitor
|
|||
: public db::PolygonNeighborhoodVisitor
|
||||
{
|
||||
public:
|
||||
ViaAggregationVisitor (const RExtractorTechVia *via_tech, std::vector<std::pair<double, db::Point> > *conductances, double dbu)
|
||||
: mp_via_tech (via_tech), mp_conductances (conductances), m_dbu (dbu)
|
||||
ViaAggregationVisitor (const RExtractorTechVia *via_tech, double dbu)
|
||||
: mp_via_tech (via_tech), m_dbu (dbu)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
// this is just for consistency - we actually do not produce output
|
||||
set_result_type (db::CompoundRegionCheckOperationNode::Region);
|
||||
}
|
||||
|
||||
virtual void neighbors (const db::Layout * /*layout*/, const db::Cell * /*cell*/, const db::PolygonWithProperties &polygon, const neighbors_type &neighbors)
|
||||
|
|
@ -145,15 +147,44 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
mp_conductances->push_back (std::make_pair (c, polygon.box ().center ()));
|
||||
db::PropertiesSet ps;
|
||||
ps.insert (prop_name_id, tl::Variant (c));
|
||||
|
||||
output_polygon (db::PolygonWithProperties (polygon, db::properties_id (ps)));
|
||||
}
|
||||
|
||||
static db::property_names_id_type prop_name_id;
|
||||
|
||||
private:
|
||||
const RExtractorTechVia *mp_via_tech;
|
||||
std::vector<std::pair<double, db::Point> > *mp_conductances;
|
||||
db::property_names_id_type m_prop_name_id;
|
||||
double m_dbu;
|
||||
};
|
||||
|
||||
db::property_names_id_type ViaAggregationVisitor::prop_name_id = db::property_names_id (tl::Variant ());
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
RNetExtractor::create_via_port (const pex::RExtractorTechVia &tech,
|
||||
double conductance,
|
||||
const db::Polygon &poly,
|
||||
unsigned int &port_index,
|
||||
std::map<unsigned int, std::vector<ViaPort> > &vias,
|
||||
RNetwork &rnetwork)
|
||||
{
|
||||
RNode *a = rnetwork.create_node (RNode::Internal, port_index++);
|
||||
RNode *b = rnetwork.create_node (RNode::Internal, port_index++);
|
||||
|
||||
db::CplxTrans to_um (m_dbu);
|
||||
db::Box box = poly.box ();
|
||||
b->location = a->location = to_um * box;
|
||||
|
||||
rnetwork.create_element (conductance, a, b);
|
||||
|
||||
vias[tech.bottom_conductor].push_back (ViaPort (box.center (), a));
|
||||
vias[tech.top_conductor].push_back (ViaPort (box.center (), b));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -162,7 +193,7 @@ RNetExtractor::create_via_ports (const RExtractorTech &tech,
|
|||
std::map<unsigned int, std::vector<ViaPort> > &vias,
|
||||
RNetwork &rnetwork)
|
||||
{
|
||||
std::vector<std::pair<double, db::Point> > via_conductances;
|
||||
unsigned int port_index = 0;
|
||||
|
||||
for (auto v = tech.vias.begin (); v != tech.vias.end (); ++v) {
|
||||
|
||||
|
|
@ -171,8 +202,6 @@ RNetExtractor::create_via_ports (const RExtractorTech &tech,
|
|||
continue;
|
||||
}
|
||||
|
||||
via_conductances.clear ();
|
||||
|
||||
if (v->merge_distance > db::epsilon) {
|
||||
|
||||
// with merge, follow this scheme:
|
||||
|
|
@ -189,32 +218,23 @@ RNetExtractor::create_via_ports (const RExtractorTech &tech,
|
|||
children.push_back (new db::CompoundRegionOperationPrimaryNode ());
|
||||
children.push_back (new db::CompoundRegionOperationSecondaryNode (const_cast<db::Region *> (&g->second)));
|
||||
|
||||
ViaAggregationVisitor visitor (v.operator-> (), &via_conductances, m_dbu);
|
||||
ViaAggregationVisitor visitor (v.operator-> (), m_dbu);
|
||||
db::PolygonNeighborhoodCompoundOperationNode en_node (children, &visitor, 0);
|
||||
merged_vias.cop_to_region (en_node);
|
||||
auto aggregated = merged_vias.cop_to_region (en_node);
|
||||
|
||||
for (auto p = aggregated.begin (); ! p.at_end (); ++p) {
|
||||
double c = db::properties (p.prop_id ()).value (ViaAggregationVisitor::prop_name_id).to_double ();
|
||||
create_via_port (*v, c, *p, port_index, vias, rnetwork);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (auto p = g->second.begin_merged (); ! p.at_end (); ++p) {
|
||||
via_conductances.push_back (std::make_pair (via_conductance (*v, *p, m_dbu), p->box ().center ()));
|
||||
create_via_port (*v, via_conductance (*v, *p, m_dbu), *p, port_index, vias, rnetwork);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// create the via resistor elements
|
||||
unsigned int port_index = 0;
|
||||
for (auto vc = via_conductances.begin (); vc != via_conductances.end (); ++vc) {
|
||||
|
||||
RNode *a = rnetwork.create_node (RNode::Internal, port_index++);
|
||||
RNode *b = rnetwork.create_node (RNode::Internal, port_index++);
|
||||
|
||||
rnetwork.create_element (vc->first, a, b);
|
||||
|
||||
vias[v->bottom_conductor].push_back (ViaPort (vc->second, a));
|
||||
vias[v->top_conductor].push_back (ViaPort (vc->second, b));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ namespace pex
|
|||
{
|
||||
|
||||
class RExtractorTech;
|
||||
class RExtractorTechVia;
|
||||
class RExtractorTechConductor;
|
||||
class RNetwork;
|
||||
class RNode;
|
||||
|
|
@ -37,7 +38,7 @@ class RNode;
|
|||
/**
|
||||
* @brief Implementation of the R extractor for a multi-polygon/multi-layer net
|
||||
*/
|
||||
class RNetExtractor
|
||||
class PEX_PUBLIC RNetExtractor
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
|
@ -74,9 +75,7 @@ public:
|
|||
RNode *node;
|
||||
};
|
||||
|
||||
private:
|
||||
double m_dbu;
|
||||
|
||||
protected:
|
||||
void create_via_ports (const RExtractorTech &tech,
|
||||
const std::map<unsigned int, db::Region> &geo,
|
||||
std::map<unsigned int, std::vector<ViaPort> > &vias,
|
||||
|
|
@ -90,6 +89,16 @@ private:
|
|||
unsigned int polygon_ports_index_offset,
|
||||
const std::vector<ViaPort> &via_ports,
|
||||
RNetwork &rnetwork);
|
||||
|
||||
private:
|
||||
double m_dbu;
|
||||
|
||||
void create_via_port (const RExtractorTechVia &tech,
|
||||
double conductance,
|
||||
const db::Polygon &poly,
|
||||
unsigned int &port_index,
|
||||
std::map<unsigned int, std::vector<ViaPort> > &vias,
|
||||
RNetwork &rnetwork);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@ namespace pex
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
std::string
|
||||
RNode::to_string () const
|
||||
RNode::to_string (bool with_coords) const
|
||||
{
|
||||
std::string res;
|
||||
|
||||
switch (type) {
|
||||
default:
|
||||
res += "$" + tl::to_string (port_index);
|
||||
|
|
@ -44,24 +45,29 @@ RNode::to_string () const
|
|||
res += "P" + tl::to_string (port_index);
|
||||
break;
|
||||
}
|
||||
|
||||
if (with_coords) {
|
||||
res += location.to_string ();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
std::string
|
||||
RElement::to_string () const
|
||||
RElement::to_string (bool with_coords) const
|
||||
{
|
||||
std::string na;
|
||||
if (a ()) {
|
||||
na = a ()->to_string ();
|
||||
na = a ()->to_string (with_coords);
|
||||
} else {
|
||||
na = "(nil)";
|
||||
}
|
||||
|
||||
std::string nb;
|
||||
if (b ()) {
|
||||
nb = b ()->to_string ();
|
||||
nb = b ()->to_string (with_coords);
|
||||
} else {
|
||||
nb = "(nil)";
|
||||
}
|
||||
|
|
@ -88,14 +94,14 @@ RNetwork::~RNetwork ()
|
|||
}
|
||||
|
||||
std::string
|
||||
RNetwork::to_string () const
|
||||
RNetwork::to_string (bool with_coords) const
|
||||
{
|
||||
std::string res;
|
||||
for (auto e = m_elements.begin (); e != m_elements.end (); ++e) {
|
||||
if (! res.empty ()) {
|
||||
res += "\n";
|
||||
}
|
||||
res += e->to_string ();
|
||||
res += e->to_string (with_coords);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ public:
|
|||
/**
|
||||
* @brief Returns a string representation of the node
|
||||
*/
|
||||
std::string to_string () const;
|
||||
std::string to_string (bool with_coords = false) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the network the node lives in
|
||||
|
|
@ -180,7 +180,7 @@ struct PEX_PUBLIC RElement
|
|||
/**
|
||||
* @brief Returns a string representation of the element
|
||||
*/
|
||||
std::string to_string () const;
|
||||
std::string to_string (bool with_coords = false) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the network the node lives in
|
||||
|
|
@ -357,7 +357,7 @@ public:
|
|||
/**
|
||||
* @brief Returns a string representation of the graph
|
||||
*/
|
||||
std::string to_string () const;
|
||||
std::string to_string (bool with_coords = false) const;
|
||||
|
||||
private:
|
||||
node_list m_nodes;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@
|
|||
namespace pex
|
||||
{
|
||||
|
||||
// Value used for number of squares for width 0 (should not happen)
|
||||
const double infinite_squares = 1e10;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
|
@ -103,7 +106,7 @@ double calculate_squares (db::Coord x1, db::Coord x2, const std::set<db::Edge> &
|
|||
// integrate the resistance along the axis x1->x2 with w=w1->w2
|
||||
|
||||
if (w1 < db::epsilon) {
|
||||
return 1e9; // @@@
|
||||
return infinite_squares;
|
||||
} else if (fabs (w1 - w2) < db::epsilon) {
|
||||
return (x2 - x1) / w1;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,139 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2025 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 "pexRNetExtractor.h"
|
||||
#include "pexRExtractorTech.h"
|
||||
#include "pexRNetwork.h"
|
||||
#include "dbReader.h"
|
||||
#include "dbLayout.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
class TestableRNetExtractor
|
||||
: public pex::RNetExtractor
|
||||
{
|
||||
public:
|
||||
TestableRNetExtractor (double dbu) : pex::RNetExtractor (dbu) { }
|
||||
|
||||
using pex::RNetExtractor::create_via_ports;
|
||||
};
|
||||
|
||||
TEST(netex_viagen1)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
std::string fn = tl::testdata () + "/pex/netex_viagen1.gds";
|
||||
tl::InputStream is (fn);
|
||||
db::Reader reader (is);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
TestableRNetExtractor rex (ly.dbu ());
|
||||
|
||||
auto tc = ly.cell_by_name ("TOP");
|
||||
tl_assert (tc.first);
|
||||
|
||||
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
|
||||
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
|
||||
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
|
||||
|
||||
std::map<unsigned int, db::Region> geo;
|
||||
geo.insert (std::make_pair (l2, db::Region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l2))));
|
||||
|
||||
pex::RNetwork network;
|
||||
|
||||
pex::RExtractorTech tech;
|
||||
|
||||
pex::RExtractorTechVia via1;
|
||||
via1.bottom_conductor = l1;
|
||||
via1.cut_layer = l2;
|
||||
via1.top_conductor = l3;
|
||||
via1.resistance = 2.0;
|
||||
tech.vias.push_back (via1);
|
||||
|
||||
std::map<unsigned int, std::vector<pex::RNetExtractor::ViaPort> > via_ports;
|
||||
rex.create_via_ports (tech, geo, via_ports, network);
|
||||
|
||||
EXPECT_EQ (via_ports [l1].size (), size_t (4));
|
||||
EXPECT_EQ (via_ports [l2].size (), size_t (0));
|
||||
EXPECT_EQ (via_ports [l3].size (), size_t (4));
|
||||
|
||||
EXPECT_EQ (network.to_string (true),
|
||||
"R $0(1.7,0.1;1.9,0.3) $1(1.7,0.1;1.9,0.3) 50\n"
|
||||
"R $2(0.4,0.5;0.6,0.7) $3(0.4,0.5;0.6,0.7) 50\n"
|
||||
"R $4(0.8,0.5;1,0.7) $5(0.8,0.5;1,0.7) 50\n"
|
||||
"R $6(2.9,0.5;3.1,0.7) $7(2.9,0.5;3.1,0.7) 50"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(netex_viagen2)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
{
|
||||
std::string fn = tl::testdata () + "/pex/netex_viagen2.gds";
|
||||
tl::InputStream is (fn);
|
||||
db::Reader reader (is);
|
||||
reader.read (ly);
|
||||
}
|
||||
|
||||
TestableRNetExtractor rex (ly.dbu ());
|
||||
|
||||
auto tc = ly.cell_by_name ("TOP");
|
||||
tl_assert (tc.first);
|
||||
|
||||
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
|
||||
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
|
||||
unsigned int l3 = ly.get_layer (db::LayerProperties (3, 0));
|
||||
|
||||
std::map<unsigned int, db::Region> geo;
|
||||
geo.insert (std::make_pair (l2, db::Region (db::RecursiveShapeIterator (ly, ly.cell (tc.second), l2))));
|
||||
|
||||
pex::RNetwork network;
|
||||
|
||||
pex::RExtractorTech tech;
|
||||
|
||||
pex::RExtractorTechVia via1;
|
||||
via1.bottom_conductor = l1;
|
||||
via1.cut_layer = l2;
|
||||
via1.top_conductor = l3;
|
||||
via1.resistance = 2.0;
|
||||
via1.merge_distance = 0.2;
|
||||
tech.vias.push_back (via1);
|
||||
|
||||
std::map<unsigned int, std::vector<pex::RNetExtractor::ViaPort> > via_ports;
|
||||
rex.create_via_ports (tech, geo, via_ports, network);
|
||||
|
||||
EXPECT_EQ (via_ports [l1].size (), size_t (6));
|
||||
EXPECT_EQ (via_ports [l2].size (), size_t (0));
|
||||
EXPECT_EQ (via_ports [l3].size (), size_t (6));
|
||||
|
||||
EXPECT_EQ (network.to_string (true),
|
||||
"R $0(4.6,2.8;4.8,3) $1(4.6,2.8;4.8,3) 50\n"
|
||||
"R $2(2.5,3.7;2.7,3.9) $3(2.5,3.7;2.7,3.9) 50\n"
|
||||
"R $4(3,3.7;3.2,3.9) $5(3,3.7;3.2,3.9) 50\n"
|
||||
"R $6(2.2,1.2;3.4,3.4) $7(2.2,1.2;3.4,3.4) 2.77778\n"
|
||||
"R $8(0.4,0.4;2.2,4.2) $9(0.4,0.4;2.2,4.2) 1\n"
|
||||
"R $10(0.6,4.9;1.2,5.1) $11(0.6,4.9;1.2,5.1) 25"
|
||||
);
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ include($$PWD/../../lib_ut.pri)
|
|||
|
||||
SOURCES = \
|
||||
pexRExtractorTests.cc \
|
||||
pexRNetExtractorTests.cc \
|
||||
pexSquareCountingRExtractorTests.cc \
|
||||
pexTriangulationRExtractorTests.cc
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue