mirror of https://github.com/KLayout/klayout.git
WIP: cell variant collecting and building.
This commit is contained in:
parent
50c8c067d5
commit
bbf7b2768b
|
|
@ -104,16 +104,32 @@ struct DB_PUBLIC GridReducer
|
|||
|
||||
db::ICplxTrans operator () (const db::ICplxTrans &trans) const
|
||||
{
|
||||
return db::ICplxTrans (db::Vector (trans.disp ().x () % m_grid, trans.disp ().y () % m_grid));
|
||||
// NOTE: we need to keep magnification, angle and mirror so when combining the
|
||||
// reduced transformations, the result will be equivalent to reducing the combined
|
||||
// transformation.
|
||||
db::ICplxTrans res (trans);
|
||||
res.disp (db::Vector (mod (trans.disp ().x ()), mod (trans.disp ().y ())));
|
||||
return res;
|
||||
}
|
||||
|
||||
db::Trans operator () (const db::Trans &trans) const
|
||||
{
|
||||
return db::Trans (db::Vector (trans.disp ().x () % m_grid, trans.disp ().y () % m_grid));
|
||||
db::Trans res (trans);
|
||||
res.disp (db::Vector (mod (trans.disp ().x ()), mod (trans.disp ().y ())));
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
db::Coord m_grid;
|
||||
|
||||
inline db::Coord mod (db::Coord c) const
|
||||
{
|
||||
if (c < 0) {
|
||||
return m_grid - (-c) % m_grid;
|
||||
} else {
|
||||
return c % m_grid;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -132,7 +148,7 @@ private:
|
|||
*
|
||||
*/
|
||||
template <class Reduce>
|
||||
class DB_PUBLIC cell_variants_builder
|
||||
class DB_PUBLIC cell_variants_collector
|
||||
{
|
||||
public:
|
||||
typedef cell_variants_reduce_traits<Reduce> compare_traits;
|
||||
|
|
@ -140,19 +156,19 @@ public:
|
|||
/**
|
||||
* @brief Creates a variant extractor
|
||||
*/
|
||||
cell_variants_builder (const Reduce &red)
|
||||
cell_variants_collector (const Reduce &red)
|
||||
: m_red (red)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Builds cell variants for the given layout starting from the top cell
|
||||
* @brief Collects cell variants for the given layout starting from the top cell
|
||||
*/
|
||||
void build (db::Layout &layout, db::Cell &top_cell)
|
||||
void collect (db::Layout &layout, db::Cell &top_cell)
|
||||
{
|
||||
// The top cell gets a single "variant" with unit transformation
|
||||
m_variants [top_cell.cell_index ()].insert (db::ICplxTrans ());
|
||||
// The top cell gets a "variant" with unit transformation
|
||||
m_variants [top_cell.cell_index ()].insert (std::make_pair (db::ICplxTrans (), 1));
|
||||
|
||||
std::set<db::cell_index_type> called;
|
||||
top_cell.collect_called_cells (called);
|
||||
|
|
@ -165,17 +181,17 @@ public:
|
|||
|
||||
// collect the parent variants per parent cell
|
||||
|
||||
std::map<db::cell_index_type, std::set<db::ICplxTrans> > variants_per_parent_cell;
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, size_t> > variants_per_parent_cell;
|
||||
for (db::Cell::parent_inst_iterator pi = layout.cell (*c).begin_parent_insts (); ! pi.at_end (); ++pi) {
|
||||
std::set<db::ICplxTrans> &variants = variants_per_parent_cell [pi->inst ().object ().cell_index ()];
|
||||
std::map<db::ICplxTrans, size_t> &variants = variants_per_parent_cell [pi->inst ().object ().cell_index ()];
|
||||
add_variant (variants, pi->child_inst ().cell_inst (), typename compare_traits::is_translation_invariant ());
|
||||
}
|
||||
|
||||
// compute the resulting variants
|
||||
|
||||
std::set<db::ICplxTrans> &new_variants = m_variants [*c];
|
||||
std::map<db::ICplxTrans, size_t> &new_variants = m_variants [*c];
|
||||
|
||||
for (std::map<db::cell_index_type, std::set<db::ICplxTrans> >::const_iterator pv = variants_per_parent_cell.begin (); pv != variants_per_parent_cell.end (); ++pv) {
|
||||
for (std::map<db::cell_index_type, std::map<db::ICplxTrans, size_t> >::const_iterator pv = variants_per_parent_cell.begin (); pv != variants_per_parent_cell.end (); ++pv) {
|
||||
product (variants (pv->first), pv->second, new_variants);
|
||||
}
|
||||
|
||||
|
|
@ -183,12 +199,120 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the variants for a given cell
|
||||
* @brief Creates cell variants for singularization of the different variants
|
||||
*
|
||||
* After this method can been used, all cells with more than one variant are separated and
|
||||
* the corresponding instances are updated.
|
||||
*
|
||||
* If given, *var_table will be filled with a map giving the new cell and variant against
|
||||
* the old cell for all cells with more than one variant.
|
||||
*/
|
||||
const std::set<db::ICplxTrans> &variants (db::cell_index_type ci) const
|
||||
void separate_variants (db::Layout &layout, db::Cell &top_cell, std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > *var_table = 0)
|
||||
{
|
||||
std::map<db::cell_index_type, std::set<db::ICplxTrans> >::const_iterator v = m_variants.find (ci);
|
||||
static std::set<db::ICplxTrans> empty_set;
|
||||
db::LayoutLocker locker (&layout);
|
||||
|
||||
std::set<db::cell_index_type> called;
|
||||
top_cell.collect_called_cells (called);
|
||||
called.insert (top_cell.cell_index ());
|
||||
|
||||
// create new cells for the variants
|
||||
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > var_table_intern;
|
||||
if (! var_table) {
|
||||
var_table = &var_table_intern;
|
||||
}
|
||||
|
||||
for (db::Layout::bottom_up_const_iterator c = layout.begin_bottom_up (); c != layout.end_bottom_up (); ++c) {
|
||||
|
||||
if (called.find (*c) == called.end ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
db::Cell &cell = layout.cell (*c);
|
||||
|
||||
std::map<db::ICplxTrans, size_t> &vv = m_variants [*c];
|
||||
if (vv.size () > 1) {
|
||||
|
||||
std::map<db::ICplxTrans, db::cell_index_type> &vt = (*var_table) [*c];
|
||||
|
||||
std::vector<db::CellInstArrayWithProperties> inst;
|
||||
inst.reserve (cell.cell_instances ());
|
||||
|
||||
for (db::Cell::const_iterator i = cell.begin (); ! i.at_end (); ++i) {
|
||||
inst.push_back (db::CellInstArrayWithProperties (i->cell_inst (), i->prop_id ()));
|
||||
}
|
||||
|
||||
cell.clear_insts ();
|
||||
|
||||
int index = 0;
|
||||
for (std::map<db::ICplxTrans, size_t>::const_iterator v = vv.begin (); v != vv.end (); ++v, ++index) {
|
||||
|
||||
db::cell_index_type ci_var;
|
||||
|
||||
if (v != vv.begin ()) {
|
||||
|
||||
std::string var_name = layout.cell_name (*c);
|
||||
var_name += "_VAR" + tl::to_string (index);
|
||||
|
||||
ci_var = layout.add_cell (var_name.c_str ());
|
||||
copy_shapes (layout, ci_var, *c);
|
||||
|
||||
// a new entry for the variant
|
||||
m_variants [ci_var].insert (*v);
|
||||
|
||||
} else {
|
||||
ci_var = *c;
|
||||
}
|
||||
|
||||
vt.insert (std::make_pair (v->first, ci_var));
|
||||
create_var_instances (layout.cell (ci_var), inst, v->first, *var_table, typename compare_traits::is_translation_invariant ());
|
||||
|
||||
}
|
||||
|
||||
// correct the first (remaining) entry
|
||||
std::pair<db::ICplxTrans, size_t> v1 = *vt.begin ();
|
||||
vv.clear ();
|
||||
vv.insert (v1);
|
||||
|
||||
} else {
|
||||
|
||||
// if the children of this cell are separated, map the instances to the new variants
|
||||
bool needs_update = false;
|
||||
for (db::Cell::child_cell_iterator cc = cell.begin_child_cells (); ! cc.at_end () && ! needs_update; ++cc) {
|
||||
if (var_table->find (*cc) != var_table->end ()) {
|
||||
needs_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_update) {
|
||||
|
||||
std::vector<db::CellInstArrayWithProperties> inst;
|
||||
inst.reserve (cell.cell_instances ());
|
||||
|
||||
for (db::Cell::const_iterator i = cell.begin (); ! i.at_end (); ++i) {
|
||||
inst.push_back (db::CellInstArrayWithProperties (i->cell_inst (), i->prop_id ()));
|
||||
}
|
||||
|
||||
cell.clear_insts ();
|
||||
create_var_instances (cell, inst, vv.begin ()->first, *var_table, typename compare_traits::is_translation_invariant ());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the variants for a given cell
|
||||
*
|
||||
* The keys of the map are the variants, the values is the instance count of the variant
|
||||
* (as seen from the top cell).
|
||||
*/
|
||||
const std::map<db::ICplxTrans, size_t> &variants (db::cell_index_type ci) const
|
||||
{
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, size_t> >::const_iterator v = m_variants.find (ci);
|
||||
static std::map<db::ICplxTrans, size_t> empty_set;
|
||||
if (v == m_variants.end ()) {
|
||||
return empty_set;
|
||||
} else {
|
||||
|
|
@ -197,39 +321,104 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
std::map<db::cell_index_type, std::set<db::ICplxTrans> > m_variants;
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, size_t> > m_variants;
|
||||
Reduce m_red;
|
||||
|
||||
void add_variant (std::set<db::ICplxTrans> &variants, const db::CellInstArray &inst, tl::false_tag) const
|
||||
void add_variant (std::map<db::ICplxTrans, size_t> &variants, const db::CellInstArray &inst, tl::false_tag) const
|
||||
{
|
||||
if (inst.is_complex ()) {
|
||||
for (db::CellInstArray::iterator i = inst.begin (); ! i.at_end (); ++i) {
|
||||
variants.insert (m_red (inst.complex_trans (*i)));
|
||||
variants [m_red (inst.complex_trans (*i))] += 1;
|
||||
}
|
||||
} else {
|
||||
for (db::CellInstArray::iterator i = inst.begin (); ! i.at_end (); ++i) {
|
||||
variants.insert (db::ICplxTrans (m_red (*i)));
|
||||
variants [db::ICplxTrans (m_red (*i))] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void add_variant (std::set<db::ICplxTrans> &variants, const db::CellInstArray &inst, tl::true_tag) const
|
||||
void add_variant (std::map<db::ICplxTrans, size_t> &variants, const db::CellInstArray &inst, tl::true_tag) const
|
||||
{
|
||||
if (inst.is_complex ()) {
|
||||
variants.insert (m_red (inst.complex_trans ()));
|
||||
variants [m_red (inst.complex_trans ())] += inst.size ();
|
||||
} else {
|
||||
variants.insert (db::ICplxTrans (m_red (inst.front ())));
|
||||
variants [db::ICplxTrans (m_red (inst.front ()))] += inst.size ();
|
||||
}
|
||||
}
|
||||
|
||||
void product (const std::set<db::ICplxTrans> &v1, const std::set<db::ICplxTrans> &v2, std::set<db::ICplxTrans> &prod) const
|
||||
void product (const std::map<db::ICplxTrans, size_t> &v1, const std::map<db::ICplxTrans, size_t> &v2, std::map<db::ICplxTrans, size_t> &prod) const
|
||||
{
|
||||
for (std::set<db::ICplxTrans>::const_iterator i = v1.begin (); i != v1.end (); ++i) {
|
||||
for (std::set<db::ICplxTrans>::const_iterator j = v2.begin (); j != v2.end (); ++j) {
|
||||
prod.insert (m_red (*i * *j));
|
||||
for (std::map<db::ICplxTrans, size_t>::const_iterator i = v1.begin (); i != v1.end (); ++i) {
|
||||
for (std::map<db::ICplxTrans, size_t>::const_iterator j = v2.begin (); j != v2.end (); ++j) {
|
||||
prod [m_red (i->first * j->first)] += i->second * j->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void copy_shapes (db::Layout &layout, db::cell_index_type ci_to, db::cell_index_type ci_from) const
|
||||
{
|
||||
db::Cell &to = layout.cell (ci_to);
|
||||
const db::Cell &from = layout.cell (ci_from);
|
||||
for (db::Layout::layer_iterator li = layout.begin_layers (); li != layout.end_layers (); ++li) {
|
||||
to.shapes ((*li).first) = from.shapes ((*li).first);
|
||||
}
|
||||
}
|
||||
|
||||
void create_var_instances (db::Cell &in_cell, std::vector<db::CellInstArrayWithProperties> &inst, const db::ICplxTrans &for_var, const std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > &var_table, tl::false_tag) const
|
||||
{
|
||||
for (std::vector<db::CellInstArrayWithProperties>::const_iterator i = inst.begin (); i != inst.end (); ++i) {
|
||||
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> >::const_iterator f = var_table.find (i->object ().cell_index ());
|
||||
if (f == var_table.end ()) {
|
||||
|
||||
in_cell.insert (*i);
|
||||
|
||||
} else {
|
||||
|
||||
const std::map<db::ICplxTrans, db::cell_index_type> &vt = f->second;
|
||||
|
||||
for (db::CellInstArray::iterator ia = i->begin (); ! ia.at_end (); ++ia) {
|
||||
|
||||
db::ICplxTrans rt = m_red (for_var * i->complex_trans (*ia));
|
||||
std::map<db::ICplxTrans, db::cell_index_type>::const_iterator v = vt.find (rt);
|
||||
tl_assert (v != vt.end ());
|
||||
|
||||
in_cell.insert (db::CellInstArrayWithProperties (db::CellInstArray (db::CellInst (v->second), i->complex_trans (*ia)), i->properties_id ()));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void create_var_instances (db::Cell &in_cell, std::vector<db::CellInstArrayWithProperties> &inst, const db::ICplxTrans &for_var, const std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > &var_table, tl::true_tag) const
|
||||
{
|
||||
for (std::vector<db::CellInstArrayWithProperties>::const_iterator i = inst.begin (); i != inst.end (); ++i) {
|
||||
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> >::const_iterator f = var_table.find (i->object ().cell_index ());
|
||||
if (f == var_table.end ()) {
|
||||
|
||||
in_cell.insert (*i);
|
||||
|
||||
} else {
|
||||
|
||||
const std::map<db::ICplxTrans, db::cell_index_type> &vt = f->second;
|
||||
|
||||
std::map<db::ICplxTrans, db::cell_index_type>::const_iterator v;
|
||||
|
||||
db::ICplxTrans rt = m_red (for_var * i->complex_trans ());
|
||||
v = vt.find (rt);
|
||||
tl_assert (v != vt.end ());
|
||||
|
||||
db::CellInstArrayWithProperties new_inst = *i;
|
||||
new_inst.object ().cell_index (v->second);
|
||||
in_cell.insert (new_inst);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace db
|
||||
|
|
|
|||
|
|
@ -22,23 +22,67 @@
|
|||
|
||||
|
||||
#include "dbCellVariants.h"
|
||||
#include "dbTestSupport.h"
|
||||
#include "dbReader.h"
|
||||
#include "tlUnitTest.h"
|
||||
#include "tlStream.h"
|
||||
|
||||
std::string var2str (const std::set<db::ICplxTrans> &vars)
|
||||
std::string var2str (const std::map<db::ICplxTrans, size_t> &vars)
|
||||
{
|
||||
std::string res;
|
||||
for (std::set<db::ICplxTrans>::const_iterator i = vars.begin (); i != vars.end (); ++i) {
|
||||
for (std::map<db::ICplxTrans, size_t>::const_iterator i = vars.begin (); i != vars.end (); ++i) {
|
||||
if (! res.empty ()) {
|
||||
res += ";";
|
||||
}
|
||||
res += i->to_string ();
|
||||
res += i->first.to_string ();
|
||||
res += "[";
|
||||
res += tl::to_string (i->second);
|
||||
res += "]";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string vm2str (const db::Layout &ly, const std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > &vm)
|
||||
{
|
||||
std::string res;
|
||||
for (std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> >::const_iterator i = vm.begin (); i != vm.end (); ++i) {
|
||||
if (! res.empty ()) {
|
||||
res += ";";
|
||||
}
|
||||
res += ly.cell_name (i->first);
|
||||
res += ":";
|
||||
for (std::map<db::ICplxTrans, db::cell_index_type>::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
|
||||
if (j != i->second.begin ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += ly.cell_name (j->second);
|
||||
res += "[";
|
||||
res += j->first.to_string ();
|
||||
res += "]";
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string inst2str (const db::Layout &ly, const db::Cell &cell)
|
||||
{
|
||||
std::string res;
|
||||
for (db::Cell::const_iterator i = cell.begin (); ! i.at_end (); ++i) {
|
||||
for (db::CellInstArray::iterator ia = i->begin (); ! ia.at_end (); ++ia) {
|
||||
db::ICplxTrans rt = i->complex_trans (*ia);
|
||||
if (! res.empty ()) {
|
||||
res += ";";
|
||||
}
|
||||
res += ly.cell_name (i->cell_index ());
|
||||
res += ":";
|
||||
res += rt.to_string ();
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
TEST(1_Trivial)
|
||||
{
|
||||
|
||||
db::Layout ly;
|
||||
db::Cell &a = ly.cell (ly.add_cell ("A"));
|
||||
db::Cell &b = ly.cell (ly.add_cell ("B"));
|
||||
|
|
@ -48,17 +92,21 @@ TEST(1_Trivial)
|
|||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::Trans (0, false, db::Vector (1, 10))));
|
||||
|
||||
db::OrientationReducer red;
|
||||
db::cell_variants_builder<db::OrientationReducer> vb (red);
|
||||
vb.build (ly, a);
|
||||
EXPECT_EQ (var2str (vb.variants (a.cell_index ())), "r0 *1 0,0");
|
||||
EXPECT_EQ (var2str (vb.variants (b.cell_index ())), "r0 *1 0,0");
|
||||
db::cell_variants_collector<db::OrientationReducer> vb (red);
|
||||
vb.collect (ly, a);
|
||||
EXPECT_EQ (var2str (vb.variants (a.cell_index ())), "r0 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (b.cell_index ())), "r0 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (c.cell_index ())), "");
|
||||
EXPECT_EQ (var2str (vb.variants (d.cell_index ())), "");
|
||||
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > vm;
|
||||
vb.separate_variants (ly, a, &vm);
|
||||
EXPECT_EQ (vm.empty (), true);
|
||||
EXPECT_EQ (vm2str (ly, vm), "");
|
||||
}
|
||||
|
||||
TEST(2_TwoVariants)
|
||||
{
|
||||
|
||||
db::Layout ly;
|
||||
db::Cell &a = ly.cell (ly.add_cell ("A"));
|
||||
db::Cell &b = ly.cell (ly.add_cell ("B"));
|
||||
|
|
@ -69,17 +117,23 @@ TEST(2_TwoVariants)
|
|||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::Trans (0, true, db::Vector (1, 100))));
|
||||
|
||||
db::OrientationReducer red;
|
||||
db::cell_variants_builder<db::OrientationReducer> vb (red);
|
||||
vb.build (ly, a);
|
||||
EXPECT_EQ (var2str (vb.variants (a.cell_index ())), "r0 *1 0,0");
|
||||
EXPECT_EQ (var2str (vb.variants (b.cell_index ())), "m0 *1 0,0;r0 *1 0,0");
|
||||
db::cell_variants_collector<db::OrientationReducer> vb (red);
|
||||
vb.collect (ly, a);
|
||||
EXPECT_EQ (var2str (vb.variants (a.cell_index ())), "r0 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (b.cell_index ())), "m0 *1 0,0[1];r0 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (c.cell_index ())), "");
|
||||
EXPECT_EQ (var2str (vb.variants (d.cell_index ())), "");
|
||||
|
||||
EXPECT_EQ (inst2str (ly, a), "B:r0 *1 1,10;B:m0 *1 1,100");
|
||||
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > vm;
|
||||
vb.separate_variants (ly, a, &vm);
|
||||
EXPECT_EQ (vm2str (ly, vm), "B:B[m0 *1 0,0],B_VAR1[r0 *1 0,0]");
|
||||
EXPECT_EQ (inst2str (ly, a), "B_VAR1:r0 *1 1,10;B:m0 *1 1,100");
|
||||
}
|
||||
|
||||
TEST(3_TwoLevels)
|
||||
{
|
||||
|
||||
db::Layout ly;
|
||||
db::Cell &a = ly.cell (ly.add_cell ("A"));
|
||||
db::Cell &b = ly.cell (ly.add_cell ("B"));
|
||||
|
|
@ -92,10 +146,249 @@ TEST(3_TwoLevels)
|
|||
b.insert (db::CellInstArray (db::CellInst (c.cell_index ()), db::Trans (0, true, db::Vector (2, 100))));
|
||||
|
||||
db::OrientationReducer red;
|
||||
db::cell_variants_builder<db::OrientationReducer> vb (red);
|
||||
vb.build (ly, a);
|
||||
EXPECT_EQ (var2str (vb.variants (a.cell_index ())), "r0 *1 0,0");
|
||||
EXPECT_EQ (var2str (vb.variants (b.cell_index ())), "r0 *1 0,0;r90 *1 0,0");
|
||||
EXPECT_EQ (var2str (vb.variants (c.cell_index ())), "m0 *1 0,0;r0 *1 0,0;m45 *1 0,0;r90 *1 0,0");
|
||||
db::cell_variants_collector<db::OrientationReducer> vb (red);
|
||||
vb.collect (ly, a);
|
||||
EXPECT_EQ (var2str (vb.variants (a.cell_index ())), "r0 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (b.cell_index ())), "r0 *1 0,0[1];r90 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (c.cell_index ())), "m0 *1 0,0[1];r0 *1 0,0[1];m45 *1 0,0[1];r90 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (d.cell_index ())), "");
|
||||
|
||||
EXPECT_EQ (inst2str (ly, a), "B:r0 *1 1,10;B:r90 *1 1,100");
|
||||
EXPECT_EQ (inst2str (ly, b), "C:r0 *1 2,10;C:m0 *1 2,100");
|
||||
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > vm;
|
||||
vb.separate_variants (ly, a, &vm);
|
||||
EXPECT_EQ (vm2str (ly, vm), "B:B[r0 *1 0,0],B_VAR1[r90 *1 0,0];C:C[m0 *1 0,0],C_VAR1[r0 *1 0,0],C_VAR2[m45 *1 0,0],C_VAR3[r90 *1 0,0]");
|
||||
|
||||
EXPECT_EQ (inst2str (ly, a), "B:r0 *1 1,10;B_VAR1:r90 *1 1,100");
|
||||
EXPECT_EQ (inst2str (ly, b), "C_VAR1:r0 *1 2,10;C:m0 *1 2,100");
|
||||
EXPECT_EQ (inst2str (ly, ly.cell (ly.cell_by_name ("B_VAR1").second)), "C_VAR3:r0 *1 2,10;C_VAR2:m0 *1 2,100");
|
||||
}
|
||||
|
||||
TEST(4_ThreeLevels)
|
||||
{
|
||||
db::Layout ly;
|
||||
db::Cell &a = ly.cell (ly.add_cell ("A"));
|
||||
db::Cell &b = ly.cell (ly.add_cell ("B"));
|
||||
db::Cell &c = ly.cell (ly.add_cell ("C"));
|
||||
db::Cell &d = ly.cell (ly.add_cell ("D"));
|
||||
|
||||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::Trans (0, false, db::Vector (1, 10))));
|
||||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::Trans (1, false, db::Vector (1, 100))));
|
||||
b.insert (db::CellInstArray (db::CellInst (c.cell_index ()), db::Trans (0, false, db::Vector (2, 10))));
|
||||
b.insert (db::CellInstArray (db::CellInst (c.cell_index ()), db::Trans (0, true, db::Vector (2, 100))));
|
||||
c.insert (db::CellInstArray (db::CellInst (d.cell_index ()), db::Trans (1, true, db::Vector (0, 0))));
|
||||
|
||||
db::OrientationReducer red;
|
||||
db::cell_variants_collector<db::OrientationReducer> vb (red);
|
||||
vb.collect (ly, a);
|
||||
EXPECT_EQ (var2str (vb.variants (a.cell_index ())), "r0 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (b.cell_index ())), "r0 *1 0,0[1];r90 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (c.cell_index ())), "m0 *1 0,0[1];r0 *1 0,0[1];m45 *1 0,0[1];r90 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (d.cell_index ())), "r270 *1 0,0[1];m90 *1 0,0[1];r0 *1 0,0[1];m45 *1 0,0[1]");
|
||||
|
||||
EXPECT_EQ (inst2str (ly, a), "B:r0 *1 1,10;B:r90 *1 1,100");
|
||||
EXPECT_EQ (inst2str (ly, b), "C:r0 *1 2,10;C:m0 *1 2,100");
|
||||
EXPECT_EQ (inst2str (ly, c), "D:m45 *1 0,0");
|
||||
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > vm;
|
||||
vb.separate_variants (ly, a, &vm);
|
||||
EXPECT_EQ (vm2str (ly, vm), "B:B[r0 *1 0,0],B_VAR1[r90 *1 0,0];C:C[m0 *1 0,0],C_VAR1[r0 *1 0,0],C_VAR2[m45 *1 0,0],C_VAR3[r90 *1 0,0];D:D[r270 *1 0,0],D_VAR1[m90 *1 0,0],D_VAR2[r0 *1 0,0],D_VAR3[m45 *1 0,0]");
|
||||
|
||||
EXPECT_EQ (inst2str (ly, a), "B:r0 *1 1,10;B_VAR1:r90 *1 1,100");
|
||||
EXPECT_EQ (inst2str (ly, b), "C_VAR1:r0 *1 2,10;C:m0 *1 2,100");
|
||||
EXPECT_EQ (inst2str (ly, ly.cell (ly.cell_by_name ("B_VAR1").second)), "C_VAR3:r0 *1 2,10;C_VAR2:m0 *1 2,100");
|
||||
EXPECT_EQ (inst2str (ly, c), "D:m45 *1 0,0");
|
||||
EXPECT_EQ (inst2str (ly, ly.cell (ly.cell_by_name ("C_VAR1").second)), "D_VAR3:m45 *1 0,0");
|
||||
EXPECT_EQ (inst2str (ly, ly.cell (ly.cell_by_name ("C_VAR2").second)), "D_VAR2:m45 *1 0,0");
|
||||
EXPECT_EQ (inst2str (ly, ly.cell (ly.cell_by_name ("C_VAR3").second)), "D_VAR1:m45 *1 0,0");
|
||||
}
|
||||
|
||||
TEST(5_ComplexTrans)
|
||||
{
|
||||
db::Layout ly;
|
||||
db::Cell &a = ly.cell (ly.add_cell ("A"));
|
||||
db::Cell &b = ly.cell (ly.add_cell ("B"));
|
||||
db::Cell &c = ly.cell (ly.add_cell ("C"));
|
||||
db::Cell &d = ly.cell (ly.add_cell ("D"));
|
||||
|
||||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::ICplxTrans (db::Trans (0, false, db::Vector (1, 10)))));
|
||||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::ICplxTrans (db::Trans (1, false, db::Vector (1, 100)))));
|
||||
b.insert (db::CellInstArray (db::CellInst (c.cell_index ()), db::ICplxTrans (db::Trans (0, false, db::Vector (2, 10)))));
|
||||
b.insert (db::CellInstArray (db::CellInst (c.cell_index ()), db::ICplxTrans (db::Trans (0, true, db::Vector (2, 100)))));
|
||||
|
||||
db::OrientationReducer red;
|
||||
db::cell_variants_collector<db::OrientationReducer> vb (red);
|
||||
vb.collect (ly, a);
|
||||
EXPECT_EQ (var2str (vb.variants (a.cell_index ())), "r0 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (b.cell_index ())), "r0 *1 0,0[1];r90 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (c.cell_index ())), "m0 *1 0,0[1];r0 *1 0,0[1];m45 *1 0,0[1];r90 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (d.cell_index ())), "");
|
||||
}
|
||||
|
||||
TEST(6_Arrays)
|
||||
{
|
||||
|
||||
db::Layout ly;
|
||||
db::Cell &a = ly.cell (ly.add_cell ("A"));
|
||||
db::Cell &b = ly.cell (ly.add_cell ("B"));
|
||||
db::Cell &c = ly.cell (ly.add_cell ("C"));
|
||||
db::Cell &d = ly.cell (ly.add_cell ("D"));
|
||||
|
||||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::Trans (0, false, db::Vector (1, 10)), db::Vector (0, 100), db::Vector (100, 0), 10, 10));
|
||||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::Trans (1, false, db::Vector (1, 100))));
|
||||
b.insert (db::CellInstArray (db::CellInst (c.cell_index ()), db::Trans (0, false, db::Vector (2, 10)), db::Vector (0, 101), db::Vector (101, 0), 10, 10));
|
||||
b.insert (db::CellInstArray (db::CellInst (c.cell_index ()), db::Trans (0, true, db::Vector (2, 100))));
|
||||
|
||||
db::OrientationReducer red;
|
||||
db::cell_variants_collector<db::OrientationReducer> vb (red);
|
||||
vb.collect (ly, a);
|
||||
EXPECT_EQ (var2str (vb.variants (a.cell_index ())), "r0 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (b.cell_index ())), "r0 *1 0,0[100];r90 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (c.cell_index ())), "m0 *1 0,0[100];r0 *1 0,0[10000];m45 *1 0,0[1];r90 *1 0,0[100]");
|
||||
EXPECT_EQ (var2str (vb.variants (d.cell_index ())), "");
|
||||
}
|
||||
|
||||
TEST(7_ScalingVariants)
|
||||
{
|
||||
db::Layout ly;
|
||||
db::Cell &a = ly.cell (ly.add_cell ("A"));
|
||||
db::Cell &b = ly.cell (ly.add_cell ("B"));
|
||||
db::Cell &c = ly.cell (ly.add_cell ("C"));
|
||||
db::Cell &d = ly.cell (ly.add_cell ("D"));
|
||||
|
||||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::ICplxTrans (1.5, 0, false, db::Vector (1, 10)), db::Vector (0, 100), db::Vector (100, 0), 10, 10));
|
||||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::ICplxTrans (1.0, 90.0, false, db::Vector (1, 100))));
|
||||
b.insert (db::CellInstArray (db::CellInst (c.cell_index ()), db::ICplxTrans (2.0, 0, false, db::Vector (2, 10)), db::Vector (0, 101), db::Vector (101, 0), 10, 10));
|
||||
b.insert (db::CellInstArray (db::CellInst (c.cell_index ()), db::ICplxTrans (1.0, 0, true, db::Vector (2, 100))));
|
||||
|
||||
db::MagnificationReducer red;
|
||||
db::cell_variants_collector<db::MagnificationReducer> vb (red);
|
||||
vb.collect (ly, a);
|
||||
EXPECT_EQ (var2str (vb.variants (a.cell_index ())), "r0 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (b.cell_index ())), "r0 *1 0,0[1];r0 *1.5 0,0[100]");
|
||||
EXPECT_EQ (var2str (vb.variants (c.cell_index ())), "r0 *1 0,0[1];r0 *1.5 0,0[100];r0 *2 0,0[100];r0 *3 0,0[10000]");
|
||||
EXPECT_EQ (var2str (vb.variants (d.cell_index ())), "");
|
||||
}
|
||||
|
||||
TEST(8_GridVariants)
|
||||
{
|
||||
db::Layout ly;
|
||||
db::Cell &a = ly.cell (ly.add_cell ("A"));
|
||||
db::Cell &b = ly.cell (ly.add_cell ("B"));
|
||||
db::Cell &c = ly.cell (ly.add_cell ("C"));
|
||||
db::Cell &d = ly.cell (ly.add_cell ("D"));
|
||||
|
||||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::ICplxTrans (1.0, 0, false, db::Vector (1, 10)), db::Vector (0, 101), db::Vector (102, 0), 2, 2));
|
||||
b.insert (db::CellInstArray (db::CellInst (c.cell_index ()), db::ICplxTrans (1.0, 0, false, db::Vector (2, 3))));
|
||||
|
||||
db::GridReducer red (10);
|
||||
db::cell_variants_collector<db::GridReducer> vb (red);
|
||||
vb.collect (ly, a);
|
||||
EXPECT_EQ (var2str (vb.variants (a.cell_index ())), "r0 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (b.cell_index ())), "r0 *1 1,0[1];r0 *1 3,0[1];r0 *1 1,1[1];r0 *1 3,1[1]");
|
||||
|
||||
// placements are:
|
||||
// b in a: r0 *1 x=1,1+102 y=10,10+101
|
||||
// c in b: r0 *1 x=2,y=3
|
||||
// expanded placements:
|
||||
// c in a: r0 *2 x=1,1+102 y=10,10+101 x r0 *1 x=2,y=3
|
||||
// = (3,13),(105,13),(3,114),(105,114)
|
||||
// expanded placements mod 10:
|
||||
// c in a: r0 *2 x=1,1+102 y=10,10+101 x r0 *1 x=2,y=3
|
||||
// = (3,3),(5,3),(3,4),(5,4)
|
||||
EXPECT_EQ (var2str (vb.variants (c.cell_index ())), "r0 *1 3,3[1];r0 *1 5,3[1];r0 *1 3,4[1];r0 *1 5,4[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (d.cell_index ())), "");
|
||||
|
||||
EXPECT_EQ (inst2str (ly, a), "B:r0 *1 1,10;B:r0 *1 1,111;B:r0 *1 103,10;B:r0 *1 103,111");
|
||||
EXPECT_EQ (inst2str (ly, b), "C:r0 *1 2,3");
|
||||
EXPECT_EQ (inst2str (ly, c), "");
|
||||
|
||||
std::map<db::cell_index_type, std::map<db::ICplxTrans, db::cell_index_type> > vm;
|
||||
vb.separate_variants (ly, a, &vm);
|
||||
EXPECT_EQ (vm2str (ly, vm), "B:B[r0 *1 1,0],B_VAR1[r0 *1 3,0],B_VAR2[r0 *1 1,1],B_VAR3[r0 *1 3,1];C:C[r0 *1 3,3],C_VAR1[r0 *1 5,3],C_VAR2[r0 *1 3,4],C_VAR3[r0 *1 5,4]");
|
||||
|
||||
EXPECT_EQ (inst2str (ly, a), "B:r0 *1 1,10;B_VAR2:r0 *1 1,111;B_VAR1:r0 *1 103,10;B_VAR3:r0 *1 103,111");
|
||||
EXPECT_EQ (inst2str (ly, b), "C:r0 *1 2,3");
|
||||
EXPECT_EQ (inst2str (ly, ly.cell (ly.cell_by_name ("B_VAR1").second)), "C_VAR1:r0 *1 2,3");
|
||||
EXPECT_EQ (inst2str (ly, ly.cell (ly.cell_by_name ("B_VAR2").second)), "C_VAR2:r0 *1 2,3");
|
||||
EXPECT_EQ (inst2str (ly, ly.cell (ly.cell_by_name ("B_VAR3").second)), "C_VAR3:r0 *1 2,3");
|
||||
EXPECT_EQ (inst2str (ly, c), "");
|
||||
}
|
||||
|
||||
TEST(9_ComplexGridVariants)
|
||||
{
|
||||
db::Layout ly;
|
||||
db::Cell &a = ly.cell (ly.add_cell ("A"));
|
||||
db::Cell &b = ly.cell (ly.add_cell ("B"));
|
||||
db::Cell &c = ly.cell (ly.add_cell ("C"));
|
||||
db::Cell &d = ly.cell (ly.add_cell ("D"));
|
||||
|
||||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::ICplxTrans (2.0, 0, false, db::Vector (1, 10)), db::Vector (0, 101), db::Vector (102, 0), 2, 2));
|
||||
a.insert (db::CellInstArray (db::CellInst (b.cell_index ()), db::ICplxTrans (1.0, 90.0, false, db::Vector (1, 100))));
|
||||
b.insert (db::CellInstArray (db::CellInst (c.cell_index ()), db::ICplxTrans (2.0, 0, false, db::Vector (2, 10)), db::Vector (0, 103), db::Vector (105, 0), 2, 2));
|
||||
b.insert (db::CellInstArray (db::CellInst (c.cell_index ()), db::ICplxTrans (1.0, 0, true, db::Vector (2, 100))));
|
||||
|
||||
db::GridReducer red (10);
|
||||
db::cell_variants_collector<db::GridReducer> vb (red);
|
||||
vb.collect (ly, a);
|
||||
EXPECT_EQ (var2str (vb.variants (a.cell_index ())), "r0 *1 0,0[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (b.cell_index ())), "r0 *2 1,0[1];r90 *1 1,0[1];r0 *2 3,0[1];r0 *2 1,1[1];r0 *2 3,1[1]");
|
||||
|
||||
// placements are:
|
||||
// b in a: r0 *2 x=1,1+102 y=10,10+101
|
||||
// r90 *1 x=1,y=100
|
||||
// c in b: r0 *2 x=2,2+105 y=10,10+103
|
||||
// m0 *1 x=2,y=100
|
||||
// expanded placements:
|
||||
// c in a: r0 *2 x=1,1+102 y=10,10+101 x r0 *2 x=2,2+105 y=10,10+103
|
||||
// = (5,30),(215,30),(5,236),(215,236)
|
||||
// (107,30),(317,30),(107,236),(317,236)
|
||||
// (5,131),(215,131),(5,337),(215,337)
|
||||
// (107,131),(317,131),(107,337),(317,337)
|
||||
// r0 *2 x=1,1+102 y=10,10+101 x m0 *1 x=2,y=100
|
||||
// (5,210),(5,311),(107,210),(107,311)
|
||||
// r90 *1 x=1,y=100 x r0 *2 x=2,2+105 y=10,10+103
|
||||
// (-9,102),(-9,207),(-112,102),(-112,207)
|
||||
// r90 *1 x=1,y=100 x m0 *1 x=2,y=100
|
||||
// (-99,102)
|
||||
// expanded placements mod 10:
|
||||
// c in a: r0 *2 x=1,1+102 y=10,10+101 x r0 *2 x=2,2+105 y=10,10+103
|
||||
// = (5,0),(5,0),(5,6),(5,6)
|
||||
// (7,0),(7,0),(7,6),(7,6)
|
||||
// (5,1),(5,1),(5,7),(5,7)
|
||||
// (7,1),(7,1),(7,7),(7,7)
|
||||
// r0 *2 x=1,1+102 y=10,10+101 x m0 *1 x=2,y=100
|
||||
// (5,0),(5,1),(7,0),(7,1)
|
||||
// r90 *1 x=1,y=100 x r0 *2 x=2,2+105 y=10,10+103
|
||||
// (1,2),(1,7),(8,2),(8,7)
|
||||
// r90 *1 x=1,y=100 x m0 *1 x=2,y=100
|
||||
// (1,2)
|
||||
EXPECT_EQ (var2str (vb.variants (c.cell_index ())), "m0 *2 5,0[1];r0 *4 5,0[2];m0 *2 7,0[1];r0 *4 7,0[2];m0 *2 5,1[1];r0 *4 5,1[2];"
|
||||
"m0 *2 7,1[1];r0 *4 7,1[2];m45 *1 1,2[1];r90 *2 1,2[1];r90 *2 8,2[1];"
|
||||
"r0 *4 5,6[2];r0 *4 7,6[2];r90 *2 1,7[1];r0 *4 5,7[2];r0 *4 7,7[2];r90 *2 8,7[1]");
|
||||
EXPECT_EQ (var2str (vb.variants (d.cell_index ())), "");
|
||||
}
|
||||
|
||||
TEST(100_OrientationVariantsWithLayout)
|
||||
{
|
||||
db::Layout ly;
|
||||
{
|
||||
std::string fn (tl::testsrc ());
|
||||
fn += "/testdata/algo/deep_region_l1.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);
|
||||
|
||||
db::OrientationReducer red;
|
||||
db::cell_variants_collector<db::OrientationReducer> vb (red);
|
||||
vb.collect (ly, top_cell);
|
||||
vb.separate_variants (ly, top_cell);
|
||||
|
||||
CHECKPOINT();
|
||||
db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/cell_variants_au1.gds");
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue