mirror of https://github.com/KLayout/klayout.git
WIP: Hierarchical production of error db's. Needs testing.
This commit is contained in:
parent
dd4fcd9e36
commit
2d9a3aaaa6
|
|
@ -463,7 +463,7 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
|
|||
|
||||
db::BoolAndOrNotLocalOperation op (and_op);
|
||||
|
||||
db::local_processor<db::PolygonRef> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
|
||||
proc.set_base_verbosity (base_verbosity ());
|
||||
proc.set_threads (m_deep_layer.store ()->threads ());
|
||||
proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -42,12 +42,12 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
template <class T> class local_processor;
|
||||
template <class T> class local_processor_cell_context;
|
||||
template <class T> class local_processor_contexts;
|
||||
template <class TS, class TI> class local_processor;
|
||||
template <class TS, class TI> class local_processor_cell_context;
|
||||
template <class TS, class TI> class local_processor_contexts;
|
||||
|
||||
// TODO: move this somewhere else?
|
||||
template <class T>
|
||||
template <class TS, class TI>
|
||||
class DB_PUBLIC shape_interactions
|
||||
{
|
||||
public:
|
||||
|
|
@ -67,12 +67,15 @@ public:
|
|||
return m_interactions.end ();
|
||||
}
|
||||
|
||||
bool has_shape_id (unsigned int id) const;
|
||||
void add_shape (unsigned int id, const T &shape);
|
||||
void add_subject (unsigned int id, const T &shape);
|
||||
bool has_intruder_shape_id (unsigned int id) const;
|
||||
bool has_subject_shape_id (unsigned int id) const;
|
||||
void add_intruder_shape (unsigned int id, const TI &shape);
|
||||
void add_subject_shape (unsigned int id, const TS &shape);
|
||||
void add_subject (unsigned int id, const TS &shape);
|
||||
void add_interaction (unsigned int subject_id, unsigned int intruder_id);
|
||||
const std::vector<unsigned int> &intruders_for (unsigned int subject_id) const;
|
||||
const T &shape (unsigned int id) const;
|
||||
const TS &subject_shape (unsigned int id) const;
|
||||
const TI &intruder_shape (unsigned int id) const;
|
||||
|
||||
unsigned int next_id ()
|
||||
{
|
||||
|
|
@ -81,45 +84,46 @@ public:
|
|||
|
||||
private:
|
||||
std::unordered_map<unsigned int, std::vector<unsigned int> > m_interactions;
|
||||
std::unordered_map<unsigned int, T> m_shapes;
|
||||
std::unordered_map<unsigned int, TS> m_subject_shapes;
|
||||
std::unordered_map<unsigned int, TI> m_intruder_shapes;
|
||||
unsigned int m_id;
|
||||
};
|
||||
|
||||
// TODO: should be hidden (private data?)
|
||||
template <class T>
|
||||
template <class TS, class TI>
|
||||
struct DB_PUBLIC local_processor_cell_drop
|
||||
{
|
||||
local_processor_cell_drop (db::local_processor_cell_context<T> *_parent_context, db::Cell *_parent, const db::ICplxTrans &_cell_inst)
|
||||
local_processor_cell_drop (db::local_processor_cell_context<TS, TI> *_parent_context, db::Cell *_parent, const db::ICplxTrans &_cell_inst)
|
||||
: parent_context (_parent_context), parent (_parent), cell_inst (_cell_inst)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
db::local_processor_cell_context<T> *parent_context;
|
||||
db::local_processor_cell_context<TS, TI> *parent_context;
|
||||
db::Cell *parent;
|
||||
db::ICplxTrans cell_inst;
|
||||
};
|
||||
|
||||
// TODO: should be hidden (private data?)
|
||||
template <class T>
|
||||
template <class TS, class TI>
|
||||
class DB_PUBLIC local_processor_cell_context
|
||||
{
|
||||
public:
|
||||
typedef std::pair<const db::Cell *, db::ICplxTrans> parent_inst_type;
|
||||
typedef typename std::vector<local_processor_cell_drop<T> >::const_iterator drop_iterator;
|
||||
typedef typename std::vector<local_processor_cell_drop<TS, TI> >::const_iterator drop_iterator;
|
||||
|
||||
local_processor_cell_context ();
|
||||
local_processor_cell_context (const local_processor_cell_context &other);
|
||||
|
||||
void add (db::local_processor_cell_context<T> *parent_context, db::Cell *parent, const db::ICplxTrans &cell_inst);
|
||||
void propagate (const std::unordered_set<T> &res);
|
||||
void add (db::local_processor_cell_context<TS, TI> *parent_context, db::Cell *parent, const db::ICplxTrans &cell_inst);
|
||||
void propagate (const std::unordered_set<TS> &res);
|
||||
|
||||
std::unordered_set<T> &propagated ()
|
||||
std::unordered_set<TS> &propagated ()
|
||||
{
|
||||
return m_propagated;
|
||||
}
|
||||
|
||||
const std::unordered_set<T> &propagated () const
|
||||
const std::unordered_set<TS> &propagated () const
|
||||
{
|
||||
return m_propagated;
|
||||
}
|
||||
|
|
@ -147,25 +151,25 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
std::unordered_set<T> m_propagated;
|
||||
std::vector<local_processor_cell_drop<T> > m_drops;
|
||||
std::unordered_set<TS> m_propagated;
|
||||
std::vector<local_processor_cell_drop<TS, TI> > m_drops;
|
||||
tl::Mutex m_lock;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <class TS, class TI>
|
||||
class DB_PUBLIC local_processor_cell_contexts
|
||||
{
|
||||
public:
|
||||
typedef std::pair<std::set<CellInstArray>, std::set<T> > context_key_type;
|
||||
typedef std::unordered_map<context_key_type, db::local_processor_cell_context<T> > context_map_type;
|
||||
typedef std::pair<std::set<CellInstArray>, std::set<TI> > context_key_type;
|
||||
typedef std::unordered_map<context_key_type, db::local_processor_cell_context<TS, TI> > context_map_type;
|
||||
typedef typename context_map_type::const_iterator iterator;
|
||||
|
||||
local_processor_cell_contexts ();
|
||||
local_processor_cell_contexts (const db::Cell *intruder_cell);
|
||||
|
||||
db::local_processor_cell_context<T> *find_context (const context_key_type &intruders);
|
||||
db::local_processor_cell_context<T> *create (const context_key_type &intruders);
|
||||
void compute_results (const local_processor_contexts<T> &contexts, db::Cell *cell, const local_operation<T> *op, unsigned int output_layer, const local_processor<T> *proc);
|
||||
db::local_processor_cell_context<TS, TI> *find_context (const context_key_type &intruders);
|
||||
db::local_processor_cell_context<TS, TI> *create (const context_key_type &intruders);
|
||||
void compute_results (const local_processor_contexts<TS, TI> &contexts, db::Cell *cell, const local_operation<TS, TI> *op, unsigned int output_layer, const local_processor<TS, TI> *proc);
|
||||
|
||||
iterator begin () const
|
||||
{
|
||||
|
|
@ -179,14 +183,14 @@ public:
|
|||
|
||||
private:
|
||||
const db::Cell *mp_intruder_cell;
|
||||
std::unordered_map<context_key_type, db::local_processor_cell_context<T> > m_contexts;
|
||||
std::unordered_map<context_key_type, db::local_processor_cell_context<TS, TI> > m_contexts;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <class TS, class TI>
|
||||
class DB_PUBLIC local_processor_contexts
|
||||
{
|
||||
public:
|
||||
typedef std::unordered_map<db::Cell *, local_processor_cell_contexts<T> > contexts_per_cell_type;
|
||||
typedef std::unordered_map<db::Cell *, local_processor_cell_contexts<TS, TI> > contexts_per_cell_type;
|
||||
typedef typename contexts_per_cell_type::iterator iterator;
|
||||
|
||||
local_processor_contexts ()
|
||||
|
|
@ -206,11 +210,11 @@ public:
|
|||
m_contexts_per_cell.clear ();
|
||||
}
|
||||
|
||||
local_processor_cell_contexts<T> &contexts_per_cell (db::Cell *subject_cell, const db::Cell *intruder_cell)
|
||||
local_processor_cell_contexts<TS, TI> &contexts_per_cell (db::Cell *subject_cell, const db::Cell *intruder_cell)
|
||||
{
|
||||
typename contexts_per_cell_type::iterator ctx = m_contexts_per_cell.find (subject_cell);
|
||||
if (ctx == m_contexts_per_cell.end ()) {
|
||||
ctx = m_contexts_per_cell.insert (std::make_pair (subject_cell, local_processor_cell_contexts<T> (intruder_cell))).first;
|
||||
ctx = m_contexts_per_cell.insert (std::make_pair (subject_cell, local_processor_cell_contexts<TS, TI> (intruder_cell))).first;
|
||||
}
|
||||
return ctx->second;
|
||||
}
|
||||
|
|
@ -261,27 +265,27 @@ private:
|
|||
mutable tl::Mutex m_lock;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <class TS, class TI>
|
||||
class DB_PUBLIC local_processor_context_computation_task
|
||||
: public tl::Task
|
||||
{
|
||||
public:
|
||||
local_processor_context_computation_task (const local_processor<T> *proc, local_processor_contexts<T> &contexts, db::local_processor_cell_context<T> *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, typename local_processor_cell_contexts<T>::context_key_type &intruders, db::Coord dist);
|
||||
local_processor_context_computation_task (const local_processor<TS, TI> *proc, local_processor_contexts<TS, TI> &contexts, db::local_processor_cell_context<TS, TI> *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, typename local_processor_cell_contexts<TS, TI>::context_key_type &intruders, db::Coord dist);
|
||||
void perform ();
|
||||
|
||||
private:
|
||||
const local_processor<T> *mp_proc;
|
||||
local_processor_contexts<T> *mp_contexts;
|
||||
db::local_processor_cell_context<T> *mp_parent_context;
|
||||
const local_processor<TS, TI> *mp_proc;
|
||||
local_processor_contexts<TS, TI> *mp_contexts;
|
||||
db::local_processor_cell_context<TS, TI> *mp_parent_context;
|
||||
db::Cell *mp_subject_parent;
|
||||
db::Cell *mp_subject_cell;
|
||||
db::ICplxTrans m_subject_cell_inst;
|
||||
const db::Cell *mp_intruder_cell;
|
||||
typename local_processor_cell_contexts<T>::context_key_type m_intruders;
|
||||
typename local_processor_cell_contexts<TS, TI>::context_key_type m_intruders;
|
||||
db::Coord m_dist;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <class TS, class TI>
|
||||
class DB_PUBLIC local_processor_context_computation_worker
|
||||
: public tl::Worker
|
||||
{
|
||||
|
|
@ -294,28 +298,28 @@ public:
|
|||
|
||||
void perform_task (tl::Task *task)
|
||||
{
|
||||
static_cast<local_processor_context_computation_task<T> *> (task)->perform ();
|
||||
static_cast<local_processor_context_computation_task<TS, TI> *> (task)->perform ();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <class TS, class TI>
|
||||
class DB_PUBLIC local_processor_result_computation_task
|
||||
: public tl::Task
|
||||
{
|
||||
public:
|
||||
local_processor_result_computation_task (const local_processor<T> *proc, local_processor_contexts<T> &contexts, db::Cell *cell, local_processor_cell_contexts<T> *cell_contexts, const local_operation<T> *op, unsigned int output_layer);
|
||||
local_processor_result_computation_task (const local_processor<TS, TI> *proc, local_processor_contexts<TS, TI> &contexts, db::Cell *cell, local_processor_cell_contexts<TS, TI> *cell_contexts, const local_operation<TS, TI> *op, unsigned int output_layer);
|
||||
void perform ();
|
||||
|
||||
private:
|
||||
const local_processor<T> *mp_proc;
|
||||
local_processor_contexts<T> *mp_contexts;
|
||||
const local_processor<TS, TI> *mp_proc;
|
||||
local_processor_contexts<TS, TI> *mp_contexts;
|
||||
db::Cell *mp_cell;
|
||||
local_processor_cell_contexts<T> *mp_cell_contexts;
|
||||
const local_operation<T> *mp_op;
|
||||
local_processor_cell_contexts<TS, TI> *mp_cell_contexts;
|
||||
const local_operation<TS, TI> *mp_op;
|
||||
unsigned int m_output_layer;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <class TS, class TI>
|
||||
class DB_PUBLIC local_processor_result_computation_worker
|
||||
: public tl::Worker
|
||||
{
|
||||
|
|
@ -328,19 +332,19 @@ public:
|
|||
|
||||
void perform_task (tl::Task *task)
|
||||
{
|
||||
static_cast<local_processor_result_computation_task<T> *> (task)->perform ();
|
||||
static_cast<local_processor_result_computation_task<TS, TI> *> (task)->perform ();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <class TS, class TI>
|
||||
class DB_PUBLIC local_processor
|
||||
{
|
||||
public:
|
||||
local_processor (db::Layout *layout, db::Cell *top);
|
||||
local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell);
|
||||
void run (local_operation<T> *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer);
|
||||
void compute_contexts (local_processor_contexts<T> &contexts, const local_operation<T> *op, unsigned int subject_layer, unsigned int intruder_layer) const;
|
||||
void compute_results (local_processor_contexts<T> &contexts, const local_operation<T> *op, unsigned int output_layer) const;
|
||||
void run (local_operation<TS, TI> *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer);
|
||||
void compute_contexts (local_processor_contexts<TS, TI> &contexts, const local_operation<TS, TI> *op, unsigned int subject_layer, unsigned int intruder_layer) const;
|
||||
void compute_results (local_processor_contexts<TS, TI> &contexts, const local_operation<TS, TI> *op, unsigned int output_layer) const;
|
||||
|
||||
void set_description (const std::string &d)
|
||||
{
|
||||
|
|
@ -388,8 +392,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
template<typename> friend class local_processor_cell_contexts;
|
||||
template<typename> friend class local_processor_context_computation_task;
|
||||
template<typename, typename> friend class local_processor_cell_contexts;
|
||||
template<typename, typename> friend class local_processor_context_computation_task;
|
||||
|
||||
db::Layout *mp_subject_layout;
|
||||
const db::Layout *mp_intruder_layout;
|
||||
|
|
@ -400,14 +404,14 @@ private:
|
|||
size_t m_max_vertex_count;
|
||||
double m_area_ratio;
|
||||
int m_base_verbosity;
|
||||
mutable std::auto_ptr<tl::Job<local_processor_context_computation_worker<T> > > mp_cc_job;
|
||||
mutable std::auto_ptr<tl::Job<local_processor_context_computation_worker<TS, TI> > > mp_cc_job;
|
||||
|
||||
std::string description (const local_operation<T> *op) const;
|
||||
void compute_contexts (db::local_processor_contexts<T> &contexts, db::local_processor_cell_context<T> *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const typename local_processor_cell_contexts<T>::context_key_type &intruders, db::Coord dist) const;
|
||||
void do_compute_contexts (db::local_processor_cell_context<T> *cell_context, const db::local_processor_contexts<T> &contexts, db::local_processor_cell_context<T> *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const typename local_processor_cell_contexts<T>::context_key_type &intruders, db::Coord dist) const;
|
||||
void issue_compute_contexts (db::local_processor_contexts<T> &contexts, db::local_processor_cell_context<T> *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, typename local_processor_cell_contexts<T>::context_key_type &intruders, db::Coord dist) const;
|
||||
void push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set<T> &result) const;
|
||||
void compute_local_cell (const db::local_processor_contexts<T> &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation<T> *op, const typename local_processor_cell_contexts<T>::context_key_type &intruders, std::unordered_set<T> &result) const;
|
||||
std::string description (const local_operation<TS, TI> *op) const;
|
||||
void compute_contexts (db::local_processor_contexts<TS, TI> &contexts, db::local_processor_cell_context<TS, TI> *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const typename local_processor_cell_contexts<TS, TI>::context_key_type &intruders, db::Coord dist) const;
|
||||
void do_compute_contexts (db::local_processor_cell_context<TS, TI> *cell_context, const db::local_processor_contexts<TS, TI> &contexts, db::local_processor_cell_context<TS, TI> *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const typename local_processor_cell_contexts<TS, TI>::context_key_type &intruders, db::Coord dist) const;
|
||||
void issue_compute_contexts (db::local_processor_contexts<TS, TI> &contexts, db::local_processor_cell_context<TS, TI> *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, typename local_processor_cell_contexts<TS, TI>::context_key_type &intruders, db::Coord dist) const;
|
||||
void push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set<TS> &result) const;
|
||||
void compute_local_cell (const db::local_processor_contexts<TS, TI> &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation<TS, TI> *op, const typename local_processor_cell_contexts<TS, TI>::context_key_type &intruders, std::unordered_set<TS> &result) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -415,8 +419,8 @@ private:
|
|||
namespace tl
|
||||
{
|
||||
|
||||
template <class T>
|
||||
struct type_traits<db::local_processor<T> > : public tl::type_traits<void>
|
||||
template <class TS, class TI>
|
||||
struct type_traits<db::local_processor<TS, TI> > : public tl::type_traits<void>
|
||||
{
|
||||
// mark "LocalProcessor" as not having a default ctor and no copy ctor
|
||||
typedef tl::false_tag has_default_constructor;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ BoolAndOrNotLocalOperation::BoolAndOrNotLocalOperation (bool is_and)
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
local_operation<db::PolygonRef>::on_empty_intruder_mode
|
||||
local_operation<db::PolygonRef, db::PolygonRef>::on_empty_intruder_mode
|
||||
BoolAndOrNotLocalOperation::on_empty_intruder_hint () const
|
||||
{
|
||||
return m_is_and ? local_operation::Drop : local_operation::Copy;
|
||||
|
|
@ -58,22 +58,22 @@ BoolAndOrNotLocalOperation::description () const
|
|||
}
|
||||
|
||||
void
|
||||
BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t max_vertex_count, double area_ratio) const
|
||||
BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
db::EdgeProcessor ep;
|
||||
|
||||
size_t p1 = 0, p2 = 1;
|
||||
|
||||
std::set<db::PolygonRef> others;
|
||||
for (shape_interactions<db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.shape (*j));
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
others.insert (interactions.intruder_shape (*j));
|
||||
}
|
||||
}
|
||||
|
||||
for (shape_interactions<db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
const db::PolygonRef &subject = interactions.shape (i->first);
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
if (others.find (subject) != others.end ()) {
|
||||
if (m_is_and) {
|
||||
result.insert (subject);
|
||||
|
|
@ -119,7 +119,7 @@ SelfOverlapMergeLocalOperation::SelfOverlapMergeLocalOperation (unsigned int wra
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t /*max_vertex_count*/, double /*area_ratio*/) const
|
||||
{
|
||||
if (m_wrap_count == 0) {
|
||||
return;
|
||||
|
|
@ -130,23 +130,23 @@ void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const sh
|
|||
size_t p1 = 0, p2 = 1;
|
||||
std::set<unsigned int> seen;
|
||||
|
||||
for (shape_interactions<db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
for (shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = interactions.begin (); i != interactions.end (); ++i) {
|
||||
|
||||
if (seen.find (i->first) == seen.end ()) {
|
||||
seen.insert (i->first);
|
||||
const db::PolygonRef &subject = interactions.shape (i->first);
|
||||
const db::PolygonRef &subject = interactions.subject_shape (i->first);
|
||||
for (db::PolygonRef::polygon_edge_iterator e = subject.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p1);
|
||||
}
|
||||
p1 += 2;
|
||||
}
|
||||
|
||||
for (db::shape_interactions<db::PolygonRef>::iterator2 o = i->second.begin (); o != i->second.end (); ++o) {
|
||||
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 o = i->second.begin (); o != i->second.end (); ++o) {
|
||||
// don't take the same (really the same, not an identical one) shape twice - the interaction
|
||||
// set does not take care to list just one copy of the same item on the intruder side.
|
||||
if (seen.find (*o) == seen.end ()) {
|
||||
seen.insert (*o);
|
||||
const db::PolygonRef &intruder = interactions.shape (*o);
|
||||
const db::PolygonRef &intruder = interactions.intruder_shape (*o);
|
||||
for (db::PolygonRef::polygon_edge_iterator e = intruder.begin_edge (); ! e.at_end(); ++e) {
|
||||
ep.insert (*e, p2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
template <class T> class shape_interactions;
|
||||
template <class TS, class TI> class shape_interactions;
|
||||
|
||||
/**
|
||||
* @brief A base class for "local operations"
|
||||
|
|
@ -49,7 +49,7 @@ template <class T> class shape_interactions;
|
|||
* This class implements the actual operation. It receives a
|
||||
* cluster of subject shapes vs. corresponding intruder shapes.
|
||||
*/
|
||||
template <class T>
|
||||
template <class TS, class TI>
|
||||
class DB_PUBLIC local_operation
|
||||
{
|
||||
public:
|
||||
|
|
@ -89,7 +89,7 @@ public:
|
|||
* @param interactions The interaction set
|
||||
* @param result The container to which the results are written
|
||||
*/
|
||||
virtual void compute_local (db::Layout *layout, const shape_interactions<T> &interactions, std::unordered_set<T> &result, size_t max_vertex_count, double area_ratio) const = 0;
|
||||
virtual void compute_local (db::Layout *layout, const shape_interactions<TS, TI> &interactions, std::unordered_set<TS> &result, size_t max_vertex_count, double area_ratio) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Indicates the desired behaviour when a shape does not have an intruder
|
||||
|
|
@ -112,12 +112,12 @@ public:
|
|||
* @brief Implements a boolean AND or NOT operation
|
||||
*/
|
||||
class DB_PUBLIC BoolAndOrNotLocalOperation
|
||||
: public local_operation<db::PolygonRef>
|
||||
: public local_operation<db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
BoolAndOrNotLocalOperation (bool is_and);
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual void compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
|
|
@ -131,12 +131,12 @@ private:
|
|||
* the original shapes overlap at least "wrap_count" times.
|
||||
*/
|
||||
class DB_PUBLIC SelfOverlapMergeLocalOperation
|
||||
: public local_operation<db::PolygonRef>
|
||||
: public local_operation<db::PolygonRef, db::PolygonRef>
|
||||
{
|
||||
public:
|
||||
SelfOverlapMergeLocalOperation (unsigned int wrap_count);
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual void compute_local (db::Layout *layout, const shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t max_vertex_count, double area_ratio) const;
|
||||
virtual on_empty_intruder_mode on_empty_intruder_hint () const;
|
||||
virtual std::string description () const;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,15 +55,15 @@ public:
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const db::shape_interactions<db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t max_vertex_count, double area_ratio) const
|
||||
virtual void compute_local (db::Layout *layout, const db::shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
db::shape_interactions<db::PolygonRef> sized_interactions = interactions;
|
||||
for (db::shape_interactions<db::PolygonRef>::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) {
|
||||
for (db::shape_interactions<db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
const db::PolygonRef &ref = interactions.shape (*j);
|
||||
db::shape_interactions<db::PolygonRef, db::PolygonRef> sized_interactions = interactions;
|
||||
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) {
|
||||
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
const db::PolygonRef &ref = interactions.intruder_shape (*j);
|
||||
db::Polygon poly = ref.obj ().transformed (ref.trans ());
|
||||
poly.size (m_dist, m_dist);
|
||||
sized_interactions.add_shape (*j, db::PolygonRef (poly, layout->shape_repository ()));
|
||||
sized_interactions.add_intruder_shape (*j, db::PolygonRef (poly, layout->shape_repository ()));
|
||||
}
|
||||
}
|
||||
BoolAndOrNotLocalOperation::compute_local (layout, sized_interactions, result, max_vertex_count, area_ratio);
|
||||
|
|
@ -91,21 +91,21 @@ public:
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void compute_local (db::Layout *layout, const db::shape_interactions<db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t max_vertex_count, double area_ratio) const
|
||||
virtual void compute_local (db::Layout *layout, const db::shape_interactions<db::PolygonRef, db::PolygonRef> &interactions, std::unordered_set<db::PolygonRef> &result, size_t max_vertex_count, double area_ratio) const
|
||||
{
|
||||
db::shape_interactions<db::PolygonRef> sized_interactions = interactions;
|
||||
for (db::shape_interactions<db::PolygonRef>::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) {
|
||||
db::shape_interactions<db::PolygonRef, db::PolygonRef> sized_interactions = interactions;
|
||||
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) {
|
||||
|
||||
const db::PolygonRef &ref = interactions.shape (i->first);
|
||||
const db::PolygonRef &ref = interactions.subject_shape (i->first);
|
||||
db::Polygon poly = ref.obj ().transformed (ref.trans ());
|
||||
poly.size (m_dist / 2, m_dist / 2);
|
||||
sized_interactions.add_shape (i->first, db::PolygonRef (poly, layout->shape_repository ()));
|
||||
sized_interactions.add_subject_shape (i->first, db::PolygonRef (poly, layout->shape_repository ()));
|
||||
|
||||
for (db::shape_interactions<db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
const db::PolygonRef &ref = interactions.shape (*j);
|
||||
for (db::shape_interactions<db::PolygonRef, db::PolygonRef>::iterator2 j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
const db::PolygonRef &ref = interactions.intruder_shape (*j);
|
||||
db::Polygon poly = ref.obj ().transformed (ref.trans ());
|
||||
poly.size (m_dist / 2, m_dist / 2);
|
||||
sized_interactions.add_shape (*j, db::PolygonRef (poly, layout->shape_repository ()));
|
||||
sized_interactions.add_intruder_shape (*j, db::PolygonRef (poly, layout->shape_repository ()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -140,15 +140,15 @@ static void normalize_layer (db::Layout &layout, unsigned int layer)
|
|||
}
|
||||
|
||||
|
||||
static std::string contexts_to_s (db::Layout *layout, db::local_processor_contexts<db::PolygonRef> &contexts)
|
||||
static std::string contexts_to_s (db::Layout *layout, db::local_processor_contexts<db::PolygonRef, db::PolygonRef> &contexts)
|
||||
{
|
||||
std::string res;
|
||||
|
||||
for (db::Layout::top_down_const_iterator i = layout->begin_top_down (); i != layout->end_top_down(); ++i) {
|
||||
db::local_processor_contexts<db::PolygonRef>::iterator cc = contexts.context_map ().find (&layout->cell (*i));
|
||||
db::local_processor_contexts<db::PolygonRef, db::PolygonRef>::iterator cc = contexts.context_map ().find (&layout->cell (*i));
|
||||
if (cc != contexts.context_map ().end ()) {
|
||||
int index = 1;
|
||||
for (db::local_processor_cell_contexts<db::PolygonRef>::iterator j = cc->second.begin (); j != cc->second.end (); ++j) {
|
||||
for (db::local_processor_cell_contexts<db::PolygonRef, db::PolygonRef>::iterator j = cc->second.begin (); j != cc->second.end (); ++j) {
|
||||
res += tl::sprintf ("%s[%d] %d insts, %d shapes (%d times)\n", layout->cell_name (*i), index, int (j->first.first.size ()), int (j->first.second.size ()), int (j->second.size ()));
|
||||
index += 1;
|
||||
}
|
||||
|
|
@ -203,7 +203,7 @@ static void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode m
|
|||
normalize_layer (layout_org, l2);
|
||||
}
|
||||
|
||||
db::local_operation<db::PolygonRef> *lop = 0;
|
||||
db::local_operation<db::PolygonRef, db::PolygonRef> *lop = 0;
|
||||
db::BoolAndOrNotLocalOperation bool_op (mode == TMAnd || mode == TMAndSwapped);
|
||||
db::SelfOverlapMergeLocalOperation self_intersect_op (2);
|
||||
BoolAndOrNotWithSizedLocalOperation sized_bool_op (mode == TMAnd || mode == TMAndSwapped, dist);
|
||||
|
|
@ -224,7 +224,7 @@ static void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode m
|
|||
|
||||
if (single) {
|
||||
|
||||
db::local_processor<db::PolygonRef> proc (&layout_org, &layout_org.cell (*layout_org.begin_top_down ()));
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef> proc (&layout_org, &layout_org.cell (*layout_org.begin_top_down ()));
|
||||
proc.set_threads (nthreads);
|
||||
proc.set_area_ratio (3.0);
|
||||
proc.set_max_vertex_count (16);
|
||||
|
|
@ -232,7 +232,7 @@ static void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode m
|
|||
if (! context_doc) {
|
||||
proc.run (lop, l1, l2, lout);
|
||||
} else {
|
||||
db::local_processor_contexts<db::PolygonRef> contexts;
|
||||
db::local_processor_contexts<db::PolygonRef, db::PolygonRef> contexts;
|
||||
proc.compute_contexts (contexts, lop, l1, l2);
|
||||
*context_doc = contexts_to_s (&layout_org, contexts);
|
||||
proc.compute_results (contexts, lop, lout);
|
||||
|
|
@ -242,7 +242,7 @@ static void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode m
|
|||
|
||||
db::Layout layout_org2 = layout_org;
|
||||
|
||||
db::local_processor<db::PolygonRef> proc (&layout_org, &layout_org.cell (*layout_org.begin_top_down ()), &layout_org2, &layout_org2.cell (*layout_org2.begin_top_down ()));
|
||||
db::local_processor<db::PolygonRef, db::PolygonRef> proc (&layout_org, &layout_org.cell (*layout_org.begin_top_down ()), &layout_org2, &layout_org2.cell (*layout_org2.begin_top_down ()));
|
||||
proc.set_threads (nthreads);
|
||||
proc.set_area_ratio (3.0);
|
||||
proc.set_max_vertex_count (16);
|
||||
|
|
@ -250,7 +250,7 @@ static void run_test_bool_gen (tl::TestBase *_this, const char *file, TestMode m
|
|||
if (! context_doc) {
|
||||
proc.run (lop, l1, l2, lout);
|
||||
} else {
|
||||
db::local_processor_contexts<db::PolygonRef> contexts;
|
||||
db::local_processor_contexts<db::PolygonRef, db::PolygonRef> contexts;
|
||||
proc.compute_contexts (contexts, lop, l1, l2);
|
||||
*context_doc = contexts_to_s (&layout_org, contexts);
|
||||
proc.compute_results (contexts, lop, lout);
|
||||
|
|
|
|||
|
|
@ -267,9 +267,27 @@ static void scan_layer3 (rdb::Category *cat, const db::Layout &layout, unsigned
|
|||
rdb::scan_layer (cat, layout, layer, from_cell, levels);
|
||||
}
|
||||
|
||||
static void scan_shapes (rdb::Category *cat, const db::RecursiveShapeIterator &iter)
|
||||
static void scan_shapes (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat)
|
||||
{
|
||||
rdb::scan_layer (cat, iter);
|
||||
rdb::scan_layer (cat, iter, flat);
|
||||
}
|
||||
|
||||
static void scan_region (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Region ®ion, bool flat)
|
||||
{
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = region.begin_iter ();
|
||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat);
|
||||
}
|
||||
|
||||
static void scan_edges (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Edges &edges, bool flat)
|
||||
{
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = edges.begin_iter ();
|
||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat);
|
||||
}
|
||||
|
||||
static void scan_edge_pairs (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::EdgePairs &edge_pairs, bool flat)
|
||||
{
|
||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it; /* @@@ = edges.begin_iter (); */
|
||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat);
|
||||
}
|
||||
|
||||
Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
|
||||
|
|
@ -289,13 +307,41 @@ Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.23."
|
||||
) +
|
||||
gsi::method_ext ("scan_shapes", &scan_shapes,
|
||||
gsi::method_ext ("scan_shapes", &scan_shapes, gsi::arg ("iter"), gsi::arg ("flat", false),
|
||||
"@brief Scans the polygon or edge shapes from the shape iterator into the category\n"
|
||||
"@args iter\n"
|
||||
"Creates RDB items for each polygon or edge shape read from the iterator and puts them into this category.\n"
|
||||
"A similar, but lower-level method is \\ReportDatabase#create_items with a \\RecursiveShapeIterator argument.\n"
|
||||
"In contrast to \\ReportDatabase#create_items, 'scan_shapes' can also produce hierarchical databases "
|
||||
"if the \\flat argument is false. In this case, the hierarchy the recursive shape iterator traverses is "
|
||||
"copied into the report database using sample references.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
"This method has been introduced in version 0.23. The flat mode argument has been added in version 0.26.\n"
|
||||
) +
|
||||
gsi::method_ext ("scan_region", &scan_region, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("region"), gsi::arg ("flat", false),
|
||||
"@brief Turns the given region into a hierarchical or flat report database\n"
|
||||
"The exact behavior depends on the nature of the region. If the region is a hierarchical (original or deep) region "
|
||||
"and the 'flat' argument is false, this method will produce a hierarchical report database in the given category. "
|
||||
"The 'cell_id' parameter is ignored in this case. Sample references will be produced to supply "
|
||||
"minimal instantiation information.\n"
|
||||
"\n"
|
||||
"If the region is a flat one or the 'flat' argument is true, the region's polygons will be produced as "
|
||||
"report database items in this category and in the cell given by 'cell_id'.\n"
|
||||
"\n"
|
||||
"The transformation argument needs to supply the dbu-to-micron transformation.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.\n"
|
||||
) +
|
||||
gsi::method_ext ("scan_edges", &scan_edges, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edges"), gsi::arg ("flat", false),
|
||||
"@brief Turns the given edge collection into a hierarchical or flat report database\n"
|
||||
"This method behaves like the \\scan_region method, except that is accepts an edge collection.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.\n"
|
||||
) +
|
||||
gsi::method_ext ("scan_edge_pairs", &scan_edge_pairs, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edge_pairs"), gsi::arg ("flat", false),
|
||||
"@brief Turns the given edge pair collection into a hierarchical or flat report database\n"
|
||||
"This method behaves like the \\scan_region method, except that is accepts an edge pair collection.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.\n"
|
||||
) +
|
||||
gsi::method_ext ("scan_layer", &scan_layer1,
|
||||
"@brief Scans a layer from a layout into this category\n"
|
||||
|
|
@ -966,98 +1012,19 @@ void database_set_tag_description (rdb::Database *db, rdb::id_type tag, const st
|
|||
db->set_tag_description (tag, d);
|
||||
}
|
||||
|
||||
void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter)
|
||||
{
|
||||
tl_assert (iter.layout ());
|
||||
double dbu = iter.layout ()->dbu ();
|
||||
|
||||
for (db::RecursiveShapeIterator i = iter; !i.at_end (); ++i) {
|
||||
std::auto_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*i, db::CplxTrans (dbu) * i.trans ()));
|
||||
if (value.get ()) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (value.release ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes)
|
||||
{
|
||||
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::All); !s.at_end (); ++s) {
|
||||
std::auto_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*s, trans));
|
||||
if (value.get ()) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (value.release ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape)
|
||||
{
|
||||
std::auto_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (shape, trans));
|
||||
if (value.get ()) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (value.release ());
|
||||
}
|
||||
}
|
||||
|
||||
void create_items_from_region (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Region &collection)
|
||||
{
|
||||
typedef db::Region::const_iterator iter;
|
||||
|
||||
for (iter o = collection.begin (); ! o.at_end (); ++o) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (new rdb::Value <db::DPolygon> (o->transformed (trans)));
|
||||
}
|
||||
}
|
||||
|
||||
void create_items_from_edges (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Edges &collection)
|
||||
{
|
||||
typedef db::Edges::const_iterator iter;
|
||||
|
||||
for (iter o = collection.begin (); ! o.at_end (); ++o) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (new rdb::Value <db::DEdge> (o->transformed (trans)));
|
||||
}
|
||||
}
|
||||
|
||||
void create_items_from_edge_pairs (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::EdgePairs &collection)
|
||||
{
|
||||
typedef db::EdgePairs::const_iterator iter;
|
||||
|
||||
for (iter o = collection.begin (); ! o.at_end (); ++o) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (new rdb::Value <db::DEdgePair> (o->transformed (trans)));
|
||||
}
|
||||
}
|
||||
|
||||
void create_items_from_polygon_array (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const std::vector<db::Polygon> &collection)
|
||||
{
|
||||
typedef std::vector<db::Polygon>::const_iterator iter;
|
||||
|
||||
for (iter o = collection.begin (); o != collection.end (); ++o) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (new rdb::Value <db::DPolygon> (o->transformed (trans)));
|
||||
}
|
||||
rdb::create_items_from_sequence (db, cell_id, cat_id, trans, collection.begin (), collection.end ());
|
||||
}
|
||||
|
||||
void create_items_from_edge_array (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const std::vector<db::Edge> &collection)
|
||||
{
|
||||
typedef std::vector<db::Edge>::const_iterator iter;
|
||||
|
||||
for (iter o = collection.begin (); o != collection.end (); ++o) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (new rdb::Value <db::DEdge> (o->transformed (trans)));
|
||||
}
|
||||
rdb::create_items_from_sequence (db, cell_id, cat_id, trans, collection.begin (), collection.end ());
|
||||
}
|
||||
|
||||
void create_items_from_edge_pair_array (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const std::vector<db::EdgePair> &collection)
|
||||
{
|
||||
typedef std::vector<db::EdgePair>::const_iterator iter;
|
||||
|
||||
for (iter o = collection.begin (); o != collection.end (); ++o) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (new rdb::Value <db::DEdgePair> (o->transformed (trans)));
|
||||
}
|
||||
rdb::create_items_from_sequence (db, cell_id, cat_id, trans, collection.begin (), collection.end ());
|
||||
}
|
||||
|
||||
static rdb::Item *create_item (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id)
|
||||
|
|
@ -1081,9 +1048,8 @@ static rdb::Item *create_item_from_objects (rdb::Database *db, rdb::Cell *cell,
|
|||
}
|
||||
|
||||
Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
||||
gsi::constructor ("new", &create_rdb,
|
||||
gsi::constructor ("new", &create_rdb, gsi::arg ("name"),
|
||||
"@brief Creates a report database\n"
|
||||
"@args name\n"
|
||||
"@param name The name of the database\n"
|
||||
"The name of the database will be used in the user interface to refer to a certain database."
|
||||
) +
|
||||
|
|
@ -1093,9 +1059,8 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"in a human-readable form.\n"
|
||||
"@return The description string\n"
|
||||
) +
|
||||
gsi::method ("description=", &rdb::Database::set_description,
|
||||
gsi::method ("description=", &rdb::Database::set_description, gsi::arg ("desc"),
|
||||
"@brief Sets the databases description\n"
|
||||
"@args desc\n"
|
||||
"@param desc The description string\n"
|
||||
) +
|
||||
gsi::method ("generator", &rdb::Database::generator,
|
||||
|
|
@ -1104,9 +1069,8 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"In a later version this should allow to rerun the tool that created the report.\n"
|
||||
"@return The generator string\n"
|
||||
) +
|
||||
gsi::method ("generator=", &rdb::Database::set_generator,
|
||||
gsi::method ("generator=", &rdb::Database::set_generator, gsi::arg ("generator"),
|
||||
"@brief Sets the generator string\n"
|
||||
"@args generator\n"
|
||||
"@param generator The generator string\n"
|
||||
) +
|
||||
gsi::method ("filename", &rdb::Database::filename,
|
||||
|
|
@ -1126,9 +1090,8 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"This property must be set to establish a proper hierarchical context for a hierarchical report database. "
|
||||
"@return The top cell name\n"
|
||||
) +
|
||||
gsi::method ("top_cell_name=", &rdb::Database::set_top_cell_name,
|
||||
gsi::method ("top_cell_name=", &rdb::Database::set_top_cell_name, gsi::arg ("cell_name"),
|
||||
"@brief Sets the top cell name string\n"
|
||||
"@args cell_name\n"
|
||||
"@param cell_name The top cell name\n"
|
||||
) +
|
||||
gsi::method ("original_file", &rdb::Database::original_file,
|
||||
|
|
@ -1136,14 +1099,12 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"The original file name is supposed to describe the file from which this report database was generated. "
|
||||
"@return The original file name and path\n"
|
||||
) +
|
||||
gsi::method ("original_file=", &rdb::Database::set_original_file,
|
||||
gsi::method ("original_file=", &rdb::Database::set_original_file, gsi::arg ("path"),
|
||||
"@brief Sets the original file name and path\n"
|
||||
"@args path\n"
|
||||
"@param path The path\n"
|
||||
) +
|
||||
gsi::method_ext ("tag_id", &database_tag_id,
|
||||
gsi::method_ext ("tag_id", &database_tag_id, gsi::arg ("name"),
|
||||
"@brief Gets the tag ID for a given tag name\n"
|
||||
"@args name\n"
|
||||
"@param name The tag name\n"
|
||||
"@return The corresponding tag ID\n"
|
||||
"Tags are used to tag items in the database and to specify tagged (named) values. "
|
||||
|
|
@ -1153,9 +1114,8 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"\n"
|
||||
"\\tag_id handles system tags while \\user_tag_id handles user tags.\n"
|
||||
) +
|
||||
gsi::method_ext ("user_tag_id", &database_user_tag_id,
|
||||
gsi::method_ext ("user_tag_id", &database_user_tag_id, gsi::arg ("name"),
|
||||
"@brief Gets the tag ID for a given user tag name\n"
|
||||
"@args name\n"
|
||||
"@param name The user tag name\n"
|
||||
"@return The corresponding tag ID\n"
|
||||
"This method will always succeed and the tag will be created if it does not exist yet. "
|
||||
|
|
@ -1163,23 +1123,20 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"\n"
|
||||
"This method has been added in version 0.24.\n"
|
||||
) +
|
||||
gsi::method_ext ("set_tag_description", &database_set_tag_description,
|
||||
gsi::method_ext ("set_tag_description", &database_set_tag_description, gsi::arg ("tag_id"), gsi::arg ("description"),
|
||||
"@brief Sets the tag description for the given tag ID\n"
|
||||
"@args tag_id, description\n"
|
||||
"@param tag_id The ID of the tag\n"
|
||||
"@param description The description string\n"
|
||||
"See \\tag_id for a details about tags.\n"
|
||||
) +
|
||||
gsi::method_ext ("tag_description", &database_tag_description,
|
||||
gsi::method_ext ("tag_description", &database_tag_description, gsi::arg ("tag_id"),
|
||||
"@brief Gets the tag description for the given tag ID\n"
|
||||
"@args tag_id\n"
|
||||
"@param tag_id The ID of the tag\n"
|
||||
"@return The description string\n"
|
||||
"See \\tag_id for a details about tags.\n"
|
||||
) +
|
||||
gsi::method_ext ("tag_name", &database_tag_name,
|
||||
gsi::method_ext ("tag_name", &database_tag_name, gsi::arg ("tag_id"),
|
||||
"@brief Gets the tag name for the given tag ID\n"
|
||||
"@args tag_id\n"
|
||||
"@param tag_id The ID of the tag\n"
|
||||
"@return The name of the tag\n"
|
||||
"See \\tag_id for a details about tags.\n\n"
|
||||
|
|
@ -1188,54 +1145,45 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
gsi::iterator_ext ("each_category", &database_begin_categories, &database_end_categories,
|
||||
"@brief Iterates over all top-level categories\n"
|
||||
) +
|
||||
gsi::method ("create_category", (rdb::Category *(rdb::Database::*) (const std::string &)) &rdb::Database::create_category,
|
||||
gsi::method ("create_category", (rdb::Category *(rdb::Database::*) (const std::string &)) &rdb::Database::create_category, gsi::arg ("name"),
|
||||
"@brief Creates a new top level category\n"
|
||||
"@args name\n"
|
||||
"@param name The name of the category\n"
|
||||
) +
|
||||
gsi::method ("create_category", (rdb::Category *(rdb::Database::*) (rdb::Category *, const std::string &)) &rdb::Database::create_category,
|
||||
gsi::method ("create_category", (rdb::Category *(rdb::Database::*) (rdb::Category *, const std::string &)) &rdb::Database::create_category, gsi::arg ("parent"), gsi::arg ("name"),
|
||||
"@brief Creates a new sub-category\n"
|
||||
"@args parent,name\n"
|
||||
"@param parent The category under which the category should be created\n"
|
||||
"@param name The name of the category\n"
|
||||
) +
|
||||
gsi::method ("category_by_path", &rdb::Database::category_by_name,
|
||||
gsi::method ("category_by_path", &rdb::Database::category_by_name, gsi::arg ("path"),
|
||||
"@brief Gets a category by path\n"
|
||||
"@args path\n"
|
||||
"@param path The full path to the category starting from the top level (subcategories separated by dots)\n"
|
||||
"@return The (const) category object or nil if the name is not valid\n"
|
||||
) +
|
||||
gsi::method ("category_by_id", &rdb::Database::category_by_id,
|
||||
gsi::method ("category_by_id", &rdb::Database::category_by_id, gsi::arg ("id"),
|
||||
"@brief Gets a category by ID\n"
|
||||
"@args id\n"
|
||||
"@return The (const) category object or nil if the ID is not valid\n"
|
||||
) +
|
||||
gsi::method ("create_cell", (rdb::Cell *(rdb::Database::*) (const std::string &)) &rdb::Database::create_cell,
|
||||
gsi::method ("create_cell", (rdb::Cell *(rdb::Database::*) (const std::string &)) &rdb::Database::create_cell, gsi::arg ("name"),
|
||||
"@brief Creates a new cell\n"
|
||||
"@args name\n"
|
||||
"@param name The name of the cell\n"
|
||||
) +
|
||||
gsi::method ("create_cell", (rdb::Cell *(rdb::Database::*) (const std::string &, const std::string &)) &rdb::Database::create_cell,
|
||||
gsi::method ("create_cell", (rdb::Cell *(rdb::Database::*) (const std::string &, const std::string &)) &rdb::Database::create_cell, gsi::arg ("name"), gsi::arg ("variant"),
|
||||
"@brief Creates a new cell, potentially as a variant for a cell with the same name\n"
|
||||
"@args name, variant\n"
|
||||
"@param name The name of the cell\n"
|
||||
"@param variant The variant name of the cell\n"
|
||||
) +
|
||||
gsi::method ("variants", &rdb::Database::variants,
|
||||
gsi::method ("variants", &rdb::Database::variants, gsi::arg ("name"),
|
||||
"@brief Gets the variants for a given cell name\n"
|
||||
"@args name\n"
|
||||
"@param name The basic name of the cell\n"
|
||||
"@return An array of ID's representing cells that are variants for the given base name\n"
|
||||
) +
|
||||
gsi::method ("cell_by_qname", &rdb::Database::cell_by_qname,
|
||||
gsi::method ("cell_by_qname", &rdb::Database::cell_by_qname, gsi::arg ("qname"),
|
||||
"@brief Returns the cell for a given qualified name\n"
|
||||
"@args qname\n"
|
||||
"@param qname The qualified name of the cell (name plus variant name optionally)\n"
|
||||
"@return The cell object or nil if no such cell exists\n"
|
||||
) +
|
||||
gsi::method ("cell_by_id", &rdb::Database::cell_by_id,
|
||||
gsi::method ("cell_by_id", &rdb::Database::cell_by_id, gsi::arg ("id"),
|
||||
"@brief Returns the cell for a given ID\n"
|
||||
"@args id\n"
|
||||
"@param id The ID of the cell\n"
|
||||
"@return The cell object or nil if no cell with that ID exists\n"
|
||||
) +
|
||||
|
|
@ -1281,12 +1229,13 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"\n"
|
||||
"This convenience method has been added in version 0.25.\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &create_items_from_iterator, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("iter"),
|
||||
gsi::method_ext ("create_items", &rdb::create_items_from_iterator, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("iter"),
|
||||
"@brief Creates new items from a shape iterator\n"
|
||||
"This method takes the shapes from the given iterator and produces items from them.\n"
|
||||
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
|
||||
"converts them to corresponding items. "
|
||||
"A similar method, which is intended for production of polygon or edge error layers is \\RdbCategory#scan_shapes.\n"
|
||||
"converts them to corresponding items. This method will produce a flat version of the shapes iterated by the shape iterator. "
|
||||
"A similar method, which is intended for production of polygon or edge error layers and also provides hierarchical database "
|
||||
"construction is \\RdbCategory#scan_shapes.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.25.3.\n"
|
||||
"\n"
|
||||
|
|
@ -1294,7 +1243,7 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
"@param iter The iterator (a \\RecursiveShapeIterator object) from which to take the items\n"
|
||||
) +
|
||||
gsi::method_ext ("create_item", &create_item_from_shape, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shape"),
|
||||
gsi::method_ext ("create_item", &rdb::create_item_from_shape, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shape"),
|
||||
"@brief Creates a new item from a single shape\n"
|
||||
"This method produces an item from the given shape.\n"
|
||||
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
|
||||
|
|
@ -1308,7 +1257,7 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"@param shape The shape to take the geometrical object from\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &create_items_from_shapes, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shapes"),
|
||||
gsi::method_ext ("create_items", &rdb::create_items_from_shapes, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shapes"),
|
||||
"@brief Creates new items from a shape container\n"
|
||||
"This method takes the shapes from the given container and produces items from them.\n"
|
||||
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
|
||||
|
|
@ -1322,52 +1271,61 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"@param shapes The shape container from which to take the items\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &create_items_from_region,
|
||||
gsi::method_ext ("create_items", &rdb::create_items_from_region, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("region"),
|
||||
"@brief Creates new polygon items for the given cell/category combination\n"
|
||||
"For each polygon in the region a single item will be created. The value of the item will be this "
|
||||
"polygon.\n"
|
||||
"A transformation can be supplied which can be used for example to convert the "
|
||||
"object's dimensions to micron units by scaling by the database unit.\n"
|
||||
"\n"
|
||||
"This method will also produce a flat version of the shapes inside the region. "
|
||||
"\\RdbCategory#scan_region is a similar method which also supports construction of "
|
||||
"hierarchical databases from deep regions.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
"\n"
|
||||
"@args cell_id, category_id, trans, polygons\n"
|
||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
"@param region The region (a \\Region object) containing the polygons for which to create items\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &create_items_from_edges,
|
||||
gsi::method_ext ("create_items", &rdb::create_items_from_edges, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("edges"),
|
||||
"@brief Creates new edge items for the given cell/category combination\n"
|
||||
"For each edge a single item will be created. The value of the item will be this "
|
||||
"edge.\n"
|
||||
"A transformation can be supplied which can be used for example to convert the "
|
||||
"object's dimensions to micron units by scaling by the database unit.\n"
|
||||
"\n"
|
||||
"This method will also produce a flat version of the edges inside the edge collection. "
|
||||
"\\RdbCategory#scan_edges is a similar method which also supports construction of "
|
||||
"hierarchical databases from deep edge collections.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
"\n"
|
||||
"@args cell_id, category_id, trans, edges\n"
|
||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
"@param edges The list of edges (an \\Edges object) for which the items are created\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &create_items_from_edge_pairs,
|
||||
gsi::method_ext ("create_items", &rdb::create_items_from_edge_pairs, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("edge_pairs"),
|
||||
"@brief Creates new edge pair items for the given cell/category combination\n"
|
||||
"For each edge pair a single item will be created. The value of the item will be this "
|
||||
"edge pair.\n"
|
||||
"A transformation can be supplied which can be used for example to convert the "
|
||||
"object's dimensions to micron units by scaling by the database unit.\n"
|
||||
"\n"
|
||||
"This method will also produce a flat version of the edge pairs inside the edge pair collection. "
|
||||
"\\RdbCategory#scan_edge_pairs is a similar method which also supports construction of "
|
||||
"hierarchical databases from deep edge pair collections.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
"\n"
|
||||
"@args cell_id, category_id, trans, edge_pairs\n"
|
||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
"@param edges The list of edge pairs (an \\EdgePairs object) for which the items are created\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &create_items_from_polygon_array,
|
||||
gsi::method_ext ("create_items", &create_items_from_polygon_array, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("array"),
|
||||
"@brief Creates new polygon items for the given cell/category combination\n"
|
||||
"For each polygon a single item will be created. The value of the item will be this "
|
||||
"polygon.\n"
|
||||
|
|
@ -1376,13 +1334,12 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
"\n"
|
||||
"@args cell_id, category_id, trans, polygons\n"
|
||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
"@param polygons The list of polygons for which the items are created\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &create_items_from_edge_array,
|
||||
gsi::method_ext ("create_items", &create_items_from_edge_array, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("array"),
|
||||
"@brief Creates new edge items for the given cell/category combination\n"
|
||||
"For each edge a single item will be created. The value of the item will be this "
|
||||
"edge.\n"
|
||||
|
|
@ -1391,13 +1348,12 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
"\n"
|
||||
"@args cell_id, category_id, trans, edges\n"
|
||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
"@param edges The list of edges for which the items are created\n"
|
||||
) +
|
||||
gsi::method_ext ("create_items", &create_items_from_edge_pair_array,
|
||||
gsi::method_ext ("create_items", &create_items_from_edge_pair_array, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("array"),
|
||||
"@brief Creates new edge pair items for the given cell/category combination\n"
|
||||
"For each edge pair a single item will be created. The value of the item will be this "
|
||||
"edge pair.\n"
|
||||
|
|
@ -1406,7 +1362,6 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
|||
"\n"
|
||||
"This method has been introduced in version 0.23.\n"
|
||||
"\n"
|
||||
"@args cell_id, category_id, trans, edge_pairs\n"
|
||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||
"@param category_id The ID of the category to which the item is associated\n"
|
||||
"@param trans The transformation to apply\n"
|
||||
|
|
|
|||
|
|
@ -520,6 +520,15 @@ private:
|
|||
C m_value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Type bindings
|
||||
*/
|
||||
template <class T>
|
||||
RDB_PUBLIC ValueBase *make_value (const T &value)
|
||||
{
|
||||
return new Value<T> (value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A class encapsulating ValueBase pointer
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -26,11 +26,14 @@
|
|||
#include "dbLayout.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "dbRecursiveShapeIterator.h"
|
||||
#include "dbRegion.h"
|
||||
#include "dbEdges.h"
|
||||
#include "dbEdgePairs.h"
|
||||
|
||||
namespace rdb
|
||||
{
|
||||
|
||||
RDB_PUBLIC void
|
||||
void
|
||||
scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from, int levels)
|
||||
{
|
||||
rdb::Database *rdb = cat->database ();
|
||||
|
|
@ -75,63 +78,231 @@ scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, co
|
|||
|
||||
}
|
||||
|
||||
for (db::ShapeIterator shape = cell.shapes (layer).begin (db::ShapeIterator::All); ! shape.at_end (); ++shape) {
|
||||
|
||||
if (shape->is_polygon () || shape->is_path () || shape->is_box ()) {
|
||||
|
||||
db::Polygon poly;
|
||||
shape->polygon (poly);
|
||||
rdb::Item *item = rdb->create_item (rdb_cell->id (), cat->id ());
|
||||
item->values ().add (new rdb::Value <db::DPolygon> (poly.transformed (db::CplxTrans (layout.dbu ()))));
|
||||
|
||||
} else if (shape->is_edge ()) {
|
||||
|
||||
db::Edge edge;
|
||||
shape->edge (edge);
|
||||
rdb::Item *item = rdb->create_item (rdb_cell->id (), cat->id ());
|
||||
item->values ().add (new rdb::Value <db::DEdge> (edge.transformed (db::CplxTrans (layout.dbu ()))));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
create_items_from_shapes (rdb, rdb_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()), cell.shapes (layer));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RDB_PUBLIC void
|
||||
scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter)
|
||||
namespace
|
||||
{
|
||||
|
||||
class CreateItemsRecursiveReceiver
|
||||
: public db::RecursiveShapeReceiver
|
||||
{
|
||||
public:
|
||||
CreateItemsRecursiveReceiver (rdb::Category *cat, const db::CplxTrans &trans, rdb::Cell *cell)
|
||||
: mp_cat (cat), mp_rdb (cat->database ()), m_trans (trans), mp_rdb_cell (cell)
|
||||
{
|
||||
// just in case the iterator is non-hierarchical
|
||||
if (cell) {
|
||||
m_cell_stack.push_back (cell);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void begin (const db::RecursiveShapeIterator *iter)
|
||||
{
|
||||
m_cell_stack.clear ();
|
||||
|
||||
db::cell_index_type ci = iter->top_cell ()->cell_index ();
|
||||
const rdb::Cell *rdb_cell = cell_for_id (iter->layout (), ci);
|
||||
m_cell_stack.push_back (rdb_cell);
|
||||
m_id_to_cell.insert (std::make_pair (ci, rdb_cell));
|
||||
}
|
||||
|
||||
virtual void end (const db::RecursiveShapeIterator *)
|
||||
{
|
||||
m_cell_stack.pop_back ();
|
||||
}
|
||||
|
||||
virtual void enter_cell (const db::RecursiveShapeIterator *iter, const db::Cell *cell, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||
{
|
||||
db::cell_index_type ci = cell->cell_index ();
|
||||
const rdb::Cell *rdb_cell = cell_for_id (iter->layout (), ci);
|
||||
m_cell_stack.push_back (rdb_cell);
|
||||
m_id_to_cell.insert (std::make_pair (ci, rdb_cell));
|
||||
|
||||
if (rdb_cell->references ().begin () == rdb_cell->references ().end ()) {
|
||||
db::DCplxTrans t = m_trans * iter->trans () * m_trans.inverted ();
|
||||
// TODO: get rid of the const_cast
|
||||
(const_cast<rdb::Cell *> (rdb_cell))->references ().insert (rdb::Reference (t, m_cell_stack.front ()->id ()));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void leave_cell (const db::RecursiveShapeIterator * /*iter*/, const db::Cell * /*cell*/)
|
||||
{
|
||||
m_cell_stack.pop_back ();
|
||||
}
|
||||
|
||||
virtual new_inst_mode new_inst (const db::RecursiveShapeIterator * /*iter*/, const db::CellInstArray &inst, const db::Box & /*region*/, const box_tree_type * /*complex_region*/, bool /*all*/)
|
||||
{
|
||||
db::cell_index_type ci = inst.object ().cell_index ();
|
||||
if (m_id_to_cell.find (ci) != m_id_to_cell.end ()) {
|
||||
return NI_skip;
|
||||
} else {
|
||||
return NI_single;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void shape (const db::RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans & /*trans*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||
{
|
||||
tl_assert (! m_cell_stack.empty ());
|
||||
create_item_from_shape (mp_rdb, m_cell_stack.back ()->id (), mp_cat->id (), m_trans, shape);
|
||||
}
|
||||
|
||||
public:
|
||||
rdb::Category *mp_cat;
|
||||
rdb::Database *mp_rdb;
|
||||
std::vector<const rdb::Cell *> m_cell_stack;
|
||||
std::map<db::cell_index_type, const rdb::Cell *> m_id_to_cell;
|
||||
db::CplxTrans m_trans;
|
||||
rdb::Cell *mp_rdb_cell;
|
||||
|
||||
const rdb::Cell *cell_for_id (const db::Layout *layout, db::cell_index_type ci)
|
||||
{
|
||||
tl_assert (layout != 0);
|
||||
std::string cn = layout->cell_name (ci);
|
||||
const rdb::Cell *rdb_cell = mp_rdb->cell_by_qname (cn);
|
||||
if (! rdb_cell) {
|
||||
return mp_rdb->create_cell (cn);
|
||||
} else {
|
||||
return rdb_cell;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CreateItemsFlatReceiver
|
||||
: public db::RecursiveShapeReceiver
|
||||
{
|
||||
public:
|
||||
CreateItemsFlatReceiver (rdb::Category *cat, const db::CplxTrans &trans, rdb::Cell *cell)
|
||||
: mp_cat (cat), mp_rdb (cat->database ()), m_trans (trans), mp_rdb_cell (cell)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void begin (const db::RecursiveShapeIterator *iter)
|
||||
{
|
||||
if (! mp_rdb_cell) {
|
||||
|
||||
db::cell_index_type ci = iter->top_cell ()->cell_index ();
|
||||
|
||||
tl_assert (iter->layout () != 0);
|
||||
std::string cn = iter->layout ()->cell_name (ci);
|
||||
mp_rdb_cell = mp_rdb->cell_by_qname (cn);
|
||||
if (! mp_rdb_cell) {
|
||||
mp_rdb_cell = mp_rdb->create_cell (cn);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
virtual void shape (const db::RecursiveShapeIterator *iter, const db::Shape &shape, const db::ICplxTrans & /*trans*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||
{
|
||||
create_item_from_shape (mp_rdb, mp_rdb_cell->id (), mp_cat->id (), m_trans * iter->trans (), shape);
|
||||
}
|
||||
|
||||
public:
|
||||
rdb::Category *mp_cat;
|
||||
rdb::Database *mp_rdb;
|
||||
db::CplxTrans m_trans;
|
||||
const rdb::Cell *mp_rdb_cell;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat)
|
||||
{
|
||||
if (! iter.top_cell () || ! iter.layout ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
rdb::Database *rdb = cat->database ();
|
||||
if (! rdb) {
|
||||
db::CplxTrans trans (iter.layout ()->dbu ());
|
||||
scan_layer (cat, 0, trans, iter, flat);
|
||||
}
|
||||
|
||||
void
|
||||
scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::RecursiveShapeIterator &iter, bool flat)
|
||||
{
|
||||
if (! cat->database ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
rdb::Cell *rdb_cell = rdb->create_cell (iter.layout ()->cell_name (iter.top_cell ()->cell_index ()));
|
||||
std::auto_ptr<db::RecursiveShapeReceiver> rec;
|
||||
if (flat) {
|
||||
rec.reset (new CreateItemsFlatReceiver (cat, trans, cell));
|
||||
} else {
|
||||
rec.reset (new CreateItemsRecursiveReceiver (cat, trans, cell));
|
||||
}
|
||||
|
||||
for (db::RecursiveShapeIterator i = iter; ! i.at_end (); ++i) {
|
||||
db::RecursiveShapeIterator (iter).push (rec.get ());
|
||||
}
|
||||
|
||||
if (i.shape ().is_polygon () || i.shape ().is_path () || i.shape ().is_box ()) {
|
||||
// ------------------------------------------------------------------------------------------------------------
|
||||
|
||||
db::Polygon poly;
|
||||
i.shape ().polygon (poly);
|
||||
rdb::Item *item = rdb->create_item (rdb_cell->id (), cat->id ());
|
||||
item->values ().add (new rdb::Value <db::DPolygon> (poly.transformed (db::CplxTrans (iter.layout ()->dbu ()) * i.trans ())));
|
||||
|
||||
} else if (i.shape ().is_edge ()) {
|
||||
|
||||
db::Edge edge;
|
||||
i.shape ().edge (edge);
|
||||
rdb::Item *item = rdb->create_item (rdb_cell->id (), cat->id ());
|
||||
item->values ().add (new rdb::Value <db::DEdge> (edge.transformed (db::CplxTrans (iter.layout ()->dbu ()) * i.trans ())));
|
||||
void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter)
|
||||
{
|
||||
tl_assert (iter.layout ());
|
||||
double dbu = iter.layout ()->dbu ();
|
||||
|
||||
for (db::RecursiveShapeIterator i = iter; !i.at_end (); ++i) {
|
||||
std::auto_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*i, db::CplxTrans (dbu) * i.trans ()));
|
||||
if (value.get ()) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (value.release ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes)
|
||||
{
|
||||
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::All); !s.at_end (); ++s) {
|
||||
std::auto_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*s, trans));
|
||||
if (value.get ()) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (value.release ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape)
|
||||
{
|
||||
std::auto_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (shape, trans));
|
||||
if (value.get ()) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (value.release ());
|
||||
}
|
||||
}
|
||||
|
||||
void create_items_from_region (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Region &collection)
|
||||
{
|
||||
typedef db::Region::const_iterator iter;
|
||||
|
||||
for (iter o = collection.begin (); ! o.at_end (); ++o) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (new rdb::Value <db::DPolygon> (o->transformed (trans)));
|
||||
}
|
||||
}
|
||||
|
||||
void create_items_from_edges (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Edges &collection)
|
||||
{
|
||||
typedef db::Edges::const_iterator iter;
|
||||
|
||||
for (iter o = collection.begin (); ! o.at_end (); ++o) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (new rdb::Value <db::DEdge> (o->transformed (trans)));
|
||||
}
|
||||
}
|
||||
|
||||
void create_items_from_edge_pairs (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::EdgePairs &collection)
|
||||
{
|
||||
typedef db::EdgePairs::const_iterator iter;
|
||||
|
||||
for (iter o = collection.begin (); ! o.at_end (); ++o) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (new rdb::Value <db::DEdgePair> (o->transformed (trans)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,12 +26,17 @@
|
|||
|
||||
#include "rdb.h"
|
||||
#include "dbTypes.h"
|
||||
#include "dbTrans.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
class Layout;
|
||||
class Cell;
|
||||
class RecursiveShapeIterator;
|
||||
class Shapes;
|
||||
class Region;
|
||||
class Edges;
|
||||
class EdgePairs;
|
||||
}
|
||||
|
||||
namespace rdb
|
||||
|
|
@ -52,7 +57,84 @@ RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::Layout &layout, unsign
|
|||
/**
|
||||
* @brief Scans a recursive shape iterator into a RDB category
|
||||
*/
|
||||
RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter);
|
||||
RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat = false);
|
||||
|
||||
/**
|
||||
* @brief Scans a recursive shape iterator into a RDB category
|
||||
*
|
||||
* This version allows supplying a cell and a transformation. With this information, the function can also handle
|
||||
* pseudo-iterators which don't deliver the information from a layout from from a plain shape collection.
|
||||
*/
|
||||
RDB_PUBLIC void scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::RecursiveShapeIterator &iter, bool flat = false);
|
||||
|
||||
/**
|
||||
* @brief Creates RDB items from a recursive shape iterator
|
||||
*
|
||||
* This function will produce items from the flattened shape iterator. The items will be stored under
|
||||
* the given cell.
|
||||
*/
|
||||
RDB_PUBLIC void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter);
|
||||
|
||||
/**
|
||||
* @brief Creates RDB items from a shape collection
|
||||
*
|
||||
* An arbitrary transformation can be applied to translate the shapes before turning them to items.
|
||||
* This transformation is useful for providing the DBU-to-micron conversion.
|
||||
*/
|
||||
RDB_PUBLIC void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes);
|
||||
|
||||
/**
|
||||
* @brief Creates RDB items from a single shape
|
||||
*
|
||||
* An arbitrary transformation can be applied to translate the shapes before turning them to items.
|
||||
* This transformation is useful for providing the DBU-to-micron conversion.
|
||||
*/
|
||||
RDB_PUBLIC void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape);
|
||||
|
||||
/**
|
||||
* @brief Creates RDB items from a region
|
||||
*
|
||||
* This function will flatten the region and store the resulting items under the given cell.
|
||||
*
|
||||
* An arbitrary transformation can be applied to translate the shapes before turning them to items.
|
||||
* This transformation is useful for providing the DBU-to-micron conversion.
|
||||
*/
|
||||
RDB_PUBLIC void create_items_from_region (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Region &collection);
|
||||
|
||||
/**
|
||||
* @brief Creates RDB items from an edge collection
|
||||
*
|
||||
* This function will flatten the edge collection and store the resulting items under the given cell.
|
||||
*
|
||||
* An arbitrary transformation can be applied to translate the shapes before turning them to items.
|
||||
* This transformation is useful for providing the DBU-to-micron conversion.
|
||||
*/
|
||||
RDB_PUBLIC void create_items_from_edges (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Edges &collection);
|
||||
|
||||
/**
|
||||
* @brief Creates RDB items from an edge pair collection
|
||||
*
|
||||
* This function will flatten the edge pair collection and store the resulting items under the given cell.
|
||||
*
|
||||
* An arbitrary transformation can be applied to translate the shapes before turning them to items.
|
||||
* This transformation is useful for providing the DBU-to-micron conversion.
|
||||
*/
|
||||
RDB_PUBLIC void create_items_from_edge_pairs (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::EdgePairs &collection);
|
||||
|
||||
/**
|
||||
* @brief Creates RDB items from a sequence of integer-type objects
|
||||
*
|
||||
* An arbitrary transformation can be applied to translate the shapes before turning them to items.
|
||||
* This transformation is useful for providing the DBU-to-micron conversion.
|
||||
*/
|
||||
template <class Trans, class Iter>
|
||||
RDB_PUBLIC void create_items_from_sequence (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const Trans &trans, Iter begin, Iter end)
|
||||
{
|
||||
for (Iter o = begin; o != end; ++o) {
|
||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||
item->values ().add (rdb::make_value (o->transformed (trans)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -769,18 +769,18 @@ class RDB_TestClass < TestBase
|
|||
|
||||
rdb = RBA::ReportDatabase.new("neu")
|
||||
cat = rdb.create_category("l1")
|
||||
cat.scan_shapes(c1.begin_shapes_rec(l1))
|
||||
cat.scan_shapes(c1.begin_shapes_rec(l1)) # hierarchical scan
|
||||
assert_equal(cat.num_items, 3)
|
||||
cn = []
|
||||
rdb.each_cell { |c| cn << c.to_s_test }
|
||||
assert_equal(cn.join(";"), "c1[]")
|
||||
assert_equal(cn.join(";"), "c1[];c2[c1->r0 *1 0.01,0.02];c3[c1->r0 *1 0.021,0.041]")
|
||||
cn = []
|
||||
rdb.each_cell { |c| cn << c.to_s_items }
|
||||
assert_equal(cn.join(";"), "c1[polygon: (0,0.001;0,0.03;0.02,0.03;0.02,0.001),polygon: (0.01,0.021;0.01,0.051;0.031,0.051;0.031,0.021),polygon: (0.021,0.042;0.021,0.073;0.043,0.073;0.043,0.042)]")
|
||||
assert_equal(cn.join(";"), "c1[polygon: (0,0.001;0,0.03;0.02,0.03;0.02,0.001)];c2[polygon: (0,0.001;0,0.031;0.021,0.031;0.021,0.001)];c3[polygon: (0,0.001;0,0.032;0.022,0.032;0.022,0.001)]")
|
||||
|
||||
rdb = RBA::ReportDatabase.new("neu")
|
||||
cat = rdb.create_category("l1")
|
||||
cat.scan_shapes(c1.begin_shapes_rec(l1))
|
||||
cat.scan_shapes(c1.begin_shapes_rec(l1), true) # flat scan
|
||||
assert_equal(cat.num_items, 3)
|
||||
cn = []
|
||||
rdb.each_cell { |c| cn << c.to_s_test }
|
||||
|
|
|
|||
Loading…
Reference in New Issue