klayout/src/unit_tests/dbLayoutQuery.cc

1418 lines
49 KiB
C++
Raw Normal View History

/*
KLayout Layout Viewer
Copyright (C) 2006-2016 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "utHead.h"
#include "dbLayoutQuery.h"
#include "gsiExpression.h"
#include "dbCell.h"
#include "dbLayout.h"
#include "dbPCellDeclaration.h"
#include "dbLibrary.h"
#include "dbLibraryManager.h"
static std::string q2s_var (db::Layout &g, const std::string &query, const std::string &pname, const char *sep = ",")
{
db::LayoutQuery q (query);
db::LayoutQueryIterator iq (q, &g);
std::string res;
while (! iq.at_end ()) {
if (!res.empty ()) {
res += sep;
}
tl::Variant v;
iq.get (pname, v);
res += v.to_string ();
++iq;
}
return res;
}
static std::string q2s_var_skip (db::LayoutQueryIterator &iq, const std::string &pname, const char *sep = ",")
{
iq.reset ();
std::string res;
while (! iq.at_end ()) {
if (!res.empty ()) {
res += sep;
}
tl::Variant v;
iq.get (pname, v);
res += v.to_string ();
iq.next (true);
}
return res;
}
static std::string q2s_var (db::LayoutQueryIterator &iq, const std::string &pname, const char *sep = ",")
{
iq.reset ();
std::string res;
while (! iq.at_end ()) {
if (!res.empty ()) {
res += sep;
}
tl::Variant v;
iq.get (pname, v);
res += v.to_string ();
++iq;
}
return res;
}
static std::string q2s_expr (db::LayoutQueryIterator &iq, const std::string &es)
{
std::string res;
iq.reset ();
tl::Expression ex;
iq.eval ().parse (ex, es, true);
while (! iq.at_end ()) {
if (!res.empty ()) {
res += ",";
}
res += ex.execute().to_string ();
++iq;
}
return res;
}
static std::string q2s_cell (db::LayoutQueryIterator &iq, const std::string &pname)
{
iq.reset ();
std::string res;
while (! iq.at_end ()) {
if (!res.empty ()) {
res += ",";
}
tl::Variant v;
iq.get (pname, v);
if (v.is_nil ()) {
res += v.to_string ();
} else {
res += iq.layout ()->cell_name (v.to_ulong ());
}
++iq;
}
return res;
}
TEST(1)
{
db::Layout g;
g.insert_layer (0);
g.insert_layer (1);
db::Cell &c1 (g.cell (g.add_cell ("c1")));
db::Cell &c2 (g.cell (g.add_cell ("c2x")));
db::Cell &c3 (g.cell (g.add_cell ("c3")));
db::Cell &c4 (g.cell (g.add_cell ("c4")));
db::Cell &c5 (g.cell (g.add_cell ("c5x")));
c2.shapes (0).insert (db::Box (0, 1, 2, 3));
db::FTrans f (1, true);
db::Vector p (-10, 20);
db::Trans t (f.rot (), p);
db::Vector pp (10, -20);
db::Trans tt (0, pp);
// c4->c1 (aref)
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3));
// c5->c1
c5.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t));
// c3->c5 (3x)
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), tt));
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
// c4->c3
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c3.cell_index ()), t));
// c4->c1
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), tt));
// c2->c1 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), tt));
// c2->c4 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c4.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c4.cell_index ()), t));
// c2->c5 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), tt));
{
db::LayoutQuery q ("*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c2x,c4,c3,c5x,c1");
s = q2s_cell (iq, "cell_index");
EXPECT_EQ (s, "c2x,c4,c3,c5x,c1");
s = q2s_expr (iq, "cell.name");
EXPECT_EQ (s, "c2x,c4,c3,c5x,c1");
s = q2s_var (iq, "initial_cell_name");
EXPECT_EQ (s, "c2x,c4,c3,c5x,c1");
s = q2s_expr (iq, "initial_cell.name");
EXPECT_EQ (s, "c2x,c4,c3,c5x,c1");
s = q2s_cell (iq, "initial_cell_index");
EXPECT_EQ (s, "c2x,c4,c3,c5x,c1");
}
{
db::LayoutQuery q ("*x");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c2x,c5x");
s = q2s_cell (iq, "cell_index");
EXPECT_EQ (s, "c2x,c5x");
s = q2s_cell (iq, "initial_cell_index");
EXPECT_EQ (s, "c2x,c5x");
s = q2s_var (iq, "instances");
EXPECT_EQ (s, "1,8");
s = q2s_var (iq, "bbox");
EXPECT_EQ (s, "(0,1;2,3),()");
}
{
db::LayoutQuery q (".*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c2x");
s = q2s_cell (iq, "cell_index");
EXPECT_EQ (s, "c2x");
s = q2s_cell (iq, "initial_cell_index");
EXPECT_EQ (s, "c2x");
s = q2s_expr (iq, "initial_cell.name");
EXPECT_EQ (s, "c2x");
s = q2s_var (iq, "initial_cell_name");
EXPECT_EQ (s, "c2x");
s = q2s_cell (iq, "parent_cell_index");
EXPECT_EQ (s, "nil");
s = q2s_var (iq, "parent_cell_name");
EXPECT_EQ (s, "nil");
s = q2s_var (iq, "path_names");
EXPECT_EQ (s, "c2x");
s = q2s_var (iq, "path");
EXPECT_EQ (s, "1");
s = q2s_var (iq, "hier_levels");
EXPECT_EQ (s, "0");
}
{
// all cells one level below the top cell
db::LayoutQuery q (".*.*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c4,c5x");
s = q2s_expr (iq, "cell.name");
EXPECT_EQ (s, "c1,c4,c5x");
bool error = false;
try {
// errors: cannot call non-const method on const reference
s = q2s_expr (iq, "cell.name='hallo'");
} catch (...) {
error = true;
}
EXPECT_EQ (error, true);
s = q2s_expr (iq, "cell.name");
EXPECT_EQ (s, "c1,c4,c5x");
s = q2s_cell (iq, "cell_index");
EXPECT_EQ (s, "c1,c4,c5x");
s = q2s_cell (iq, "initial_cell_index");
EXPECT_EQ (s, "c2x,c2x,c2x");
s = q2s_var (iq, "initial_cell_name");
EXPECT_EQ (s, "c2x,c2x,c2x");
s = q2s_cell (iq, "parent_cell_index");
EXPECT_EQ (s, "c2x,c2x,c2x");
s = q2s_var (iq, "parent_cell_name");
EXPECT_EQ (s, "c2x,c2x,c2x");
s = q2s_expr (iq, "parent_cell.name");
EXPECT_EQ (s, "c2x,c2x,c2x");
s = q2s_var (iq, "path_names");
EXPECT_EQ (s, "c2x,c1,c2x,c4,c2x,c5x");
s = q2s_var (iq, "hier_levels");
EXPECT_EQ (s, "1,1,1");
}
{
// all cells one level below the top cell
db::LayoutQuery q (".c2x.*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c4,c5x");
}
{
// invalid top cell
db::LayoutQuery q (".x.*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "");
}
{
// all cells two levels below the top cell
db::LayoutQuery q (".*.*.*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c3,c1");
}
{
// all cells two levels below the top cell
db::LayoutQuery q (".*.c4.*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c3");
}
{
db::LayoutQuery q ("cell (.*)[3]");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c3,c1");
}
{
db::LayoutQuery q ("cell (.*)[1..2]");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c2x,c1,c4,c5x");
s = q2s_cell (iq, "cell_index");
EXPECT_EQ (s, "c2x,c1,c4,c5x");
s = q2s_cell (iq, "initial_cell_index");
EXPECT_EQ (s, "c2x,c2x,c2x,c2x");
s = q2s_var (iq, "initial_cell_name");
EXPECT_EQ (s, "c2x,c2x,c2x,c2x");
s = q2s_cell (iq, "parent_cell_index");
EXPECT_EQ (s, "nil,c2x,c2x,c2x");
s = q2s_var (iq, "parent_cell_name");
EXPECT_EQ (s, "nil,c2x,c2x,c2x");
s = q2s_var (iq, "path_names");
EXPECT_EQ (s, "c2x,c2x,c1,c2x,c4,c2x,c5x");
s = q2s_var (iq, "hier_levels");
EXPECT_EQ (s, "0,1,1,1");
}
{
db::LayoutQuery q ("cell (.*)(.*)?");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c2x,c1,c4,c5x");
s = q2s_var (iq, "bbox");
EXPECT_EQ (s, "(0,1;2,3),(),(),()");
}
{
db::LayoutQuery q ("cell (.*)[0..5]");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "nil,c2x,c1,c4,c1,c3,c5x,c1,c5x,c1");
s = q2s_var (iq, "references");
EXPECT_EQ (s, "nil,0,2,2,2,1,3,1,2,1");
s = q2s_var (iq, "weight");
EXPECT_EQ (s, "nil,0,2,2,7,1,3,1,2,1");
s = q2s_var (iq, "tot_weight");
EXPECT_EQ (s, "nil,0,2,2,14,2,6,6,2,2");
}
{
db::LayoutQuery q ("cell (.*)[0..5] where weight==7");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1");
s = q2s_var (iq, "references");
EXPECT_EQ (s, "2");
s = q2s_var (iq, "weight");
EXPECT_EQ (s, "7");
s = q2s_var (iq, "tot_weight");
EXPECT_EQ (s, "14");
}
{
db::LayoutQuery q ("cell (.*)*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "nil,c2x,c1,c4,c1,c3,c5x,c1,c5x,c1");
s = q2s_var (iq, "hier_levels");
EXPECT_EQ (s, "nil,0,1,1,2,2,3,4,1,2");
}
{
db::LayoutQuery q ("cell (.*)*.c5x");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c5x,c5x");
s = q2s_cell (iq, "cell_index");
EXPECT_EQ (s, "c5x,c5x");
s = q2s_cell (iq, "initial_cell_index");
EXPECT_EQ (s, "c2x,c2x");
s = q2s_var (iq, "initial_cell_name");
EXPECT_EQ (s, "c2x,c2x");
s = q2s_cell (iq, "parent_cell_index");
EXPECT_EQ (s, "c2x,c3");
s = q2s_var (iq, "parent_cell_name");
EXPECT_EQ (s, "c2x,c3");
s = q2s_var (iq, "path_names");
EXPECT_EQ (s, "c2x,c5x,c2x,c4,c3,c5x");
s = q2s_var (iq, "hier_levels");
EXPECT_EQ (s, "1,3");
}
{
db::LayoutQuery q ("c2x..c1");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c1,c1,c1");
s = q2s_cell (iq, "cell_index");
EXPECT_EQ (s, "c1,c1,c1,c1");
s = q2s_cell (iq, "initial_cell_index");
EXPECT_EQ (s, "c2x,c2x,c2x,c2x");
s = q2s_var (iq, "initial_cell_name");
EXPECT_EQ (s, "c2x,c2x,c2x,c2x");
s = q2s_cell (iq, "parent_cell_index");
EXPECT_EQ (s, "c2x,c4,c5x,c5x");
s = q2s_var (iq, "parent_cell_name");
EXPECT_EQ (s, "c2x,c4,c5x,c5x");
s = q2s_var (iq, "path_names");
EXPECT_EQ (s, "c2x,c1,c2x,c4,c1,c2x,c4,c3,c5x,c1,c2x,c5x,c1");
s = q2s_var (iq, "hier_levels");
EXPECT_EQ (s, "1,2,4,2");
s = q2s_var (iq, "references");
EXPECT_EQ (s, "2,2,1,1");
s = q2s_var (iq, "weight");
EXPECT_EQ (s, "2,7,1,1");
s = q2s_var (iq, "tot_weight");
EXPECT_EQ (s, "2,14,6,2");
}
{
db::LayoutQuery q ("c2x...c1");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c1,c1,c1");
s = q2s_cell (iq, "cell_index");
EXPECT_EQ (s, "c1,c1,c1,c1");
s = q2s_cell (iq, "initial_cell_index");
EXPECT_EQ (s, "c2x,c2x,c2x,c2x");
s = q2s_var (iq, "initial_cell_name");
EXPECT_EQ (s, "c2x,c2x,c2x,c2x");
s = q2s_cell (iq, "parent_cell_index");
EXPECT_EQ (s, "c2x,c4,c5x,c5x");
s = q2s_var (iq, "parent_cell_name");
EXPECT_EQ (s, "c2x,c4,c5x,c5x");
s = q2s_var (iq, "path_names");
EXPECT_EQ (s, "c2x,c1,c2x,c4,c1,c2x,c4,c3,c5x,c1,c2x,c5x,c1");
s = q2s_var (iq, "hier_levels");
EXPECT_EQ (s, "1,2,4,2");
s = q2s_var (iq, "references");
EXPECT_EQ (s, "2,2,1,1");
s = q2s_var (iq, "weight");
EXPECT_EQ (s, "2,7,1,1");
s = q2s_var (iq, "tot_weight");
EXPECT_EQ (s, "2,14,6,2");
}
{
db::LayoutQuery q ("c2x c1");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1");
s = q2s_cell (iq, "cell_index");
EXPECT_EQ (s, "c1");
s = q2s_cell (iq, "initial_cell_index");
EXPECT_EQ (s, "c1");
s = q2s_var (iq, "initial_cell_name");
EXPECT_EQ (s, "c1");
s = q2s_cell (iq, "parent_cell_index");
EXPECT_EQ (s, "nil");
s = q2s_var (iq, "parent_cell_name");
EXPECT_EQ (s, "nil");
s = q2s_var (iq, "path_names");
EXPECT_EQ (s, "c1");
s = q2s_var (iq, "hier_levels");
EXPECT_EQ (s, "0");
s = q2s_var (iq, "references");
EXPECT_EQ (s, "0");
s = q2s_var (iq, "weight");
EXPECT_EQ (s, "0");
s = q2s_var (iq, "tot_weight");
EXPECT_EQ (s, "0");
s = q2s_var (iq, "instances");
EXPECT_EQ (s, "24");
}
{
// all cells one level below the top cell with an expression for the top cell
db::LayoutQuery q (".$('c2'+'x').*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c4,c5x");
}
{
// Another way of saying "c2x.*"
db::LayoutQuery q ("*.$(cell_name=='c2x'?'*':'')");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c4,c5x");
}
}
TEST(2)
{
db::Layout g;
g.insert_layer (0);
g.insert_layer (1);
db::Cell &c1 (g.cell (g.add_cell ("c1")));
db::Cell &c2 (g.cell (g.add_cell ("c2x")));
db::Cell &c3 (g.cell (g.add_cell ("c3")));
db::Cell &c4 (g.cell (g.add_cell ("c4")));
db::Cell &c5 (g.cell (g.add_cell ("c5x")));
c2.shapes (0).insert (db::Box (0, 1, 2, 3));
c1.shapes (1).insert (db::Box (0, 10, 10, 30));
db::FTrans f (1, true);
db::Vector p (-10, 20);
db::Trans t (f.rot (), p);
db::Vector pp (10, -20);
db::Trans tt (0, pp);
// c4->c1 (aref)
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3));
// c5->c1
c5.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t));
// c3->c5 (3x)
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), tt));
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
// c4->c3
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c3.cell_index ()), t));
// c4->c1
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), tt));
// c2->c1 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), tt));
// c2->c4 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c4.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c4.cell_index ()), t));
// c2->c5 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), tt));
{
db::LayoutQuery q ("instances of c2x.c1");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c1");
s = q2s_var (iq, "trans");
EXPECT_EQ (s, "r0 *1 10,-20,m45 *1 -10,20");
s = q2s_var (iq, "path_trans");
EXPECT_EQ (s, "r0 *1 10,-20,m45 *1 -10,20");
s = q2s_var (iq, "inst_bbox");
EXPECT_EQ (s, "(10,-10;20,10),(0,20;20,30)");
s = q2s_var (iq, "inst");
EXPECT_EQ (s, "cell_index=0 r0 10,-20,cell_index=0 m45 -10,20");
s = q2s_var (iq, "array_a");
EXPECT_EQ (s, "nil,nil");
s = q2s_var (iq, "array_b");
EXPECT_EQ (s, "nil,nil");
s = q2s_var (iq, "array_na");
EXPECT_EQ (s, "nil,nil");
s = q2s_var (iq, "array_nb");
EXPECT_EQ (s, "nil,nil");
s = q2s_var (iq, "array_ia");
EXPECT_EQ (s, "-1,-1");
s = q2s_var (iq, "array_ia");
EXPECT_EQ (s, "-1,-1");
}
{
db::LayoutQuery q ("instances of c4.c1");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c1,c1,c1,c1,c1,c1");
s = q2s_var (iq, "trans");
EXPECT_EQ (s, "r0 *1 10,-20,m45 *1 -10,20,m45 *1 -9,21,m45 *1 -10,22,m45 *1 -9,23,m45 *1 -10,24,m45 *1 -9,25");
s = q2s_var (iq, "path_trans");
EXPECT_EQ (s, "r0 *1 10,-20,m45 *1 -10,20,m45 *1 -9,21,m45 *1 -10,22,m45 *1 -9,23,m45 *1 -10,24,m45 *1 -9,25");
s = q2s_var (iq, "inst_bbox");
EXPECT_EQ (s, "(10,-10;20,10),(0,20;20,30),(1,21;21,31),(0,22;20,32),(1,23;21,33),(0,24;20,34),(1,25;21,35)");
s = q2s_var (iq, "inst");
EXPECT_EQ (s, "cell_index=0 r0 10,-20,cell_index=0 m45 -10,20 array=(1,1,0,2 2x3),cell_index=0 m45 -10,20 array=(1,1,0,2 2x3),cell_index=0 m45 -10,20 array=(1,1,0,2 2x3),cell_index=0 m45 -10,20 array=(1,1,0,2 2x3),cell_index=0 m45 -10,20 array=(1,1,0,2 2x3),cell_index=0 m45 -10,20 array=(1,1,0,2 2x3)");
s = q2s_var (iq, "array_a");
EXPECT_EQ (s, "nil,1,1,1,1,1,1,1,1,1,1,1,1");
s = q2s_var (iq, "array_b");
EXPECT_EQ (s, "nil,0,2,0,2,0,2,0,2,0,2,0,2");
s = q2s_var (iq, "array_na");
EXPECT_EQ (s, "nil,2,2,2,2,2,2");
s = q2s_var (iq, "array_nb");
EXPECT_EQ (s, "nil,3,3,3,3,3,3");
s = q2s_var (iq, "array_ia");
EXPECT_EQ (s, "-1,0,1,0,1,0,1");
s = q2s_var (iq, "array_ib");
EXPECT_EQ (s, "-1,0,0,1,1,2,2");
}
{
db::LayoutQuery q ("instances of c4.c3");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c3");
s = q2s_var (iq, "trans");
EXPECT_EQ (s, "m45 *1 -10,20");
s = q2s_var (iq, "path_trans");
EXPECT_EQ (s, "m45 *1 -10,20");
}
{
db::LayoutQuery q ("instances of ...*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_expr (iq, "inst&&inst.cell.qname");
EXPECT_EQ (s, "nil,c1,c1,c4,c4,c5x,c5x,c1,c1,c1,c1,c1,c1,c1,c3,c5x,c5x,c5x,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c3,c5x,c5x,c5x,c1,c1,c1,c1,c1");
}
{
db::LayoutQuery q ("arrays of c4.c1");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c1");
s = q2s_var (iq, "trans");
EXPECT_EQ (s, "r0 *1 10,-20,m45 *1 -10,20");
s = q2s_var (iq, "path_trans");
EXPECT_EQ (s, "r0 *1 10,-20,m45 *1 -10,20");
s = q2s_var (iq, "inst_bbox");
EXPECT_EQ (s, "(20,-30;30,-10),(10,20;25,41)");
s = q2s_var (iq, "inst");
EXPECT_EQ (s, "cell_index=0 r0 10,-20,cell_index=0 m45 -10,20 array=(1,1,0,2 2x3)");
s = q2s_var (iq, "array_a");
EXPECT_EQ (s, "nil,1,1");
s = q2s_var (iq, "array_b");
EXPECT_EQ (s, "nil,0,2");
s = q2s_var (iq, "array_na");
EXPECT_EQ (s, "nil,2");
s = q2s_var (iq, "array_nb");
EXPECT_EQ (s, "nil,3");
s = q2s_var (iq, "array_ia");
EXPECT_EQ (s, "nil,nil");
s = q2s_var (iq, "array_ib");
EXPECT_EQ (s, "nil,nil");
}
{
db::LayoutQuery q ("arrays of (.*)*.c1");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1");
s = q2s_var (iq, "parent_cell_name");
EXPECT_EQ (s, "c2x,c2x,c4,c4,c5x,c5x,c5x,c4,c4,c5x,c5x,c5x,c5x,c5x");
s = q2s_var (iq, "trans");
EXPECT_EQ (s, "r0 *1 10,-20,m45 *1 -10,20,r0 *1 10,-20,m45 *1 -10,20,m45 *1 -10,20,m45 *1 -10,20,m45 *1 -10,20,r0 *1 10,-20,m45 *1 -10,20,m45 *1 -10,20,m45 *1 -10,20,m45 *1 -10,20,m45 *1 -10,20,m45 *1 -10,20");
s = q2s_var (iq, "path_trans");
EXPECT_EQ (s, "r0 *1 10,-20,m45 *1 -10,20,m45 *1 -30,30,r0 *1 10,10,m45 *1 10,10,r0 *1 20,20,r0 *1 20,20,m45 *1 -30,30,r0 *1 10,10,m45 *1 10,10,r0 *1 20,20,r0 *1 20,20,m45 *1 0,0,r0 *1 10,10");
}
{
db::LayoutQuery q ("arrays of (.*)*.c1 where trans.rot==0");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c1,c1");
s = q2s_var (iq, "parent_cell_name");
EXPECT_EQ (s, "c2x,c4,c4");
s = q2s_var (iq, "trans");
EXPECT_EQ (s, "r0 *1 10,-20,r0 *1 10,-20,r0 *1 10,-20");
s = q2s_var (iq, "path_trans");
EXPECT_EQ (s, "r0 *1 10,-20,m45 *1 -30,30,m45 *1 -30,30");
}
{
db::LayoutQuery q ("arrays of ..'c1' where parent_cell_name=='c4' && trans.rot==0");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c1");
s = q2s_var (iq, "parent_cell_name");
EXPECT_EQ (s, "c4,c4");
s = q2s_var (iq, "trans");
EXPECT_EQ (s, "r0 *1 10,-20,r0 *1 10,-20");
s = q2s_var (iq, "path_trans");
EXPECT_EQ (s, "m45 *1 -30,30,m45 *1 -30,30");
}
}
TEST(3)
{
db::Layout g;
g.insert_layer (0, db::LayerProperties ("l0"));
g.insert_layer (1, db::LayerProperties ("l1"));
g.insert_layer (2, db::LayerProperties ("l2"));
db::Cell &c1 (g.cell (g.add_cell ("c1")));
db::Cell &c2 (g.cell (g.add_cell ("c2x")));
db::Cell &c3 (g.cell (g.add_cell ("c3")));
db::Cell &c4 (g.cell (g.add_cell ("c4")));
db::Cell &c5 (g.cell (g.add_cell ("c5x")));
c2.shapes (0).insert (db::Box (0, 1, 2, 3));
c2.shapes (1).insert (db::Polygon (db::Box (0, 1, 2, 3)));
c2.shapes (1).insert (db::Edge (db::Point (0, 1), db::Point (2, 3)));
c2.shapes (2).insert (db::Text ("hallo", db::Trans (db::Vector (10, 11))));
c1.shapes (1).insert (db::Box (0, 10, 10, 30));
db::FTrans f (1, true);
db::Vector p (-10, 20);
db::Trans t (f.rot (), p);
db::Vector pp (10, -20);
db::Trans tt (0, pp);
// c4->c1 (aref)
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3));
// c5->c1
c5.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t));
// c3->c5 (3x)
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), tt));
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
// c4->c3
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c3.cell_index ()), t));
// c4->c1
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), tt));
// c2->c1 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), tt));
// c2->c4 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c4.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c4.cell_index ()), t));
// c2->c5 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), tt));
{
db::LayoutQuery q ("shapes of c1");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1");
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,10;10,30)");
}
{
db::LayoutQuery q ("boxes of *");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c2x,c1");
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),box (0,10;10,30)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l0,l1");
}
{
db::LayoutQuery q ("boxes of * where shape.area > 10");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1");
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,10;10,30)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l1");
}
{
db::LayoutQuery q ("shapes of c2x");
db::LayoutQueryIterator iq (q, &g);
std::string s;
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3),text ('hallo',r0 10,11)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l0,l1,l1,l2");
s = q2s_var (iq, "layer_index");
EXPECT_EQ (s, "0,1,1,2");
s = q2s_var (iq, "bbox");
EXPECT_EQ (s, "(0,1;2,3),(0,1;2,3),(0,1;2,3),(10,11;10,11)");
}
{
db::LayoutQuery q ("polygons of c2x");
db::LayoutQueryIterator iq (q, &g);
std::string s;
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "polygon (0,1;0,3;2,3;2,1)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l1");
s = q2s_var (iq, "layer_index");
EXPECT_EQ (s, "1");
s = q2s_var (iq, "bbox");
EXPECT_EQ (s, "(0,1;2,3)");
}
{
db::LayoutQuery q ("boxes of c2x");
db::LayoutQueryIterator iq (q, &g);
std::string s;
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l0");
s = q2s_var (iq, "layer_index");
EXPECT_EQ (s, "0");
s = q2s_var (iq, "bbox");
EXPECT_EQ (s, "(0,1;2,3)");
}
{
db::LayoutQuery q ("boxes, polygons of c2x");
db::LayoutQueryIterator iq (q, &g);
std::string s;
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),polygon (0,1;0,3;2,3;2,1)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l0,l1");
s = q2s_var (iq, "layer_index");
EXPECT_EQ (s, "0,1");
s = q2s_var (iq, "bbox");
EXPECT_EQ (s, "(0,1;2,3),(0,1;2,3)");
}
{
db::LayoutQuery q ("paths of c2x");
db::LayoutQueryIterator iq (q, &g);
std::string s;
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "");
s = q2s_var (iq, "layer_index");
EXPECT_EQ (s, "");
s = q2s_var (iq, "bbox");
EXPECT_EQ (s, "");
}
c4.shapes (2).insert (db::Box (0, -1, 2, 1));
{
db::LayoutQuery q ("boxes of c2x.*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c4");
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,10;10,30),box (0,-1;2,1)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l1,l2");
}
{
db::LayoutQuery q ("boxes of instances of c2x.*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c1,c4,c4");
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,10;10,30),box (0,10;10,30),box (0,-1;2,1),box (0,-1;2,1)");
s = q2s_expr (iq, "bbox.transformed(path_trans)");
EXPECT_EQ (s, "(10,-10;20,10),(0,20;20,30),(-11,20;-9,22),(-11,20;-9,22)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l1,l1,l2,l2");
}
{
db::LayoutQuery q ("boxes on 'l1';'l2' of instances of c2x.*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c1,c4,c4");
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,10;10,30),box (0,10;10,30),box (0,-1;2,1),box (0,-1;2,1)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l1,l1,l2,l2");
}
{
db::LayoutQuery q ("boxes on 'l2' of instances of c2x.*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c4,c4");
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,-1;2,1),box (0,-1;2,1)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l2,l2");
}
{
db::LayoutQuery q ("boxes on 'l0';'l2' of instances of c2x.*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c4,c4");
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,-1;2,1),box (0,-1;2,1)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l2,l2");
}
{
db::LayoutQuery q ("boxes of instances of c2x..*");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c1,c4,c4,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1");
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,10;10,30),box (0,10;10,30),box (0,-1;2,1),box (0,-1;2,1),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30)");
}
{
db::LayoutQuery q ("boxes of instances of c2x..* where true");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c1,c1,c4,c4,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1");
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,10;10,30),box (0,10;10,30),box (0,-1;2,1),box (0,-1;2,1),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30)");
}
{
db::LayoutQuery q ("boxes of instances of c2x..");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c2x,c1,c1,c4,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c4,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1");
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),box (0,10;10,30),box (0,10;10,30),box (0,-1;2,1),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,-1;2,1),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30)");
}
{
db::LayoutQuery q ("boxes of instances of c2x.. where true");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c2x,c1,c1,c4,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c4,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1");
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),box (0,10;10,30),box (0,10;10,30),box (0,-1;2,1),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,-1;2,1),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30),box (0,10;10,30)");
}
}
void init_layout (db::Layout &g)
{
g = db::Layout ();
g.insert_layer (0, db::LayerProperties ("l0"));
g.insert_layer (1, db::LayerProperties ("l1"));
g.insert_layer (2, db::LayerProperties ("l2"));
db::Cell &c1 (g.cell (g.add_cell ("c1")));
db::Cell &c2 (g.cell (g.add_cell ("c2x")));
db::Cell &c3 (g.cell (g.add_cell ("c3")));
db::Cell &c4 (g.cell (g.add_cell ("c4")));
db::Cell &c5 (g.cell (g.add_cell ("c5x")));
c2.shapes (0).insert (db::Box (0, 1, 2, 3));
c2.shapes (1).insert (db::Polygon (db::Box (0, 1, 2, 3)));
c2.shapes (1).insert (db::Edge (db::Point (0, 1), db::Point (2, 3)));
c2.shapes (2).insert (db::Text ("hallo", db::Trans (db::Vector (10, 11))));
c1.shapes (1).insert (db::Box (0, 10, 10, 30));
db::FTrans f (1, true);
db::Vector p (-10, 20);
db::Trans t (f.rot (), p);
db::Vector pp (10, -20);
db::Trans tt (0, pp);
// c4->c1 (aref)
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t, db::Vector(1, 1), db::Vector (0, 2), 2, 3));
// c5->c1
c5.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t));
// c3->c5 (3x)
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), tt));
c3.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
// c4->c3
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c3.cell_index ()), t));
// c4->c1
c4.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), tt));
// c2->c1 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), tt));
// c2->c4 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c4.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c4.cell_index ()), t));
// c2->c5 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c5.cell_index ()), tt));
}
TEST(4)
{
db::Layout g;
init_layout (g);
{
db::LayoutQuery q ("select cell_name+'#'+cell_index from *");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "data");
EXPECT_EQ (s, "c2x#1,c4#3,c3#2,c5x#4,c1#0");
}
{
db::LayoutQuery q ("select $1 from 'c(*)'");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "data");
EXPECT_EQ (s, "2x,4,3,5x,1");
}
{
db::LayoutQuery q ("select cell_index+'#'+cell_name from * sorted by cell_name");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "data");
EXPECT_EQ (s, "0#c1,1#c2x,2#c3,3#c4,4#c5x");
}
{
db::LayoutQuery q ("select cell_index+'#'+cell_name from ..* sorted by cell_name");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "data");
EXPECT_EQ (s, "0#c1,0#c1,0#c1,0#c1,1#c2x,2#c3,3#c4,4#c5x,4#c5x");
}
{
db::LayoutQuery q ("select cell_index+'#'+cell_name from ..* sorted by cell_name unique");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "data");
EXPECT_EQ (s, "0#c1,1#c2x,2#c3,3#c4,4#c5x");
}
{
db::LayoutQuery q ("select cell_index+'#'+cell_name from instances of ..* sorted by cell_name");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "data");
EXPECT_EQ (s, "0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,0#c1,1#c2x,2#c3,2#c3,3#c4,3#c4,4#c5x,4#c5x,4#c5x,4#c5x,4#c5x,4#c5x,4#c5x,4#c5x");
}
{
db::LayoutQuery q ("select cell_index+'#'+cell_name from instances of ..* sorted by cell_name unique");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "data");
EXPECT_EQ (s, "0#c1,1#c2x,2#c3,3#c4,4#c5x");
}
}
TEST(51a)
{
if (! db::default_editable_mode ()) { return; }
db::Layout g;
init_layout (g);
{
db::LayoutQuery ("delete cell *x").execute (g);
db::LayoutQuery q ("select cell_name+'#'+cell_index from *");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "data");
EXPECT_EQ (s, "c4#3,c1#0,c3#2");
}
{
db::LayoutQuery ("delete cell *").execute (g);
db::LayoutQuery q ("select cell_name+'#'+cell_index from *");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "data");
EXPECT_EQ (s, "");
}
}
TEST(51b)
{
if (! db::default_editable_mode ()) { return; }
db::Layout g;
init_layout (g);
{
db::LayoutQuery q ("delete cell *x");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "");
}
}
TEST(51c)
{
if (! db::default_editable_mode ()) { return; }
db::Layout g;
init_layout (g);
{
db::LayoutQuery q ("delete cell *x pass");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var_skip (iq, "cell_name");
EXPECT_EQ (s, "c2x,c5x");
}
{
db::LayoutQuery q ("delete cell *x pass");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c2x,c5x");
}
{
db::LayoutQuery q ("delete cell *x pass");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "");
}
}
TEST(52a)
{
if (! db::default_editable_mode ()) { return; }
db::Layout g;
init_layout (g);
{
db::LayoutQuery q ("shapes of c2x");
db::LayoutQueryIterator iq (q, &g);
std::string s;
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3),text ('hallo',r0 10,11)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l0,l1,l1,l2");
}
{
db::LayoutQuery q ("shapes on layer l0,l1 from c2x");
db::LayoutQueryIterator iq (q, &g);
std::string s;
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3)");
}
{
db::LayoutQuery ("delete shapes on layer l1 from *").execute (g);
db::LayoutQuery q ("shapes of c2x");
db::LayoutQueryIterator iq (q, &g);
std::string s;
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),text ('hallo',r0 10,11)");
}
{
init_layout (g);
db::LayoutQuery ("delete shapes on layer l1 from c4").execute (g);
db::LayoutQuery q ("shapes of c2x");
db::LayoutQueryIterator iq (q, &g);
std::string s;
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3),text ('hallo',r0 10,11)");
db::LayoutQuery ("delete polygons from *").execute (g);
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),edge (0,1;2,3),text ('hallo',r0 10,11)");
}
}
TEST(52b)
{
if (! db::default_editable_mode ()) { return; }
db::Layout g;
init_layout (g);
{
db::LayoutQuery q ("delete shapes on layer l1 from * pass");
db::LayoutQueryIterator iq (q, &g);
std::string s;
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3),box (0,10;10,30)");
}
}
TEST(53)
{
if (! db::default_editable_mode ()) { return; }
db::Layout g;
init_layout (g);
{
db::LayoutQuery q ("cell ..*");
std::string s;
db::LayoutQueryIterator iq (q, &g);
s = q2s_var (iq, "path_names", ";");
EXPECT_EQ (s, "c2x;c2x,c1;c2x,c4;c2x,c5x;c2x,c4,c1;c2x,c4,c3;c2x,c4,c3,c5x;c2x,c4,c3,c5x,c1;c2x,c5x,c1");
db::LayoutQuery ("delete instances of *.c1").execute (g);
s = q2s_var (iq, "path_names", ";");
EXPECT_EQ (s, "c1;c2x;c2x,c4;c2x,c5x;c2x,c4,c3;c2x,c4,c3,c5x");
}
init_layout (g);
{
std::string s;
db::LayoutQuery q ("delete instances of *.c1 pass");
db::LayoutQueryIterator iq (q, &g);
s = q2s_var (iq, "path_names", ";");
EXPECT_EQ (s, "c2x,c1;c2x,c1;c4,c1;c4,c1;c5x,c1");
}
init_layout (g);
{
db::LayoutQuery q ("cell ..*");
std::string s;
db::LayoutQueryIterator iq (q, &g);
s = q2s_var (iq, "path_names", ";");
EXPECT_EQ (s, "c2x;c2x,c1;c2x,c4;c2x,c5x;c2x,c4,c1;c2x,c4,c3;c2x,c4,c3,c5x;c2x,c4,c3,c5x,c1;c2x,c5x,c1");
db::LayoutQuery ("delete instances of c1").execute (g);
s = q2s_var (iq, "path_names", ";");
EXPECT_EQ (s, "c1;c2x;c2x,c4;c2x,c5x;c2x,c4,c3;c2x,c4,c3,c5x");
}
init_layout (g);
{
db::LayoutQuery q ("cell ..*");
std::string s;
db::LayoutQueryIterator iq (q, &g);
s = q2s_var (iq, "path_names", ";");
EXPECT_EQ (s, "c2x;c2x,c1;c2x,c4;c2x,c5x;c2x,c4,c1;c2x,c4,c3;c2x,c4,c3,c5x;c2x,c4,c3,c5x,c1;c2x,c5x,c1");
db::LayoutQuery ("delete instances of *").execute (g);
s = q2s_var (iq, "path_names", ";");
EXPECT_EQ (s, "c1;c2x;c3;c4;c5x");
}
}
TEST(61)
{
if (! db::default_editable_mode ()) { return; }
db::Layout g;
init_layout (g);
{
db::LayoutQuery q ("shapes of c2x");
db::LayoutQueryIterator iq (q, &g);
std::string s;
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3),text ('hallo',r0 10,11)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l0,l1,l1,l2");
db::LayoutQuery ("with boxes from * do shape.polygon = Polygon.new(shape.bbox)").execute (g);
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "polygon (0,1;0,3;2,3;2,1),polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3),text ('hallo',r0 10,11)");
db::LayoutQuery ("with polygons from * do shape.box = shape.bbox").execute (g);
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),edge (0,1;2,3),box (0,1;2,3),text ('hallo',r0 10,11)");
s = q2s_var (iq, "layer_info");
EXPECT_EQ (s, "l0,l1,l1,l2");
db::LayoutQuery ("with texts from * do shape.text_string = shape.text_string + 'xx'").execute (g);
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),edge (0,1;2,3),box (0,1;2,3),text ('halloxx',r0 10,11)");
db::LayoutQuery ("with texts from * where shape.text_string ~ '(*)all(*)' do shape.text_string = $1 + $2").execute (g);
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),edge (0,1;2,3),box (0,1;2,3),text ('hoxx',r0 10,11)");
}
init_layout (g);
{
std::string s;
db::LayoutQuery qq ("shapes from *");
db::LayoutQueryIterator iqq (qq, &g);
s = q2s_var (iqq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3),text ('hallo',r0 10,11),box (0,10;10,30)");
db::LayoutQuery ("with boxes from * do shape.polygon = Polygon.new(shape.bbox)").execute (g);
s = q2s_var (iqq, "shape");
EXPECT_EQ (s, "polygon (0,1;0,3;2,3;2,1),polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3),text ('hallo',r0 10,11),polygon (0,10;0,30;10,30;10,10)");
db::LayoutQuery q ("with polygons from * do shape.box = shape.bbox pass");
db::LayoutQueryIterator iq (q, &g);
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "polygon (0,1;0,3;2,3;2,1),polygon (0,1;0,3;2,3;2,1),polygon (0,10;0,30;10,30;10,10)");
s = q2s_var (iqq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),edge (0,1;2,3),box (0,1;2,3),text ('hallo',r0 10,11),box (0,10;10,30)");
}
init_layout (g);
{
std::string s;
db::LayoutQuery qq ("shapes from *");
db::LayoutQueryIterator iqq (qq, &g);
s = q2s_var (iqq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3),text ('hallo',r0 10,11),box (0,10;10,30)");
db::LayoutQuery ("with boxes from * do shape.polygon = Polygon.new(shape.bbox)").execute (g);
s = q2s_var (iqq, "shape");
EXPECT_EQ (s, "polygon (0,1;0,3;2,3;2,1),polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3),text ('hallo',r0 10,11),polygon (0,10;0,30;10,30;10,10)");
db::LayoutQuery q ("with polygons from * do shape.box = shape.bbox");
db::LayoutQueryIterator iq (q, &g);
s = q2s_var (iq, "shape");
EXPECT_EQ (s, "");
s = q2s_var (iqq, "shape");
EXPECT_EQ (s, "box (0,1;2,3),edge (0,1;2,3),box (0,1;2,3),text ('hallo',r0 10,11),box (0,10;10,30)");
}
init_layout (g);
{
db::LayoutQuery q ("*");
db::LayoutQueryIterator iq (q, &g);
std::string s;
s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "c2x,c4,c3,c5x,c1");
db::LayoutQuery ("with * do cell.name = 'i' + cell_index").execute (g);
s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "i1,i3,i2,i4,i0");
}
init_layout (g);
{
EXPECT_EQ (q2s_var (g, "shapes on l1 from c2x", "shape"), "polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3)");
EXPECT_EQ (q2s_var (g, "shapes on l1 from c1", "shape"), "box (0,10;10,30)");
db::LayoutQuery ("with shapes from instances of c2x..* do initial_cell.shapes(1).insert(shape).transform(path_trans)").execute (g);
db::LayoutQuery ("with shapes from c2x..* do shape.delete").execute (g);
EXPECT_EQ (q2s_var (g, "shapes on l1 from c2x", "shape"), "polygon (0,1;0,3;2,3;2,1),edge (0,1;2,3),box (10,-10;20,10),box (0,20;20,30),box (-20,30;0,40),box (10,20;20,40),box (20,10;40,20),box (20,30;30,50),box (20,30;30,50),box (-20,30;0,40),box (10,20;20,40),box (20,10;40,20),box (20,30;30,50),box (20,30;30,50),box (10,0;30,10),box (10,20;20,40)");
EXPECT_EQ (q2s_var (g, "shapes on l1 from c1", "shape"), "");
}
init_layout (g);
{
g.add_cell ("cx");
EXPECT_EQ (q2s_var (g, "instances of ..c4", "inst"), "cell_index=3 m45 -10,20,cell_index=3 m45 -10,20");
db::LayoutQuery ("with instances of ..c4 do inst.cell_index = layout.cell_by_name('cx')").execute (g);
EXPECT_EQ (q2s_var (g, "instances of ..c4", "inst"), "nil");
EXPECT_EQ (q2s_var (g, "instances of .*..c4", "inst"), "");
EXPECT_EQ (q2s_var (g, "instances of ..cx", "inst"), "cell_index=5 m45 -10,20,cell_index=5 m45 -10,20");
db::LayoutQuery ("delete instances of .*..c4").execute (g);
db::LayoutQuery ("delete instances of .*..cx").execute (g);
EXPECT_EQ (q2s_var (g, "instances of .*..c4", "inst"), "");
EXPECT_EQ (q2s_var (g, "instances of .*..cx", "inst"), "");
}
init_layout (g);
{
EXPECT_EQ (q2s_var (g, "instances of ..c4", "inst"), "cell_index=3 m45 -10,20,cell_index=3 m45 -10,20");
db::LayoutQuery ("with instances of ..c4 do inst.cell_index = <<cy>>").execute (g);
EXPECT_EQ (q2s_var (g, "instances of ..c4", "inst"), "nil");
EXPECT_EQ (q2s_var (g, "instances of .*..c4", "inst"), "");
EXPECT_EQ (q2s_var (g, "instances of ..cy", "inst"), "cell_index=5 m45 -10,20,cell_index=5 m45 -10,20");
}
init_layout (g);
{
EXPECT_EQ (q2s_var (g, "instances of ..c4", "inst"), "cell_index=3 m45 -10,20,cell_index=3 m45 -10,20");
db::LayoutQuery ("with instances of ..c4 do inst.cell_index = <<\"Basic\" + \".\" + \"TEXT\">>").execute (g);
EXPECT_EQ (q2s_var (g, "instances of ..c4", "inst"), "nil");
EXPECT_EQ (q2s_var (g, "instances of .*..c4", "inst"), "");
EXPECT_EQ (q2s_var (g, "instances of ..\"Basic.*\"", "inst"), "cell_index=5 m45 -10,20,cell_index=5 m45 -10,20");
}
}
TEST(62)
{
if (! db::default_editable_mode ()) { return; }
db::Library *basic_lib = db::LibraryManager::instance ().lib_ptr_by_name ("Basic");
EXPECT_EQ (basic_lib != 0, true);
if (!basic_lib) {
return;
}
size_t text_id = basic_lib->layout ().pcell_by_name ("TEXT").second;
const db::PCellDeclaration *text_decl = basic_lib->layout ().pcell_declaration (text_id);
std::vector<tl::Variant> values;
const std::vector<db::PCellParameterDeclaration> &pd = text_decl->get_parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::const_iterator p = pd.begin (); p != pd.end (); ++p) {
if (p->get_name () == "text") {
values.push_back (tl::Variant ("T1"));
} else {
values.push_back (p->get_default ());
}
}
size_t v1t1 = basic_lib->layout ().get_pcell_variant (text_id, values);
values.clear ();
for (std::vector<db::PCellParameterDeclaration>::const_iterator p = pd.begin (); p != pd.end (); ++p) {
if (p->get_name () == "text") {
values.push_back (tl::Variant ("T2"));
} else {
values.push_back (p->get_default ());
}
}
size_t v1t2 = basic_lib->layout ().get_pcell_variant (text_id, values);
db::Layout g;
init_layout (g);
size_t c3index = g.get_lib_proxy (basic_lib, v1t1);
size_t c4index = g.get_lib_proxy (basic_lib, v1t2);
db::Cell &c1 (g.cell (g.add_cell ("c1")));
db::Cell &c2 (g.cell (g.add_cell ("c2")));
db::Cell &c3 (g.cell (c3index));
db::Cell &c4 (g.cell (c4index));
db::FTrans f (1, true);
db::Vector p (-10, 20);
db::Trans t (f.rot (), p);
db::Vector pp (10, -20);
db::Trans tt (0, pp);
// c1->c3
c1.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c3.cell_index ()), t));
// c2->c4
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c4.cell_index ()), t));
// c2->c1 (2x)
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), t));
c2.insert (db::array <db::CellInst, db::Trans> (db::CellInst (c1.cell_index ()), tt));
{
db::LayoutQuery q ("\"Basic.*\"");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "cell_name");
EXPECT_EQ (s, "Basic.TEXT,Basic.TEXT");
}
{
db::LayoutQuery q ("instances of ...\"Basic.*\"");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_expr (iq, "inst.cell.display_title");
EXPECT_EQ (s, "Basic.TEXT('T2'),Basic.TEXT('T1'),Basic.TEXT('T1')");
}
{
db::LayoutQuery q ("select inst.pcell_parameters_by_name[\"text\"] from instances of ...* where cell_name ~ \"Basic.*\"");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "data");
EXPECT_EQ (s, "T2,T1,T1");
}
{
db::LayoutQuery q ("select inst.pcell_parameter(\"text\") from instances of ...* where cell_name ~ \"Basic.*\"");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "data");
EXPECT_EQ (s, "T2,T1,T1");
}
{
db::LayoutQuery q ("select inst[\"text\"] from instances of ...* where cell_name ~ \"Basic.*\"");
db::LayoutQueryIterator iq (q, &g);
std::string s = q2s_var (iq, "data");
EXPECT_EQ (s, "T2,T1,T1");
}
}