mirror of https://github.com/KLayout/klayout.git
397 lines
11 KiB
C++
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");
|
|
}
|
|
|