Merge pull request #1557 from KLayout/wip2

Wip2
This commit is contained in:
Matthias Köfferlein 2023-12-08 07:25:03 +01:00 committed by GitHub
commit 92eccb1d7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 821 additions and 131 deletions

View File

@ -134,6 +134,13 @@ if ! [ -e $target/klayout.exe ]; then
exit 1
fi
# ----------------------------------------------------------
# cert.pem
echo "Installing cert.pem .."
cp $mingw_inst/etc/ssl/cert.pem $target
# ----------------------------------------------------------
# Plugins

View File

@ -40,7 +40,7 @@ InstallDirRegKey HKLM \
"UninstallString"
# The text to prompt the user to enter a directory
DirText "Please select your ${NAME} installation path below:"
DirText "Please select your ${NAME} installation path below (CAUTION: THE GIVEN FOLDER WILL BE DELETED ENTIRELY ON UNINSTALLATION - DO NOT USE A GENERAL PURPOSE FOLDER OR A DRIVE ONLY):"
# automatically close the installer when done.
AutoCloseWindow true
@ -68,6 +68,7 @@ section
file *.dll
file strm*.exe
file .*-paths.txt
file cert.pem
file /r db_plugins
file /r lay_plugins
file /r audio
@ -154,7 +155,7 @@ section "Uninstall"
# now delete installed files
rmDir /r "$INSTDIR"
# create a shortcut
# remove shortcut
rmDir /r "$SMPROGRAMS\${NAME}"
DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}"

View File

@ -176,6 +176,7 @@ DeepEdges::~DeepEdges ()
DeepEdges::DeepEdges (const DeepEdges &other)
: MutableEdges (other), DeepShapeCollectionDelegateBase (other),
m_merged_edges_valid (other.m_merged_edges_valid),
m_merged_edges_boc_hash (other.m_merged_edges_boc_hash),
m_is_merged (other.m_is_merged)
{
if (m_merged_edges_valid) {
@ -192,6 +193,7 @@ DeepEdges::operator= (const DeepEdges &other)
DeepShapeCollectionDelegateBase::operator= (other);
m_merged_edges_valid = other.m_merged_edges_valid;
m_merged_edges_boc_hash = other.m_merged_edges_boc_hash;
m_is_merged = other.m_is_merged;
if (m_merged_edges_valid) {
m_merged_edges = other.m_merged_edges.copy ();
@ -205,6 +207,7 @@ DeepEdges::operator= (const DeepEdges &other)
void DeepEdges::init ()
{
m_merged_edges_valid = false;
m_merged_edges_boc_hash = 0;
m_merged_edges = db::DeepLayer ();
m_is_merged = false;
}
@ -458,6 +461,7 @@ void DeepEdges::apply_property_translator (const db::PropertiesTranslator &pt)
DeepShapeCollectionDelegateBase::apply_property_translator (pt);
m_merged_edges_valid = false;
m_merged_edges_boc_hash = 0;
m_merged_edges = db::DeepLayer ();
}
@ -637,10 +641,16 @@ DeepEdges::merged_deep_layer () const
}
}
bool
DeepEdges::merged_edges_available () const
{
return m_is_merged || (m_merged_edges_valid && m_merged_edges_boc_hash == deep_layer ().breakout_cells_hash ());
}
void
DeepEdges::ensure_merged_edges_valid () const
{
if (! m_merged_edges_valid) {
if (! m_merged_edges_valid || (! m_is_merged && m_merged_edges_boc_hash != deep_layer ().breakout_cells_hash ())) {
if (m_is_merged) {
@ -659,7 +669,7 @@ DeepEdges::ensure_merged_edges_valid () const
db::Connectivity conn;
conn.connect (deep_layer ());
hc.set_base_verbosity (base_verbosity() + 10);
hc.build (layout, deep_layer ().initial_cell (), conn);
hc.build (layout, deep_layer ().initial_cell (), conn, 0, deep_layer ().breakout_cells ());
// collect the clusters and merge them into larger edges
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
@ -683,6 +693,7 @@ DeepEdges::ensure_merged_edges_valid () const
}
m_merged_edges_valid = true;
m_merged_edges_boc_hash = deep_layer ().breakout_cells_hash ();
}
}
@ -692,6 +703,7 @@ DeepEdges::set_is_merged (bool f)
{
m_is_merged = f;
m_merged_edges_valid = false;
m_merged_edges_boc_hash = 0;
m_merged_edges = db::DeepLayer ();
}
@ -909,7 +921,7 @@ DeepEdges::and_or_not_with (const DeepEdges *other, EdgeBoolOp op) const
db::EdgeBoolAndOrNotLocalOperation local_op (op);
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
@ -936,7 +948,7 @@ DeepEdges::edge_region_op (const DeepRegion *other, EdgePolygonOp::mode_t mode,
db::EdgeToPolygonLocalOperation op (mode, include_borders);
db::local_processor<db::Edge, db::PolygonRef, db::Edge> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
db::local_processor<db::Edge, db::PolygonRef, db::Edge> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
@ -1253,7 +1265,6 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t
std::unique_ptr<db::DeepRegion> res (new db::DeepRegion (edges.derived ()));
db::Layout &layout = const_cast<db::Layout &> (edges.layout ());
db::Cell &top_cell = const_cast<db::Cell &> (edges.initial_cell ());
// TODO: there is a special case when we'd need a MagnificationAndOrientationReducer:
// dots formally don't have an orientation, hence the interpretation is x and y.
@ -1271,7 +1282,7 @@ RegionDelegate *DeepEdges::extended (coord_type ext_b, coord_type ext_e, coord_t
db::Connectivity conn (db::Connectivity::EdgesConnectByPoints);
conn.connect (edges);
hc.set_base_verbosity (base_verbosity () + 10);
hc.build (layout, edges.initial_cell (), conn);
hc.build (layout, edges.initial_cell (), conn, 0, edges.breakout_cells ());
// TODO: iterate only over the called cells?
for (db::Layout::iterator c = layout.begin (); c != layout.end (); ++c) {
@ -1714,7 +1725,7 @@ DeepEdges::selected_interacting_generic (const Region &other, EdgeInteractionMod
db::Edge2PolygonInteractingLocalOperation op (mode, inverse ? db::Edge2PolygonInteractingLocalOperation::Inverse : db::Edge2PolygonInteractingLocalOperation::Normal);
db::local_processor<db::Edge, db::PolygonRef, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
db::local_processor<db::Edge, db::PolygonRef, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edges.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
@ -1746,7 +1757,7 @@ DeepEdges::selected_interacting_pair_generic (const Region &other, EdgeInteracti
db::Edge2PolygonInteractingLocalOperation op (mode, db::Edge2PolygonInteractingLocalOperation::Both);
db::local_processor<db::Edge, db::PolygonRef, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
db::local_processor<db::Edge, db::PolygonRef, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edges.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
@ -1772,7 +1783,7 @@ DeepEdges::selected_interacting_generic (const Edges &other, EdgeInteractionMode
db::Edge2EdgeInteractingLocalOperation op (mode, inverse ? db::Edge2EdgeInteractingLocalOperation::Inverse : db::Edge2EdgeInteractingLocalOperation::Normal);
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edges.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
@ -1804,7 +1815,7 @@ DeepEdges::selected_interacting_pair_generic (const Edges &other, EdgeInteractio
db::Edge2EdgeInteractingLocalOperation op (mode, db::Edge2EdgeInteractingLocalOperation::Both);
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edges.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
@ -1830,7 +1841,7 @@ RegionDelegate *DeepEdges::pull_generic (const Region &other) const
db::Edge2PolygonPullLocalOperation op;
db::local_processor<db::Edge, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell ());
db::local_processor<db::Edge, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), edges.breakout_cells (), other_polygons.breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
@ -1856,7 +1867,7 @@ EdgesDelegate *DeepEdges::pull_generic (const Edges &other) const
db::Edge2EdgePullLocalOperation op;
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell ());
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell (), edges.breakout_cells (), other_edges.breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
@ -1885,7 +1896,7 @@ EdgesDelegate *DeepEdges::in (const Edges &other, bool invert) const
db::ContainedEdgesLocalOperation op (invert ? Negative : Positive);
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edges.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
@ -1916,7 +1927,7 @@ std::pair<EdgesDelegate *, EdgesDelegate *> DeepEdges::in_and_out (const Edges &
db::ContainedEdgesLocalOperation op (PositiveAndNegative);
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
db::local_processor<db::Edge, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&edges.layout ()), const_cast<db::Cell *> (&edges.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), edges.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());
@ -2049,7 +2060,9 @@ DeepEdges::run_check (db::edge_relation_type rel, const Edges *other, db::Coord
db::local_processor<db::Edge, db::Edge, db::EdgePair> proc (const_cast<db::Layout *> (&edges.layout ()),
const_cast<db::Cell *> (&edges.initial_cell ()),
other_deep ? &other_deep->deep_layer ().layout () : const_cast<db::Layout *> (&edges.layout ()),
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&edges.initial_cell ()));
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&edges.initial_cell ()),
edges.breakout_cells (),
other_deep ? other_deep->deep_layer ().breakout_cells () : 0);
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (edges.store ()->threads ());

View File

@ -170,6 +170,9 @@ public:
void set_is_merged (bool f);
bool merged_edges_available () const;
const DeepLayer &merged_deep_layer () const;
protected:
virtual void merged_semantics_changed ();
@ -180,11 +183,11 @@ private:
mutable DeepLayer m_merged_edges;
mutable bool m_merged_edges_valid;
mutable size_t m_merged_edges_boc_hash;
bool m_is_merged;
void init ();
void ensure_merged_edges_valid () const;
const DeepLayer &merged_deep_layer () const;
DeepLayer and_or_not_with(const DeepEdges *other, EdgeBoolOp op) const;
std::pair<DeepLayer, DeepLayer> edge_region_op (const DeepRegion *other, EdgePolygonOp::mode_t op, bool include_borders) const;
EdgePairsDelegate *run_check (db::edge_relation_type rel, const Edges *other, db::Coord d, const db::EdgesCheckOptions &options) const;

View File

@ -179,6 +179,7 @@ DeepRegion::~DeepRegion ()
DeepRegion::DeepRegion (const DeepRegion &other)
: MutableRegion (other), DeepShapeCollectionDelegateBase (other),
m_merged_polygons_valid (other.m_merged_polygons_valid),
m_merged_polygons_boc_hash (other.m_merged_polygons_boc_hash),
m_is_merged (other.m_is_merged)
{
if (m_merged_polygons_valid) {
@ -195,6 +196,7 @@ DeepRegion::operator= (const DeepRegion &other)
DeepShapeCollectionDelegateBase::operator= (other);
m_merged_polygons_valid = other.m_merged_polygons_valid;
m_merged_polygons_boc_hash = other.m_merged_polygons_boc_hash;
m_is_merged = other.m_is_merged;
if (m_merged_polygons_valid) {
m_merged_polygons = other.m_merged_polygons.copy ();
@ -208,6 +210,7 @@ DeepRegion::operator= (const DeepRegion &other)
void DeepRegion::init ()
{
m_merged_polygons_valid = false;
m_merged_polygons_boc_hash = 0;
m_merged_polygons = db::DeepLayer ();
m_is_merged = false;
}
@ -484,6 +487,7 @@ void DeepRegion::apply_property_translator (const db::PropertiesTranslator &pt)
DeepShapeCollectionDelegateBase::apply_property_translator (pt);
m_merged_polygons_valid = false;
m_merged_polygons_boc_hash = 0;
m_merged_polygons = db::DeepLayer ();
}
@ -683,13 +687,13 @@ DeepRegion::merged_deep_layer () const
bool
DeepRegion::merged_polygons_available () const
{
return m_is_merged || m_merged_polygons_valid;
return m_is_merged || (m_merged_polygons_valid && m_merged_polygons_boc_hash == deep_layer ().breakout_cells_hash ());
}
void
DeepRegion::ensure_merged_polygons_valid () const
{
if (! m_merged_polygons_valid) {
if (! m_merged_polygons_valid || (! m_is_merged && m_merged_polygons_boc_hash != deep_layer ().breakout_cells_hash ())) {
if (m_is_merged) {
@ -708,7 +712,7 @@ DeepRegion::ensure_merged_polygons_valid () const
db::Connectivity conn;
conn.connect (deep_layer ());
hc.set_base_verbosity (base_verbosity () + 10);
hc.build (layout, deep_layer ().initial_cell (), conn, 0, 0, true /*separate_attributes*/);
hc.build (layout, deep_layer ().initial_cell (), conn, 0, deep_layer ().breakout_cells (), true /*separate_attributes*/);
// collect the clusters and merge them into big polygons
// NOTE: using the ClusterMerger we merge bottom-up forming bigger and bigger polygons. This is
@ -732,6 +736,7 @@ DeepRegion::ensure_merged_polygons_valid () const
}
m_merged_polygons_valid = true;
m_merged_polygons_boc_hash = deep_layer ().breakout_cells_hash ();
}
}
@ -741,6 +746,7 @@ DeepRegion::set_is_merged (bool f)
{
m_is_merged = f;
m_merged_polygons_valid = false;
m_merged_polygons_boc_hash = 0;
m_merged_polygons = db::DeepLayer ();
}

View File

@ -173,6 +173,7 @@ private:
mutable DeepLayer m_merged_polygons;
mutable bool m_merged_polygons_valid;
mutable size_t m_merged_polygons_boc_hash;
bool m_is_merged;
void init ();

View File

@ -184,6 +184,12 @@ DeepLayer::breakout_cells () const
return store ()->breakout_cells (layout_index ());
}
size_t
DeepLayer::breakout_cells_hash () const
{
return store ()->breakout_cells_hash (layout_index ());
}
void
DeepLayer::insert_into (db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
@ -409,36 +415,51 @@ DeepShapeStoreState::text_property_name () const
const std::set<db::cell_index_type> *
DeepShapeStoreState::breakout_cells (unsigned int layout_index) const
{
const std::set<db::cell_index_type> &boc = (const_cast<DeepShapeStoreState *> (this))->ensure_breakout_cells (layout_index);
if (boc.empty ()) {
const std::pair<std::set<db::cell_index_type>, size_t> &boc = (const_cast<DeepShapeStoreState *> (this))->ensure_breakout_cells (layout_index);
if (boc.first.empty ()) {
return 0;
} else {
return &boc;
return &boc.first;
}
}
size_t
DeepShapeStoreState::breakout_cells_hash (unsigned int layout_index) const
{
const std::pair<std::set<db::cell_index_type>, size_t> &boc = (const_cast<DeepShapeStoreState *> (this))->ensure_breakout_cells (layout_index);
return boc.second;
}
void
DeepShapeStoreState::clear_breakout_cells (unsigned int layout_index)
{
ensure_breakout_cells (layout_index).clear ();
std::pair<std::set<db::cell_index_type>, size_t> &boc = ensure_breakout_cells (layout_index);
boc.first.clear ();
boc.second = std::hash<std::set<db::cell_index_type> >() (boc.first);
}
void
DeepShapeStoreState::set_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &boc)
DeepShapeStoreState::set_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &boc_in)
{
ensure_breakout_cells (layout_index) = boc;
std::pair<std::set<db::cell_index_type>, size_t> &boc = ensure_breakout_cells (layout_index);
boc.first = boc_in;
boc.second = std::hash<std::set<db::cell_index_type> >() (boc.first);
}
void
DeepShapeStoreState::add_breakout_cell (unsigned int layout_index, db::cell_index_type ci)
{
ensure_breakout_cells (layout_index).insert (ci);
std::pair<std::set<db::cell_index_type>, size_t> &boc = ensure_breakout_cells (layout_index);
boc.first.insert (ci);
boc.second = std::hash<std::set<db::cell_index_type> >() (boc.first);
}
void
DeepShapeStoreState::add_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &cc)
{
ensure_breakout_cells (layout_index).insert (cc.begin (), cc.end ());
std::pair<std::set<db::cell_index_type>, size_t> &boc = ensure_breakout_cells (layout_index);
boc.first.insert (cc.begin (), cc.end ());
boc.second = std::hash<std::set<db::cell_index_type> >() (boc.first);
}
void
@ -726,6 +747,12 @@ DeepShapeStore::breakout_cells (unsigned int layout_index) const
return m_state.breakout_cells (layout_index);
}
size_t
DeepShapeStore::breakout_cells_hash (unsigned int layout_index) const
{
return m_state.breakout_cells_hash (layout_index);
}
void
DeepShapeStore::clear_breakout_cells (unsigned int layout_index)
{

View File

@ -165,6 +165,11 @@ public:
*/
const std::set<db::cell_index_type> *breakout_cells () const;
/**
* @brief Gets a hash value representing the breakout cells
*/
size_t breakout_cells_hash () const;
/**
* @brief Inserts the layer into the given layout, starting from the given cell and into the given layer
*/
@ -251,6 +256,7 @@ public:
bool reject_odd_polygons () const;
const std::set<db::cell_index_type> *breakout_cells (unsigned int layout_index) const;
size_t breakout_cells_hash (unsigned int layout_index) const;
void clear_breakout_cells (unsigned int layout_index);
void set_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &boc);
void add_breakout_cell (unsigned int layout_index, db::cell_index_type ci);
@ -265,14 +271,14 @@ private:
size_t m_max_vertex_count;
bool m_reject_odd_polygons;
tl::Variant m_text_property_name;
std::vector<std::set<db::cell_index_type> > m_breakout_cells;
std::vector<std::pair<std::set<db::cell_index_type>, size_t> > m_breakout_cells;
int m_text_enlargement;
bool m_subcircuit_hierarchy_for_nets;
std::set<db::cell_index_type> &ensure_breakout_cells (unsigned int layout_index)
std::pair<std::set<db::cell_index_type>, size_t> &ensure_breakout_cells (unsigned int layout_index)
{
if (m_breakout_cells.size () <= size_t (layout_index)) {
m_breakout_cells.resize (layout_index + 1, std::set<db::cell_index_type> ());
m_breakout_cells.resize (layout_index + 1, std::pair<std::set<db::cell_index_type>, size_t> ());
}
return m_breakout_cells [layout_index];
}
@ -782,6 +788,11 @@ public:
*/
const std::set<db::cell_index_type> *breakout_cells (unsigned int layout_index) const;
/**
* @brief Gets a hash value representing the breakout cells
*/
size_t breakout_cells_hash (unsigned int layout_index) const;
/**
* @brief Clears the breakout cell list for a given layout
*/

View File

@ -80,7 +80,7 @@ Technologies::instance ()
static tl::XMLElementList xml_elements ()
{
return make_element ((Technologies::const_iterator (Technologies::*) () const) &Technologies::begin, (Technologies::const_iterator (Technologies::*) () const) &Technologies::end, &Technologies::add, "technology",
return make_element ((Technologies::const_iterator (Technologies::*) () const) &Technologies::begin, (Technologies::const_iterator (Technologies::*) () const) &Technologies::end, &Technologies::add_void, "technology",
Technology::xml_elements ()
);
}
@ -92,7 +92,7 @@ Technologies::to_xml () const
db::Technologies copy;
for (const_iterator t = begin (); t != end (); ++t) {
if (t->is_persisted ()) {
copy.add (new Technology (*t));
copy.add (*t);
}
}
@ -110,7 +110,7 @@ Technologies::load_from_xml (const std::string &s)
db::Technologies copy;
for (const_iterator t = begin (); t != end (); ++t) {
if (! t->is_persisted ()) {
copy.add (new Technology (*t));
copy.add (*t);
}
}
@ -121,34 +121,31 @@ Technologies::load_from_xml (const std::string &s)
*this = copy;
}
void
Technologies::add_tech (Technology *tech, bool replace_same)
db::Technology *
Technologies::add_tech (const Technology &tech, bool replace_same)
{
if (! tech) {
return;
}
std::unique_ptr<Technology> tech_ptr (tech);
Technology *t = 0;
for (tl::stable_vector<Technology>::iterator i = m_technologies.begin (); !t && i != m_technologies.end (); ++i) {
if (i->name () == tech->name ()) {
if (i->name () == tech.name ()) {
t = i.operator-> ();
}
}
if (t) {
if (replace_same) {
*t = *tech;
*t = tech;
} else {
throw tl::Exception (tl::to_string (tr ("A technology with this name already exists: ")) + tech->name ());
throw tl::Exception (tl::to_string (tr ("A technology with this name already exists: ")) + tech.name ());
}
} else {
m_technologies.push_back (tech_ptr.release ());
tech->technology_changed_with_sender_event.add (this, &Technologies::technology_changed);
t = new Technology (tech);
m_technologies.push_back (t);
t->technology_changed_with_sender_event.add (this, &Technologies::technology_changed);
}
technologies_changed ();
return t;
}
void

View File

@ -121,24 +121,34 @@ public:
/**
* @brief Adds a technology to the setup
*
* The container becomes owner of the technology object.
* Replaces a technology with the name of the given technology.
* @return A reference to the new Technology object
*
* If a technology with the given name already exists, it is replaced.
*/
void add (Technology *technology)
db::Technology *add (const Technology &technology)
{
add_tech (technology, true /*replace*/);
return add_tech (technology, true /*replace*/);
}
/**
* @brief Adds a technology with a new name
*
* @return A reference to the new Technology object
*
* Like \add, but throws an exception if a technology with this name
* already exists. Takes over ownership over the technology object.
* The technology object is discarded if an exception is thrown.
* already exists.
*/
void add_new (Technology *technology)
db::Technology *add_new (const Technology &technology)
{
add_tech (technology, false /*throws exception on same name*/);
return add_tech (technology, false /*throws exception on same name*/);
}
/**
* @brief Same as add, but no return value (for XML binding)
*/
void add_void (const Technology &technology)
{
add (technology);
}
/**
@ -244,7 +254,7 @@ private:
bool m_changed;
bool m_in_update;
void add_tech (Technology *technology, bool replace_same);
Technology *add_tech(const Technology &technology, bool replace_same);
};
/**

View File

@ -555,7 +555,7 @@ struct edge_defs
"This method has been introduced in version 0.26.2.\n"
) +
method ("distance", &C::distance, gsi::arg ("p"),
"@brief Distance between the edge and a point.\n"
"@brief Gets the distance of the point from the line through the edge.\n"
"\n"
"Returns the distance between the edge and the point. The \n"
"distance is signed which is negative if the point is to the\n"
@ -564,6 +564,11 @@ struct edge_defs
"line through the edge. If the edge is degenerated, the distance\n"
"is not defined.\n"
"\n"
"This method considers the edge to define an infinite line running through it.\n"
"\\distance returns the distance of 'p' to this line.\n"
"A similar method is \\euclidian_distance, but the latter regards\n"
"the edge a finite set of points between the endpoints.\n"
"\n"
"@param p The point to test.\n"
"\n"
"@return The distance\n"
@ -578,6 +583,19 @@ struct edge_defs
"\n"
"@return The side value\n"
) +
method ("euclidian_distance", &C::euclidian_distance, gsi::arg ("p"),
"@brief Gets the distance of the point from the the edge.\n"
"\n"
"Returns the minimum distance of the point to any point on the edge.\n"
"Unlike \\distance, the edge is considered a finite set of points between\n"
"the endpoints. The result is also not signed like it is the case for \\distance.\n"
"\n"
"This method has been introduced in version 0.28.14.\n"
"\n"
"@param p The point to test.\n"
"\n"
"@return The distance\n"
) +
method ("distance_abs", &C::distance_abs, gsi::arg ("p"),
"@brief Absolute distance between the edge and a point.\n"
"\n"

View File

@ -169,6 +169,14 @@ struct edge_pair_defs
method ("bbox", &C::bbox,
"@brief Gets the bounding box of the edge pair\n"
) +
method ("distance", &C::distance,
"@brief Gets the distance of the edges in the edge pair\n"
"\n"
"The distance between the two edges is defined as the minimum distance between any "
"two points on the two edges.\n"
"\n"
"This attribute has been introduced in version 0.28.14."
) +
method ("perimeter", &C::perimeter,
"@brief Gets the perimeter of the edge pair\n"
"\n"

View File

@ -45,10 +45,14 @@ static db::Technology *technology_by_name (const std::string &name)
static db::Technology *create_technology (const std::string &name)
{
db::Technology *tech = new db::Technology ();
tech->set_name (name);
db::Technologies::instance ()->add_new (tech);
return tech;
db::Technology tech;
tech.set_name (name);
return db::Technologies::instance ()->add_new (tech);
}
static db::Technology *register_technology (const db::Technology &tech)
{
return db::Technologies::instance ()->add_new (tech);
}
static void remove_technology (const std::string &name)
@ -291,10 +295,24 @@ gsi::Class<db::Technology> technology_decl ("db", "Technology",
gsi::method ("create_technology", &create_technology, gsi::arg ("name"),
"@brief Creates a new (empty) technology with the given name\n"
"\n"
"The new technology is already registered in the system.\n"
"\n"
"This method returns a reference to the new technology."
) +
gsi::method ("register_technology", &register_technology, gsi::arg ("tech"),
"@brief Registers a technology in the system\n"
"\n"
"Only after a technology is registered, it can be used in the system, e.g. by "
"specifying its name in \\Layout#technology_name. While \\create_technology already registers "
"the technology, this method allows registering a Technology object that has created in other ways.\n"
"\n"
"This method returns a reference to the new technology object, which is a copy of the argument. "
"\\remove_technology can be used to remove a technology registered by this method.\n"
"\n"
"This method has been introduced in version 0.28.14."
) +
gsi::method ("remove_technology", &remove_technology, gsi::arg ("name"),
"@brief Removes the technology with the given name\n"
"@brief Removes the technology with the given name from the system\n"
) +
gsi::method ("technologies_to_xml", &technologies_to_xml,
"@brief Returns a XML representation of all technologies registered in the system\n"
@ -317,12 +335,13 @@ gsi::Class<db::Technology> technology_decl ("db", "Technology",
gsi::method ("technologies_from_xml", &technologies_from_xml, gsi::arg ("xml"),
"@brief Loads the technologies from a XML representation\n"
"\n"
"See \\technologies_to_xml for details. This method is the corresponding setter."
"See \\technologies_to_xml for details."
) +
gsi::method ("technology_from_xml", &technology_from_xml, gsi::arg ("xml"),
"@brief Loads the technology from a XML representation\n"
"\n"
"See \\technology_to_xml for details."
"See \\technology_to_xml for details. Note that this function will create "
"a new Technology object which is not registered in the system. See \\Technology#register for details."
) +
gsi::method_ext ("component_names", &get_component_names,
"@brief Gets the names of all components available for \\component"
@ -338,6 +357,21 @@ gsi::Class<db::Technology> technology_decl ("db", "Technology",
"definitions are returned with \\technology_by_name. Use \\create_technology to register "
"new technologies and \\remove_technology to delete technologies.\n"
"\n"
"Note that a Technology object needs to be registered in the system, before its name "
"can be used to specify a technology, for example in \\Layout#technology_name. "
"Technology objects created by \\create_technology are automatically registered. "
"If you create a Technology object directly, you need to register it explicitly:"
"\n"
"@code\n"
"tech = RBA::Technology::new\n"
"tech.load(\"mytech.lyt\")\n"
"RBA::Technology::register_technology(tech)\n"
"@/code\n"
"\n"
"Note that in the latter example, an exception will be thrown if a technology with the same "
"name already exists. Also note, that \\Technology#register will register a copy of the "
"object, so modifying it after registration will not have any effect.\n"
"\n"
"The Technology class has been introduced in version 0.25.\n"
);

View File

@ -29,6 +29,7 @@
#include "dbEdgesUtils.h"
#include "dbDeepShapeStore.h"
#include "dbCellGraphUtils.h"
#include "dbDeepEdges.h"
#include "tlUnitTest.h"
#include "tlStream.h"
@ -1292,3 +1293,140 @@ TEST(20_in_and_out)
db::compare_layouts (_this, target, tl::testdata () + "/algo/deep_edges_au20.gds");
}
TEST(deep_edges_and_cheats)
{
db::Layout ly;
{
std::string fn (tl::testdata ());
fn += "/algo/cheats.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
unsigned int l10 = ly.get_layer (db::LayerProperties (10, 0));
unsigned int l11 = ly.get_layer (db::LayerProperties (11, 0));
unsigned int l12 = ly.get_layer (db::LayerProperties (12, 0));
unsigned int l13 = ly.get_layer (db::LayerProperties (13, 0));
unsigned int l14 = ly.get_layer (db::LayerProperties (14, 0));
unsigned int l19 = ly.get_layer (db::LayerProperties (19, 0));
unsigned int l20 = ly.get_layer (db::LayerProperties (20, 0));
unsigned int l21 = ly.get_layer (db::LayerProperties (21, 0));
unsigned int l22 = ly.get_layer (db::LayerProperties (22, 0));
unsigned int l23 = ly.get_layer (db::LayerProperties (23, 0));
unsigned int l24 = ly.get_layer (db::LayerProperties (24, 0));
unsigned int l29 = ly.get_layer (db::LayerProperties (29, 0));
unsigned int l30 = ly.get_layer (db::LayerProperties (30, 0));
unsigned int l31 = ly.get_layer (db::LayerProperties (31, 0));
unsigned int l32 = ly.get_layer (db::LayerProperties (32, 0));
unsigned int l33 = ly.get_layer (db::LayerProperties (33, 0));
unsigned int l34 = ly.get_layer (db::LayerProperties (34, 0));
unsigned int l39 = ly.get_layer (db::LayerProperties (39, 0));
db::DeepShapeStore dss;
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
(r1.edges () - r2).insert_into (&ly, top_cell_index, l10);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("A").second);
(r1.edges () - r2).insert_into (&ly, top_cell_index, l11);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("B").second);
(r1.edges () - r2).insert_into (&ly, top_cell_index, l12);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("C").second);
(r1.edges () - r2).insert_into (&ly, top_cell_index, l13);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("D").second);
(r1.edges () - r2).insert_into (&ly, top_cell_index, l14);
dss.clear_breakout_cells (0);
(r1.edges () - r2).insert_into (&ly, top_cell_index, l19);
(r1.edges () - r2.edges ()).insert_into (&ly, top_cell_index, l20);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("A").second);
(r1.edges () - r2.edges ()).insert_into (&ly, top_cell_index, l21);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("B").second);
(r1.edges () - r2.edges ()).insert_into (&ly, top_cell_index, l22);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("C").second);
(r1.edges () - r2.edges ()).insert_into (&ly, top_cell_index, l23);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("D").second);
(r1.edges () - r2.edges ()).insert_into (&ly, top_cell_index, l24);
dss.clear_breakout_cells (0);
(r1.edges () - r2.edges ()).insert_into (&ly, top_cell_index, l29);
db::Region eo;
db::Edges e1;
e1 = r2.edges ();
e1.extended (eo, 0, 0, 500, 0);
eo.insert_into (&ly, top_cell_index, l30);
EXPECT_EQ (dynamic_cast<const db::DeepEdges *> (e1.delegate ())->merged_edges_available (), true);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("A").second);
e1 = r2.edges ();
e1.extended (eo, 0, 0, 500, 0);
eo.insert_into (&ly, top_cell_index, l31);
EXPECT_EQ (dynamic_cast<const db::DeepEdges *> (e1.delegate ())->merged_edges_available (), true);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("B").second);
e1 = r2.edges ();
e1.extended (eo, 0, 0, 500, 0);
eo.insert_into (&ly, top_cell_index, l32);
EXPECT_EQ (dynamic_cast<const db::DeepEdges *> (e1.delegate ())->merged_edges_available (), true);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("C").second);
e1 = r2.edges ();
e1.extended (eo, 0, 0, 500, 0);
eo.insert_into (&ly, top_cell_index, l33);
EXPECT_EQ (dynamic_cast<const db::DeepEdges *> (e1.delegate ())->merged_edges_available (), true);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("D").second);
e1 = r2.edges ();
e1.extended (eo, 0, 0, 500, 0);
eo.insert_into (&ly, top_cell_index, l34);
EXPECT_EQ (dynamic_cast<const db::DeepEdges *> (e1.delegate ())->merged_edges_available (), true);
dss.clear_breakout_cells (0);
e1 = r2.edges ();
e1.extended (eo, 0, 0, 500, 0);
eo.insert_into (&ly, top_cell_index, l39);
EXPECT_EQ (dynamic_cast<const db::DeepEdges *> (e1.delegate ())->merged_edges_available (), true);
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testdata () + "/algo/cheats_edges_au.gds");
}

View File

@ -30,6 +30,7 @@
#include "dbRegionProcessors.h"
#include "dbEdgesUtils.h"
#include "dbDeepShapeStore.h"
#include "dbDeepRegion.h"
#include "dbOriginalLayerRegion.h"
#include "dbCellGraphUtils.h"
#include "dbTestSupport.h"
@ -2846,3 +2847,97 @@ TEST(issue_663_separation_from_inside)
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testdata () + "/algo/deep_region_au663.gds");
}
TEST(deep_region_and_cheats)
{
db::Layout ly;
{
std::string fn (tl::testdata ());
fn += "/algo/cheats.gds";
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly);
}
db::cell_index_type top_cell_index = *ly.begin_top_down ();
db::Cell &top_cell = ly.cell (top_cell_index);
unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0));
unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0));
unsigned int l10 = ly.get_layer (db::LayerProperties (10, 0));
unsigned int l11 = ly.get_layer (db::LayerProperties (11, 0));
unsigned int l12 = ly.get_layer (db::LayerProperties (12, 0));
unsigned int l13 = ly.get_layer (db::LayerProperties (13, 0));
unsigned int l14 = ly.get_layer (db::LayerProperties (14, 0));
unsigned int l19 = ly.get_layer (db::LayerProperties (19, 0));
unsigned int l20 = ly.get_layer (db::LayerProperties (20, 0));
unsigned int l21 = ly.get_layer (db::LayerProperties (21, 0));
unsigned int l22 = ly.get_layer (db::LayerProperties (22, 0));
unsigned int l23 = ly.get_layer (db::LayerProperties (23, 0));
unsigned int l24 = ly.get_layer (db::LayerProperties (24, 0));
unsigned int l29 = ly.get_layer (db::LayerProperties (29, 0));
db::DeepShapeStore dss;
db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss);
db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss);
(r1 - r2).insert_into (&ly, top_cell_index, l10);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("A").second);
(r1 - r2).insert_into (&ly, top_cell_index, l11);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("B").second);
(r1 - r2).insert_into (&ly, top_cell_index, l12);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("C").second);
(r1 - r2).insert_into (&ly, top_cell_index, l13);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("D").second);
(r1 - r2).insert_into (&ly, top_cell_index, l14);
dss.clear_breakout_cells (0);
(r1 - r2).insert_into (&ly, top_cell_index, l19);
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), false);
r1.sized (-1000).insert_into (&ly, top_cell_index, l20);
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), true);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("A").second);
r1.sized (-1000).insert_into (&ly, top_cell_index, l21);
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), true);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("B").second);
r1.sized (-1000).insert_into (&ly, top_cell_index, l22);
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), true);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("C").second);
r1.sized (-1000).insert_into (&ly, top_cell_index, l23);
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), true);
dss.clear_breakout_cells (0);
dss.add_breakout_cell (0, dss.layout (0).cell_by_name ("D").second);
r1.sized (-1000).insert_into (&ly, top_cell_index, l24);
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), true);
dss.clear_breakout_cells (0);
r1.sized (-1000).insert_into (&ly, top_cell_index, l29);
EXPECT_EQ (dynamic_cast<const db::DeepRegion *> (r1.delegate ())->merged_polygons_available (), true);
CHECKPOINT();
db::compare_layouts (_this, ly, tl::testdata () + "/algo/cheats_au.gds");
}

View File

@ -408,6 +408,61 @@ A::new.f(x)
omitted, the default value is used instead.
</p>
<h2>Implicit conversions</h2>
<h3>String arguments</h3>
<p>
If a method expects a string argument, other types are converted to strings
using the "to_s" method. In Python, the equivalent is "str(...)".
</p>
<p>
Example:
</p>
<pre># Also accepts a float value for the first string argument -
# it is converted to "2.5"
t = RBA::Text::new(2.5, RBA::Trans::new)</pre>
<h3>Conversion constructors</h3>
<p>Conversion constructors are constructors that take an object of a
different class and convert it to the target class.
Conversion constructors are used implicitly in applicable cases
to convert one type to the type requested by the argument.</p>
<p>
For example, in the following code, the Region object's "+" operator
is used. This expects a Region object as the second parameter, but as
there is conversion constructor available which converts a Box to
a Region, it is possible to use a Box directly:
</p>
<pre>r = RBA::Region::new(RBA::Box::new(0, 0, 1000, 2000))
r += RBA::Box::new(3000, 0, 4000, 2000)</pre>
<h3>Implicit constructor from lists</h3>
<p>
When an object is expected for an argument and a list is given,
the object constructor is called with the arguments from the list.
This specifically allows using size-2 lists instead of Point or
Vector arguments. In Python, a "list" can also be a tuple.
</p>
<p>
In the following example, this mechanism is used for
the polygon point list which is expected to be an array
of Point objects, but can use size-2 arrays instead.
Also, the "moved" method expects a Vector, but here
as well, size-2 arrays can be used instead:
</p>
<pre>pts = [ [ 0, 0 ], [ 0, 1000 ], [ 1000, 0 ] ]
poly = RBA::Polygon::new(pts)
poly = poly.moved([ 100, 200 ])</pre>
<h2>Constness</h2>
<p>

View File

@ -261,7 +261,7 @@ Service::snap_marker_to_grid (const db::DVector &v, bool &snapped) const
if (snapped) {
vr += vv;
return db::DVector (vr.x () * snapped_to.x (), vr.y () * snapped_to.y ());
return db::DVector (vr.x () * fabs (snapped_to.x ()), vr.y () * fabs (snapped_to.y ()));
} else {
return db::DVector ();
}

View File

@ -64,6 +64,7 @@
#include "tlHttpStream.h"
#include "tlArch.h"
#include "tlFileUtils.h"
#include "tlEnv.h"
#include <QIcon>
#include <QDir>
@ -568,6 +569,19 @@ ApplicationBase::init_app ()
}
std::string short_arch_string = tl::join (as, "-");
#if defined(_WIN32)
// Set SSL_CERT_FILE for Windows installation and libcrypto.
std::string cert_file = "cert.pem";
std::string cert_env_var = "SSL_CERT_FILE";
if (! tl::has_env (cert_env_var)) {
std::string cert_path = tl::combine_path (m_inst_path, cert_file);
if (tl::file_exists (cert_path)) {
tl::set_env (cert_env_var, cert_path);
}
}
#endif
std::vector<std::string> klp_paths;
for (std::vector <std::string>::const_iterator p = m_klayout_path.begin (); p != m_klayout_path.end (); ++p) {

View File

@ -379,9 +379,11 @@ MacroController::sync_package_paths ()
void
MacroController::sync_implicit_macros (bool ask_before_autorun)
{
// gets the external paths (tech, packages) into m_external_paths
sync_macro_sources ();
if (m_no_implicit_macros) {
sync_macro_sources ();
sync_package_paths ();
} else {
@ -392,9 +394,6 @@ MacroController::sync_implicit_macros (bool ask_before_autorun)
prev_folders_by_path.insert (std::make_pair (p->path, *p));
}
// gets the external paths (tech, packages) into m_external_paths
sync_macro_sources ();
// delete macro collections which are no longer required or update description
std::vector<lym::MacroCollection *> folders_to_delete;

View File

@ -2092,7 +2092,6 @@ MacroEditorDialog::search_editing ()
}
apply_search ();
page->find_reset (); // search from the initial position
if (! page->has_multi_block_selection ()) {
page->find_next ();
}
@ -2119,7 +2118,6 @@ MacroEditorDialog::search_edited ()
}
apply_search ();
page->find_reset (); // search from the initial position
if (! page->has_multi_block_selection ()) {
page->find_next ();
}

View File

@ -523,6 +523,9 @@ SaltDownloadManager::execute (lay::SaltManagerDialog *parent, lay::Salt &salt)
dialog->start ();
// Stop other events to interfere with the download, specifically not macro controller updates
tl::NoDeferredMethods silent_section;
std::sort (m_registry.begin (), m_registry.end ());
for (std::vector<Descriptor>::const_iterator p = m_registry.begin (); p != m_registry.end (); ++p) {

View File

@ -1213,13 +1213,13 @@ private:
void
SaltManagerDialog::get_remote_grain_info (lay::SaltGrain *g, SaltGrainDetailsTextWidget *details)
{
if (! g) {
// NOTE: we don't want to interfere with download here, so refuse to do update
// the info while a package is downloaded.
if (! g || m_downloaded_grain.get ()) {
details->setHtml (QString ());
return;
}
tl_assert (m_downloaded_grain.get () == 0);
m_downloaded_grain.reset (0);
if (m_downloaded_grain_reader.get ()) {

View File

@ -775,13 +775,13 @@ BEGIN_PROTECTED
}
}
db::Technology *nt = new db::Technology (*t);
db::Technology nt (*t);
nt->set_tech_file_path (tl::to_string (tech_dir.absoluteFilePath (tn + QString::fromUtf8 (".lyt"))));
nt->set_default_base_path (tl::to_string (tech_dir.absolutePath ()));
nt->set_persisted (false);
nt->set_name (tl::to_string (tn));
nt->set_description (std::string ());
nt.set_tech_file_path (tl::to_string (tech_dir.absoluteFilePath (tn + QString::fromUtf8 (".lyt"))));
nt.set_default_base_path (tl::to_string (tech_dir.absolutePath ()));
nt.set_persisted (false);
nt.set_name (tl::to_string (tn));
nt.set_description (std::string ());
m_technologies.add (nt);
update_tech_tree ();
@ -900,12 +900,7 @@ BEGIN_PROTECTED
db::Technology t;
t.load (fn);
if (m_technologies.has_technology (t.name ())) {
*m_technologies.technology_by_name (t.name ()) = t;
} else {
m_technologies.add (new db::Technology (t));
}
m_technologies.add (t);
update_tech_tree ();
select_tech (*m_technologies.technology_by_name (t.name ()));

View File

@ -536,7 +536,7 @@ TechnologyController::rescan (db::Technologies &technologies)
technologies.clear ();
for (db::Technologies::const_iterator t = current.begin (); t != current.end (); ++t) {
if (t->is_persisted ()) {
technologies.add (new db::Technology (*t));
technologies.add (*t);
}
}
@ -596,7 +596,7 @@ TechnologyController::rescan (db::Technologies &technologies)
t.set_persisted (false); // don't save that one in the configuration
t.set_readonly (readonly || ! QFileInfo (dir.filePath (*lf)).isWritable ());
t.set_grain_name (grain_name);
technologies.add (new db::Technology (t));
technologies.add (t);
} catch (tl::Exception &ex) {
tl::warn << tl::to_string (QObject::tr ("Unable to auto-import technology file ")) << tl::to_string (*lf) << ": " << ex.msg ();
@ -608,14 +608,14 @@ TechnologyController::rescan (db::Technologies &technologies)
for (std::vector<db::Technology>::const_iterator t = m_temp_tech.begin (); t != m_temp_tech.end (); ++t) {
db::Technology *tech = new db::Technology (*t);
if (tl::verbosity () >= 20) {
tl::info << "Registering special technology from " << tech->tech_file_path () << " as " << tech->name ();
tl::info << "Registering special technology from " << t->tech_file_path () << " as " << t->name ();
}
db::Technology *tech = technologies.add (*t);
tech->set_persisted (false); // don't save that one in the configuration
tech->set_tech_file_path (std::string ()); // don't save to a file either
tech->set_readonly (true); // don't edit
technologies.add (tech);
}
}

View File

@ -677,7 +677,13 @@ NetlistBrowserDialog::l2ndbs_changed ()
for (unsigned int i = 0; i < view ()->num_l2ndbs (); ++i) {
const db::LayoutToNetlist *l2ndb = view ()->get_l2ndb (i);
mp_ui->l2ndb_cb->addItem (tl::to_qstring (l2ndb->name ()));
std::string text = l2ndb->name ();
if (! l2ndb->description ().empty ()) {
text += " (";
text += l2ndb->description ();
text += ")";
}
mp_ui->l2ndb_cb->addItem (tl::to_qstring (text));
if (l2ndb->name () == m_l2ndb_name) {
l2n_index = i;
}

View File

@ -1345,7 +1345,7 @@ bbox_for_circuit (const db::Layout *layout, const db::Circuit *circuit)
void
NetlistBrowserPage::adjust_view ()
{
if (! mp_database.get () || ! mp_view) {
if (! mp_database.get () || ! mp_database->netlist () || ! mp_view) {
return;
}
@ -1666,7 +1666,7 @@ NetlistBrowserPage::update_highlights ()
}
clear_markers ();
if (! mp_database.get () || ! mp_view) {
if (! mp_database.get () || ! mp_database->netlist () || ! mp_view) {
return;
}

View File

@ -582,7 +582,13 @@ MarkerBrowserDialog::rdbs_changed ()
for (unsigned int i = 0; i < view ()->num_rdbs (); ++i) {
const rdb::Database *rdb = view ()->get_rdb (i);
mp_ui->rdb_cb->addItem (tl::to_qstring (rdb->name ()));
std::string text = rdb->name ();
if (! rdb->description ().empty ()) {
text += " (";
text += rdb->description ();
text += ")";
}
mp_ui->rdb_cb->addItem (tl::to_qstring (text));
if (rdb->name () == m_rdb_name) {
rdb_index = i;
}
@ -761,23 +767,35 @@ MarkerBrowserDialog::scan_layer ()
std::string desc;
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
if (!(*l)->has_children () && (*l)->cellview_index () >= 0 && layout.is_valid_layer ((*l)->layer_index ())) {
if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) {
if (! desc.empty ()) {
desc += ", ";
}
desc += layout.get_properties ((*l)->layer_index ()).to_string ();
}
}
rdb->set_description ("Shapes of layer(s) " + desc);
desc = tl::to_string (tr ("Hierarchical shapes of layer(s) ")) + desc;
desc += " ";
desc += tl::to_string (tr ("from cell "));
desc += cv->layout ().cell_name (cv.cell_index ());
rdb->set_description (desc);
std::set<db::cell_index_type> called_cells;
called_cells.insert (cv.cell_index ());
cv->layout ().cell (cv.cell_index ()).collect_called_cells (called_cells);
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
if (!(*l)->has_children () && (*l)->cellview_index () >= 0 && layout.is_valid_layer ((*l)->layer_index ())) {
if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) {
rdb::Category *cat = rdb->create_category (layout.get_properties ((*l)->layer_index ()).to_string ());
rdb::Category *cat = rdb->create_category (layout.get_properties ((*l)->layer_index ()).to_string ());
for (db::Layout::const_iterator cid = layout.begin (); cid != layout.end (); ++cid) {
if (called_cells.find (cid->cell_index ()) == called_cells.end ()) {
continue;
}
const db::Cell &cell = *cid;
if (cell.shapes ((*l)->layer_index ()).size () > 0) {
@ -855,18 +873,22 @@ MarkerBrowserDialog::scan_layer_flat ()
std::string desc;
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
if (!(*l)->has_children () && (*l)->cellview_index () >= 0 && layout.is_valid_layer ((*l)->layer_index ())) {
if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) {
if (! desc.empty ()) {
desc += ", ";
}
desc += layout.get_properties ((*l)->layer_index ()).to_string ();
}
}
rdb->set_description ("Shapes of layer(s) " + desc);
desc = tl::to_string (tr ("Flat shapes of layer(s) ")) + desc;
desc += " ";
desc += tl::to_string (tr ("from cell "));
desc += cv->layout ().cell_name (cv.cell_index ());
rdb->set_description (desc);
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
if (!(*l)->has_children () && (*l)->cellview_index () >= 0 && layout.is_valid_layer ((*l)->layer_index ())) {
if (!(*l)->has_children () && (*l)->cellview_index () == cv_index && layout.is_valid_layer ((*l)->layer_index ())) {
rdb::Category *cat = rdb->create_category (layout.get_properties ((*l)->layer_index ()).to_string ());

View File

@ -2148,7 +2148,7 @@ MarkerBrowserPage::do_update_markers ()
lay::CellView cv = mp_view->cellview (m_cv_index);
if (! current_cell && cv.is_valid ()) {
current_cell = mp_database->cell_by_qname (cv->layout ().cell_name (cv.cell_index ()));
current_cell = mp_database->cell_by_qname (cv->layout ().cell_name (cv.ctx_cell_index ()));
}
std::vector<db::DCplxTrans> tv = mp_view->cv_transform_variants (m_cv_index);
@ -2182,7 +2182,7 @@ MarkerBrowserPage::do_update_markers ()
// If we could not find a transformation in the RDB, try to find one in the layout DB:
std::pair<bool, db::cell_index_type> cc = cv->layout ().cell_by_name (c->name ().c_str ());
if (cc.first) {
std::pair <bool, db::ICplxTrans> ic = db::find_layout_context (cv->layout (), cc.second, cv.cell_index ());
std::pair <bool, db::ICplxTrans> ic = db::find_layout_context (cv->layout (), cc.second, cv.ctx_cell_index ());
if (ic.first) {
context.first = true;
context.second = db::DCplxTrans (cv->layout ().dbu ()) * db::DCplxTrans (ic.second) * db::DCplxTrans (1.0 / cv->layout ().dbu ());
@ -2197,7 +2197,7 @@ MarkerBrowserPage::do_update_markers ()
context = std::pair <bool, db::DCplxTrans> (true, db::DCplxTrans ());
} else if (! current_cell) {
m_error_text = tl::sprintf (tl::to_string (QObject::tr ("Current layout cell '%s' not found in marker database and no path found from marker's cell '%s' to current cell in the layout database.")),
cv->layout ().cell_name (cv.cell_index ()), c->name ());
cv->layout ().cell_name (cv.ctx_cell_index ()), c->name ());
} else {
m_error_text = tl::sprintf (tl::to_string (QObject::tr ("No example instantiation given in marker database for marker's cell '%s' to current cell '%s' and no such path in the layout database either.")),
c->name (), current_cell->name ());

View File

@ -378,8 +378,10 @@ NetTracerData::configure_l2n (db::LayoutToNetlist &l2n)
// make all connections (intra and inter-layer)
for (std::map<unsigned int, tl::shared_ptr<NetTracerLayerExpression::RegionHolder> >::const_iterator r = m_l2n_regions.begin (); r != m_l2n_regions.end (); ++r) {
l2n.connect (*r->second->get ());
const std::set<unsigned int> &connections_to = log_connections (r->first);
if (! connections_to.empty ()) {
l2n.connect (*r->second->get ());
}
for (std::set<unsigned int>::const_iterator c = connections_to.begin (); c != connections_to.end (); ++c) {
std::map<unsigned int, tl::shared_ptr<NetTracerLayerExpression::RegionHolder> >::const_iterator rc = m_l2n_regions.find (*c);
if (rc != m_l2n_regions.end ()) {

View File

@ -348,10 +348,10 @@ END_PROTECTED
}
bool
NetTracerDialog::get_net_tracer_setup (const lay::CellView &cv, db::NetTracerData &data)
NetTracerDialog::get_net_tracer_setup_from_tech (const std::string &tech_name, const std::string &stack_name, const db::Layout &layout, db::NetTracerData &data)
{
// fetch the net tracer data from the technology and apply to the current layout
const db::Technology *tech = cv->technology ();
const db::Technology *tech = db::Technologies::instance ()->technology_by_name (tech_name);
if (! tech) {
return false;
}
@ -361,8 +361,6 @@ NetTracerDialog::get_net_tracer_setup (const lay::CellView &cv, db::NetTracerDat
return false;
}
std::string stack_name = tl::to_string (stack_selector->itemData (stack_selector->currentIndex ()).toString ());
const db::NetTracerConnectivity *connectivity = 0;
for (auto d = tech_component->begin (); d != tech_component->end () && ! connectivity; ++d) {
if (d->name () == stack_name) {
@ -375,10 +373,25 @@ NetTracerDialog::get_net_tracer_setup (const lay::CellView &cv, db::NetTracerDat
}
// Set up the net tracer environment
data = connectivity->get_tracer_data (cv->layout ());
data = connectivity->get_tracer_data (layout);
return true;
}
bool
NetTracerDialog::get_net_tracer_setup (const lay::CellView &cv, db::NetTracerData &data)
{
// fetch the net tracer data from the technology and apply to the current layout
const db::Technology *tech = cv->technology ();
if (! tech) {
return false;
}
const std::string &tech_name = tech->name ();
std::string stack_name = tl::to_string (stack_selector->itemData (stack_selector->currentIndex ()).toString ());
return get_net_tracer_setup_from_tech (tech_name, stack_name, cv->layout (), data);
}
db::NetTracerNet *
NetTracerDialog::do_trace (const db::DBox &start_search_box, const db::DBox &stop_search_box, bool trace_path)
{
@ -652,11 +665,16 @@ NetTracerDialog::menu_activated (const std::string &symbol)
const lay::CellView &cv = view ()->cellview (view ()->active_cellview_index ());
if (cv.is_valid ()) {
db::RecursiveShapeIterator si (cv->layout (), *cv.cell (), std::vector<unsigned int> ());
std::unique_ptr <db::LayoutToNetlist> l2ndb (new db::LayoutToNetlist (si));
trace_all_nets (l2ndb.get (), cv, flat);
unsigned int l2ndb_index = view ()->add_l2ndb (l2ndb.release ());
view ()->open_l2ndb_browser (l2ndb_index, view ()->index_of_cellview (&cv));
if (l2ndb->netlist ()) {
unsigned int l2ndb_index = view ()->add_l2ndb (l2ndb.release ());
view ()->open_l2ndb_browser (l2ndb_index, view ()->index_of_cellview (&cv));
}
}
} else {
@ -1319,7 +1337,7 @@ BEGIN_PROTECTED
db::Technology tech = *db::Technologies::instance ()->technology_by_name (tech_name);
// call the dialog and if successful, install the new technology
lay::TechComponentSetupDialog dialog (this, &tech, db::net_tracer_component_name ());
lay::TechComponentSetupDialog dialog (isVisible () ? this : parentWidget (), &tech, db::net_tracer_component_name ());
if (dialog.exec ()) {
*db::Technologies::instance ()->technology_by_name (tech.name ()) = tech;
update_list_of_stacks ();
@ -1781,13 +1799,79 @@ NetTracerDialog::clear_markers ()
void
NetTracerDialog::trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView &cv, bool flat)
{
const db::Technology *tech = cv->technology ();
if (! tech) {
return;
}
static std::string current_stack;
QStringList stacks;
std::vector<std::string> raw_stacks;
int current = 0;
const db::NetTracerTechnologyComponent *tech_component = dynamic_cast <const db::NetTracerTechnologyComponent *> (tech->component_by_name (db::net_tracer_component_name ()));
if (tech_component) {
for (auto d = tech_component->begin (); d != tech_component->end (); ++d) {
raw_stacks.push_back (d->name ());
if (d->name () == current_stack) {
current = stacks.size ();
}
if (d->name ().empty ()) {
stacks.push_back (tr ("(default)"));
} else {
stacks.push_back (tl::to_qstring (d->name ()));
}
}
}
if (raw_stacks.empty ()) {
return;
}
current_stack = raw_stacks.front ();
if (stacks.size () >= 2) {
bool ok = true;
QString sel = QInputDialog::getItem (parentWidget (), tr ("Select Stack for Net Tracing (All Nets)"), tr ("Stack"), stacks, current, false, &ok);
if (! ok) {
return;
}
current = stacks.indexOf (sel);
if (current < 0) {
return;
}
current_stack = raw_stacks [current];
}
db::NetTracerData tracer_data;
if (! get_net_tracer_setup (cv, tracer_data)) {
if (! get_net_tracer_setup_from_tech (tech->name (), current_stack, cv->layout (), tracer_data)) {
return;
}
tracer_data.configure_l2n (*l2ndb);
std::string description = flat ? tl::to_string (tr ("Flat nets")) : tl::to_string (tr ("Hierarchical nets"));
std::string name = flat ? "Flat_Nets" : "Hierarchical_Nets";
if (! tech->name ().empty ()) {
description += ", ";
description += tl::to_string (tr ("Technology"));
description += ": ";
description += tech->name ();
name += "_";
name += tech->name ();
}
if (! current_stack.empty ()) {
description += ", ";
description += tl::to_string (tr ("Stack"));
description += ": ";
description += current_stack;
name += "_";
name += current_stack;
}
l2ndb->set_description (description);
l2ndb->set_name (name);
l2ndb->clear_join_nets ();
l2ndb->clear_join_net_names ();

View File

@ -127,6 +127,7 @@ private:
void release_mouse ();
db::NetTracerNet *do_trace (const db::DBox &start_search_box, const db::DBox &stop_search_box, bool trace_path);
bool get_net_tracer_setup (const lay::CellView &cv, db::NetTracerData &data);
static bool get_net_tracer_setup_from_tech (const std::string &tech_name, const std::string &stack_name, const db::Layout &layout, db::NetTracerData &data);
void trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView &cv, bool flat);
lay::LayoutViewBase *view ()

View File

@ -32,19 +32,12 @@
#include "tlUnitTest.h"
#include "tlStream.h"
#include "tlEnv.h"
int run_pymodtest (tl::TestBase *_this, const std::string &fn)
{
static std::string pypath;
if (pypath.empty ()) {
pypath = "PYTHONPATH=";
pypath += STRINGIFY (PYTHONPATH);
}
#if defined(_WIN32)
_putenv (const_cast<char *> (pypath.c_str ()));
#else
putenv (const_cast<char *> (pypath.c_str ()));
#endif
std::string pypath = STRINGIFY (PYTHONPATH);
tl::set_env ("PYTHONPATH", pypath);
tl::info << pypath;
std::string fp (tl::testdata ());

View File

@ -137,6 +137,7 @@ RUBYTEST (dbTilingProcessorTest, "dbTilingProcessorTest.rb")
RUBYTEST (dbTransTest, "dbTransTest.rb")
RUBYTEST (dbVectorTest, "dbVectorTest.rb")
RUBYTEST (dbUtilsTests, "dbUtilsTests.rb")
RUBYTEST (dbTechnologies, "dbTechnologies.rb")
RUBYTEST (edtTest, "edtTest.rb")
RUBYTEST (extNetTracer, "extNetTracer.rb")
RUBYTEST (imgObject, "imgObject.rb")
@ -147,7 +148,6 @@ RUBYTEST (layMacro, "layMacro.rb")
RUBYTEST (layMenuTest, "layMenuTest.rb")
RUBYTEST (layPixelBuffer, "layPixelBuffer.rb")
RUBYTEST (laySession, "laySession.rb")
RUBYTEST (layTechnologies, "layTechnologies.rb")
RUBYTEST (laySaveLayoutOptions, "laySaveLayoutOptions.rb")
#if defined(HAVE_QT) && defined(HAVE_QTBINDINGS)
RUBYTEST (qtbinding, "qtbinding.rb")

View File

@ -23,6 +23,7 @@
#include "tlEnv.h"
#include "tlString.h"
#include "tlThreads.h"
#include <string>
@ -38,8 +39,17 @@
namespace tl
{
static tl::Mutex *s_env_lock = 0;
static std::map<std::string, std::string> s_env_map;
std::string get_env (const std::string &name, const std::string &def_value)
{
if (! s_env_lock) {
s_env_lock = new tl::Mutex ();
}
tl::MutexLocker env_locker (s_env_lock);
#ifdef _WIN32
std::wstring wname = tl::to_wstring (name);
wchar_t *env = _wgetenv (wname.c_str ());
@ -58,8 +68,54 @@ std::string get_env (const std::string &name, const std::string &def_value)
#endif
}
void set_env (const std::string &name, const std::string &value)
{
if (! s_env_lock) {
s_env_lock = new tl::Mutex ();
}
tl::MutexLocker env_locker (s_env_lock);
s_env_map [name] = name + "=" + value;
const std::string &s = s_env_map [name];
#if defined(_WIN32)
_putenv (const_cast<char *> (s.c_str ()));
#else
putenv (const_cast<char *> (s.c_str ()));
#endif
}
void unset_env (const std::string &name)
{
if (! s_env_lock) {
s_env_lock = new tl::Mutex ();
}
tl::MutexLocker env_locker (s_env_lock);
#if defined(_WIN32)
s_env_map [name] = name + "=";
#else
s_env_map [name] = name;
#endif
const std::string &s = s_env_map [name];
#if defined(_WIN32)
_putenv (const_cast<char *> (s.c_str ()));
#else
putenv (const_cast<char *> (s.c_str ()));
#endif
}
bool has_env (const std::string &name)
{
if (! s_env_lock) {
s_env_lock = new tl::Mutex ();
}
tl::MutexLocker env_locker (s_env_lock);
#ifdef _WIN32
std::wstring wname = tl::to_wstring (name);
wchar_t *env = _wgetenv (wname.c_str ());

View File

@ -38,6 +38,16 @@ namespace tl
*/
std::string TL_PUBLIC get_env (const std::string &name, const std::string &def_value = std::string ());
/**
* @brief Sets the value for the given environment variable
*/
void TL_PUBLIC set_env (const std::string &name, const std::string &value);
/**
* @brief Removes the given environment variable
*/
void TL_PUBLIC unset_env (const std::string &name);
/**
* @brief Gets the value if the given environment variable is set
*/

View File

@ -27,6 +27,7 @@
#include "tlProgress.h"
#include "tlStaticObjects.h"
#include "tlLog.h"
#include "tlEnv.h"
#include <git2.h>
#include <cstdio>
@ -314,6 +315,16 @@ GitObject::read (const std::string &org_url, const std::string &org_filter, cons
fetch_opts.callbacks.credentials = &credentials_cb;
fetch_opts.callbacks.payload = (void *) &progress;
// get proxy configuration from environment variable if available
// (see https://www.klayout.de/forum/discussion/2404)
std::string http_proxy = tl::get_env ("KLAYOUT_GIT_HTTP_PROXY");
if (! http_proxy.empty ()) {
fetch_opts.proxy_opts.type = GIT_PROXY_SPECIFIED;
fetch_opts.proxy_opts.url = http_proxy.c_str ();
}
// build refspecs in case they are needed
char *refs[] = { (char *) branch.c_str () };

View File

@ -0,0 +1,45 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2023 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 "tlEnv.h"
#include "tlUnitTest.h"
const char *dne_name = "__DOES_NOT_EXIST__";
TEST(1)
{
EXPECT_EQ (tl::has_env (dne_name), false);
tl::set_env (dne_name, "123");
EXPECT_EQ (tl::has_env (dne_name), true);
EXPECT_EQ (tl::get_env (dne_name), "123");
tl::set_env (dne_name, "42");
EXPECT_EQ (tl::has_env (dne_name), true);
EXPECT_EQ (tl::get_env (dne_name), "42");
tl::unset_env (dne_name);
EXPECT_EQ (tl::get_env (dne_name, "bla"), "bla");
EXPECT_EQ (tl::has_env (dne_name), false);
}

View File

@ -16,6 +16,7 @@ SOURCES = \
tlDataMappingTests.cc \
tlDeferredExecutionTests.cc \
tlDeflateTests.cc \
tlEnvTests.cc \
tlEventsTests.cc \
tlExpressionTests.cc \
tlFileSystemWatcherTests.cc \

BIN
testdata/algo/cheats.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/cheats_au.gds vendored Normal file

Binary file not shown.

BIN
testdata/algo/cheats_edges_au.gds vendored Normal file

Binary file not shown.

BIN
testdata/drc/cheats.gds vendored Normal file

Binary file not shown.

View File

@ -61,6 +61,7 @@ class DBEdgePair_TestClass < TestBase
ep = RBA::EdgePair::new(RBA::Edge::new(0, 0, 10, 0), RBA::Edge::new(0, 20, 0, 0))
assert_equal(ep.distance, 0)
assert_equal(ep.perimeter, 30)
assert_equal(ep.area, 100)
assert_equal(ep.simple_polygon(0).area, 100)
@ -71,6 +72,10 @@ class DBEdgePair_TestClass < TestBase
assert_equal(ep.area, 0)
assert_equal(ep.simple_polygon(0).area, 0)
ep = RBA::EdgePair::new(RBA::Edge::new(0, 0, 10, 0), RBA::Edge::new(-10, 10, 20, 10))
assert_equal(ep.distance, 10)
end
# Basics
@ -108,6 +113,7 @@ class DBEdgePair_TestClass < TestBase
ep = RBA::DEdgePair::new(RBA::DEdge::new(0, 0, 10, 0), RBA::DEdge::new(0, 20, 0, 0))
assert_equal(ep.distance, 0)
assert_equal(ep.perimeter, 30)
assert_equal(ep.area, 100)
assert_equal(ep.simple_polygon(0).area, 100)
@ -118,6 +124,10 @@ class DBEdgePair_TestClass < TestBase
assert_equal(ep.area, 0)
assert_equal(ep.simple_polygon(0).area, 0)
ep = RBA::DEdgePair::new(RBA::DEdge::new(0, 0, 10, 0), RBA::DEdge::new(-10, 10, 20, 10))
assert_equal(ep.distance, 10)
end
# Fuzzy compare

View File

@ -111,6 +111,9 @@ class DBEdge_TestClass < TestBase
assert_equal( a.intersect?( RBA::DEdge::new( -1, 11, 1, 15 ) ), false )
assert_equal( a.distance( RBA::DPoint::new( 3, 3 ) ), 1.0 )
assert_equal( a.distance( RBA::DPoint::new( 3, 1 ) ), -1.0 )
assert_equal( a.euclidian_distance( RBA::DPoint::new( 3, 3 ) ), 1.0 )
assert_equal( a.euclidian_distance( RBA::DPoint::new( 3, 1 ) ), 1.0 )
assert_equal( a.euclidian_distance( RBA::DPoint::new( -3, 2 ) ), 1.0 )
assert_equal( a.distance_abs( RBA::DPoint::new( 3, 3 ) ), 1.0 )
assert_equal( a.distance_abs( RBA::DPoint::new( 3, 1 ) ), 1.0 )
assert_equal( a.side_of( RBA::DPoint::new( 3, 3 ) ), 1 )
@ -224,10 +227,13 @@ class DBEdge_TestClass < TestBase
assert_equal( a.intersection_point( RBA::Edge::new( RBA::Point::new( -1, -1 ), RBA::Point::new( 1, 5 ) ) ).to_s, "0,2" )
assert_equal( a.intersection_point( RBA::Edge::new( RBA::Point::new( -1, 3 ), RBA::Point::new( 1, 5 ) ) ) == nil, true )
assert_equal( a.intersect?( RBA::Edge::new( RBA::Point::new( -1, 11 ), RBA::Point::new( 1, 15 ) ) ), false )
assert_equal( a.distance( RBA::Point::new( 3, 3 ) ), 1.0 )
assert_equal( a.distance( RBA::Point::new( 3, 1 ) ), -1.0 )
assert_equal( a.distance_abs( RBA::Point::new( 3, 3 ) ), 1.0 )
assert_equal( a.distance_abs( RBA::Point::new( 3, 1 ) ), 1.0 )
assert_equal( a.distance( RBA::Point::new( 3, 3 ) ), 1 )
assert_equal( a.distance( RBA::Point::new( 3, 1 ) ), -1 )
assert_equal( a.euclidian_distance( RBA::Point::new( 3, 4 ) ), 2 )
assert_equal( a.euclidian_distance( RBA::Point::new( 3, 0 ) ), 2 )
assert_equal( a.euclidian_distance( RBA::Point::new( -4, 2 ) ), 2 )
assert_equal( a.distance_abs( RBA::Point::new( 3, 3 ) ), 1 )
assert_equal( a.distance_abs( RBA::Point::new( 3, 1 ) ), 1 )
assert_equal( a.side_of( RBA::Point::new( 3, 3 ) ), 1 )
assert_equal( a.side_of( RBA::Point::new( 3, 1 ) ), -1 )

View File

@ -73,6 +73,16 @@ END
RBA::Technology::remove_technology("MINE2")
assert_equal(RBA::Technology::technology_names.inspect, '[""]')
# registration
tech = RBA::Technology::new
tech.name = "NEW"
tech.dbu = 0.5
tech_new = RBA::Technology::register_technology(tech)
tech._destroy
assert_equal(RBA::Technology::technology_names.inspect, '["", "NEW"]')
assert_equal(tech_new.dbu, 0.5)
assert_equal(tech_new.name, "NEW")
end
def test_2