mirror of https://github.com/KLayout/klayout.git
1418 lines
49 KiB
C++
1418 lines
49 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2017 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");
|
|
}
|
|
}
|