klayout/src/plugins/tools/net_tracer/unit_tests/dbNetTracerTests.cc

397 lines
11 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2022 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 "tlUnitTest.h"
#include "dbNetTracerIO.h"
#include "dbNetTracer.h"
#include "dbRecursiveShapeIterator.h"
#include "dbLayoutDiff.h"
#include "dbTestSupport.h"
#include "dbWriter.h"
#include "dbReader.h"
static db::NetTracerConnectionInfo connection (const std::string &a, const std::string &v, const std::string &b)
{
return db::NetTracerConnectionInfo (db::NetTracerLayerExpressionInfo::compile (a),
db::NetTracerLayerExpressionInfo::compile (v),
db::NetTracerLayerExpressionInfo::compile (b));
}
static db::NetTracerConnectionInfo connection (const std::string &a, const std::string &b)
{
return db::NetTracerConnectionInfo (db::NetTracerLayerExpressionInfo::compile (a),
db::NetTracerLayerExpressionInfo::compile (b));
}
static db::NetTracerSymbolInfo symbol (const std::string &s, const std::string &e)
{
return db::NetTracerSymbolInfo (s, e);
}
static int layer_for (const db::Layout &layout, const db::LayerProperties &lp)
{
for (db::Layout::layer_iterator l = layout.begin_layers (); l != layout.end_layers (); ++l) {
if ((*l).second->log_equal (lp)) {
return int ((*l).first);
}
}
return -1;
}
#if 0
// not used yet:
static db::NetTracerShape find_shape (const db::Layout &layout, const db::Cell &cell, int l, const db::Point &pt)
{
if (l < 0 || ! layout.is_valid_layer ((unsigned int) l)) {
return db::NetTracerShape ();
}
db::RecursiveShapeIterator s (layout, cell, (unsigned int) l, db::Box (pt, pt));
if (! s.at_end ()) {
return db::NetTracerShape (s.itrans (), s.shape (), (unsigned int) l, s.cell_index ());
} else {
return db::NetTracerShape ();
}
}
#endif
static db::NetTracerNet trace (db::NetTracer &tracer, const db::Layout &layout, const db::Cell &cell, const db::NetTracerConnectivity &tc, unsigned int l_start, const db::Point &p_start)
{
db::NetTracerData tracer_data = tc.get_tracer_data (layout);
tracer.trace (layout, cell, p_start, l_start, tracer_data);
return db::NetTracerNet (tracer, db::ICplxTrans (), layout, cell.cell_index (), std::string (), std::string (), tracer_data);
}
static db::NetTracerNet trace (db::NetTracer &tracer, const db::Layout &layout, const db::Cell &cell, const db::NetTracerConnectivity &tc, unsigned int l_start, const db::Point &p_start, unsigned int l_stop, const db::Point &p_stop)
{
db::NetTracerData tracer_data = tc.get_tracer_data (layout);
tracer.trace (layout, cell, p_start, l_start, p_stop, l_stop, tracer_data);
return db::NetTracerNet (tracer, db::ICplxTrans (), layout, cell.cell_index (), std::string (), std::string (), tracer_data);
}
void run_test (tl::TestBase *_this, const std::string &file, const db::NetTracerConnectivity &tc, const db::LayerProperties &lp_start, const db::Point &p_start, const std::string &file_au, const char *net_name = 0, size_t depth = 0)
{
db::Manager m (false);
db::Layout layout_org (&m);
{
std::string fn (tl::testdata ());
fn += "/net_tracer/";
fn += file;
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (layout_org);
}
const db::Cell &cell = layout_org.cell (*layout_org.begin_top_down ());
db::NetTracer tracer;
tracer.set_trace_depth (depth);
db::NetTracerNet net = trace (tracer, layout_org, cell, tc, layer_for (layout_org, lp_start), p_start);
if (net_name) {
EXPECT_EQ (net.name (), std::string (net_name));
}
EXPECT_EQ (net.incomplete (), depth != 0);
if (depth > 0) {
EXPECT_EQ (net.size () <= depth, true);
}
db::Layout layout_net;
net.export_net (layout_net, layout_net.cell (layout_net.add_cell ("NET")));
std::string fn (tl::testdata ());
fn += "/net_tracer/";
fn += file_au;
CHECKPOINT ();
db::compare_layouts (_this, layout_net, fn, db::WriteOAS);
}
void run_test2 (tl::TestBase *_this, const std::string &file, const db::NetTracerConnectivity &tc, const db::LayerProperties &lp_start, const db::Point &p_start, const db::LayerProperties &lp_stop, const db::Point &p_stop, const std::string &file_au, const char *net_name = 0)
{
db::Manager m (false);
db::Layout layout_org (&m);
{
std::string fn (tl::testdata ());
fn += "/net_tracer/";
fn += file;
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (layout_org);
}
const db::Cell &cell = layout_org.cell (*layout_org.begin_top_down ());
db::NetTracer tracer;
db::NetTracerNet net = trace (tracer, layout_org, cell, tc, layer_for (layout_org, lp_start), p_start, layer_for (layout_org, lp_stop), p_stop);
if (net_name) {
EXPECT_EQ (net.name (), std::string (net_name));
}
db::Layout layout_net;
net.export_net (layout_net, layout_net.cell (layout_net.add_cell ("NET")));
std::string fn (tl::testdata ());
fn += "/net_tracer/";
fn += file_au;
CHECKPOINT ();
db::compare_layouts (_this, layout_net, fn, db::WriteOAS);
}
TEST(1)
{
std::string file = "t1.oas.gz";
std::string file_au = "t1_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1/0", "2/0", "3/0"));
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
}
TEST(1b)
{
std::string file = "t1.oas.gz";
std::string file_au = "t1b_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1/0", "2/0", "3/0"));
// point is off net ...
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 15000), file_au);
}
TEST(1c)
{
std::string file = "t1.oas.gz";
std::string file_au = "t1_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add_symbol (symbol ("a", "1/0"));
tc.add_symbol (symbol ("c", "cc"));
tc.add_symbol (symbol ("cc", "3/0"));
tc.add (connection ("a", "2/0", "cc"));
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
}
TEST(1d)
{
std::string file = "t1.oas.gz";
std::string file_au = "t1d_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1/0", "10/0", "11/0"));
// some layers are non-existing
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au);
}
TEST(2)
{
std::string file = "t2.oas.gz";
std::string file_au = "t2_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1/0", "2/0", "3/0"));
run_test2 (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), db::LayerProperties (3, 0), db::Point (4000, -20000), file_au, "THE_NAME");
}
TEST(3)
{
std::string file = "t3.oas.gz";
std::string file_au = "t3_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1/0", "2/0", "3/0"));
std::string msg;
try {
run_test2 (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), db::LayerProperties (3, 0), db::Point (4000, -20000), file_au);
} catch (tl::Exception &ex) {
msg = ex.msg ();
}
EXPECT_EQ (msg, "Nets are not connected");
}
TEST(4)
{
std::string file = "t4.oas.gz";
std::string file_au = "t4_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1/0", "2/0", "3/0"));
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "");
}
TEST(4b)
{
std::string file = "t4.oas.gz";
std::string file_au = "t4b_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1/0", "3/0"));
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
}
TEST(5)
{
std::string file = "t5.oas.gz";
std::string file_au = "t5_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1/0*10/0", "2/0", "3/0"));
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
}
TEST(5b)
{
std::string file = "t5.oas.gz";
std::string file_au = "t5b_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1/0", "2/0*10/0", "3/0"));
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
}
TEST(5c)
{
std::string file = "t5.oas.gz";
std::string file_au = "t5c_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1/0", "2/0-11/0", "3/0"));
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "");
}
TEST(5d)
{
std::string file = "t5.oas.gz";
std::string file_au = "t5d_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1/0-12/0", "2/0", "3/0-12/0"));
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
}
TEST(5e)
{
std::string file = "t5.oas.gz";
std::string file_au = "t5e_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1/0-12/0", "2/0", "3/0-12/0"));
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (7000, 1500), file_au, "THE_NAME");
}
TEST(5f)
{
std::string file = "t5.oas.gz";
std::string file_au = "t5f_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add_symbol (symbol ("x", "3-14"));
tc.add (connection ("10-13", "x"));
tc.add (connection ("x", "2", "1+13"));
run_test (_this, file, tc, db::LayerProperties (10, 0), db::Point (7000, 1500), file_au, "THE_NAME");
}
TEST(6)
{
std::string file = "t6.oas.gz";
std::string file_au = "t6_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1-10", "2", "3"));
tc.add (connection ("3", "4", "5"));
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (-2250, -900), file_au, "IN_B");
}
TEST(6b)
{
std::string file = "t6.oas.gz";
std::string file_au = "t6b_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("1-10", "2", "3"));
tc.add (connection ("3", "4", "5"));
run_test (_this, file, tc, db::LayerProperties (1, 0), db::Point (-2250, -900), file_au, "IN_B", 10);
}
TEST(7)
{
std::string file = "t7.oas.gz";
std::string file_au = "t7_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("15", "14", "2-7"));
tc.add (connection ("15", "14", "7"));
run_test (_this, file, tc, db::LayerProperties (15, 0), db::Point (-700, 300), file_au, "");
}
// bug #456: OASIS box arrays and net tracer
TEST(8)
{
std::string file = "t8.oas.gz";
std::string file_au = "t8_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add (connection ("15", "14", "7"));
run_test (_this, file, tc, db::LayerProperties (15, 0), db::Point (4000, 10000), file_au, "");
}
TEST(9)
{
std::string file = "t9.oas.gz";
std::string file_au = "t9_net.oas.gz";
db::NetTracerConnectivity tc;
tc.add_symbol (symbol ("a", "8-12"));
tc.add_symbol (symbol ("b", "a+7"));
tc.add_symbol (symbol ("c", "15*26"));
tc.add (connection ("b", "7"));
tc.add (connection ("b", "c", "9"));
run_test (_this, file, tc, db::LayerProperties (8, 0), db::Point (3000, 6800), file_au, "A");
}