WIP: cell variant collecting and building.

This commit is contained in:
Matthias Koefferlein 2019-02-09 16:29:34 +01:00
parent 50c8c067d5
commit bbf7b2768b
3 changed files with 528 additions and 46 deletions

View File

@ -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

View File

@ -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");
}

BIN
testdata/algo/cell_variants_au1.gds vendored Normal file

Binary file not shown.