mirror of https://github.com/KLayout/klayout.git
commit
92eccb1d7d
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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}"
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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", ®ister_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"
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 ()) {
|
||||
|
|
|
|||
|
|
@ -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 ()));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
|
|
|
|||
|
|
@ -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 ()) {
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ()
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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 () };
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ SOURCES = \
|
|||
tlDataMappingTests.cc \
|
||||
tlDeferredExecutionTests.cc \
|
||||
tlDeflateTests.cc \
|
||||
tlEnvTests.cc \
|
||||
tlEventsTests.cc \
|
||||
tlExpressionTests.cc \
|
||||
tlFileSystemWatcherTests.cc \
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 )
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Reference in New Issue