mirror of https://github.com/KLayout/klayout.git
175 lines
6.1 KiB
C++
175 lines
6.1 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2024 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 "tlStream.h"
|
|
#include "tlFileUtils.h"
|
|
#include "dbLayoutToNetlist.h"
|
|
#include "dbTestSupport.h"
|
|
#include "dbReader.h"
|
|
#include "dbWriter.h"
|
|
#include "dbCommonReader.h"
|
|
|
|
static unsigned int define_layer (db::Layout &ly, db::LayerMap &lmap, int gds_layer, int gds_datatype = 0)
|
|
{
|
|
unsigned int lid = ly.insert_layer (db::LayerProperties (gds_layer, gds_datatype));
|
|
lmap.map (ly.get_properties (lid), lid);
|
|
return lid;
|
|
}
|
|
|
|
db::Region make_region (const db::RecursiveShapeIterator &si, db::DeepShapeStore &dss, bool flat)
|
|
{
|
|
return flat ? db::Region (si) : db::Region (si, dss);
|
|
}
|
|
|
|
void run_test (tl::TestBase *_this, bool flat, bool flat_nets, const std::string &au_fn)
|
|
{
|
|
db::Layout ly;
|
|
db::DeepShapeStore dss;
|
|
if (! flat_nets) {
|
|
dss.set_subcircuit_hierarchy_for_nets (true);
|
|
}
|
|
|
|
db::LayerMap lmap;
|
|
|
|
unsigned int poly = define_layer (ly, lmap, 1);
|
|
unsigned int cont = define_layer (ly, lmap, 2);
|
|
unsigned int metal1 = define_layer (ly, lmap, 3);
|
|
unsigned int via1 = define_layer (ly, lmap, 4);
|
|
unsigned int metal2 = define_layer (ly, lmap, 5);
|
|
unsigned int via2 = define_layer (ly, lmap, 6);
|
|
unsigned int metal3 = define_layer (ly, lmap, 7);
|
|
unsigned int via3 = define_layer (ly, lmap, 8);
|
|
unsigned int metal4 = define_layer (ly, lmap, 9);
|
|
|
|
{
|
|
db::LoadLayoutOptions options;
|
|
options.get_options<db::CommonReaderOptions> ().layer_map = lmap;
|
|
options.get_options<db::CommonReaderOptions> ().create_other_layers = false;
|
|
|
|
std::string fn = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "nets_proc_1.gds");
|
|
|
|
tl::InputStream stream (fn);
|
|
db::Reader reader (stream);
|
|
reader.read (ly, options);
|
|
}
|
|
|
|
db::Cell &tc = ly.cell (*ly.begin_top_down ());
|
|
|
|
db::Region rpoly = make_region (db::RecursiveShapeIterator (ly, tc, poly), dss, flat);
|
|
db::Region rcont = make_region (db::RecursiveShapeIterator (ly, tc, cont), dss, flat);
|
|
db::Region rmetal1 = make_region (db::RecursiveShapeIterator (ly, tc, metal1), dss, flat);
|
|
db::Region rvia1 = make_region (db::RecursiveShapeIterator (ly, tc, via1), dss, flat);
|
|
db::Region rmetal2 = make_region (db::RecursiveShapeIterator (ly, tc, metal2), dss, flat);
|
|
db::Region rvia2 = make_region (db::RecursiveShapeIterator (ly, tc, via2), dss, flat);
|
|
db::Region rmetal3 = make_region (db::RecursiveShapeIterator (ly, tc, metal3), dss, flat);
|
|
db::Region rvia3 = make_region (db::RecursiveShapeIterator (ly, tc, via3), dss, flat);
|
|
db::Region rmetal4 = make_region (db::RecursiveShapeIterator (ly, tc, metal4), dss, flat);
|
|
|
|
std::unique_ptr<db::LayoutToNetlist> l2n;
|
|
if (! flat) {
|
|
l2n.reset (new db::LayoutToNetlist (&dss));
|
|
EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), false);
|
|
} else {
|
|
l2n.reset (new db::LayoutToNetlist (ly.cell_name (tc.cell_index ()), ly.dbu ()));
|
|
}
|
|
|
|
// net extraction
|
|
|
|
if (flat) {
|
|
// flat or original layers need to be registered
|
|
l2n->register_layer (rpoly);
|
|
l2n->register_layer (rcont);
|
|
l2n->register_layer (rmetal1);
|
|
l2n->register_layer (rvia1);
|
|
l2n->register_layer (rmetal2);
|
|
l2n->register_layer (rvia2);
|
|
l2n->register_layer (rmetal3);
|
|
l2n->register_layer (rvia3);
|
|
l2n->register_layer (rmetal4);
|
|
}
|
|
|
|
// Intra-layer
|
|
l2n->connect (rpoly);
|
|
l2n->connect (rcont);
|
|
l2n->connect (rmetal1);
|
|
l2n->connect (rvia1);
|
|
l2n->connect (rmetal2);
|
|
l2n->connect (rvia2);
|
|
l2n->connect (rmetal3);
|
|
l2n->connect (rvia3);
|
|
l2n->connect (rmetal4);
|
|
// Inter-layer
|
|
l2n->connect (rpoly, rcont);
|
|
l2n->connect (rcont, rmetal1);
|
|
l2n->connect (rmetal1, rvia1);
|
|
l2n->connect (rvia1, rmetal2);
|
|
l2n->connect (rmetal2, rvia2);
|
|
l2n->connect (rvia2, rmetal3);
|
|
l2n->connect (rmetal3, rvia3);
|
|
l2n->connect (rvia3, rmetal4);
|
|
|
|
l2n->extract_netlist ();
|
|
|
|
db::Region rmetal1_nets = rmetal1.nets (*l2n, db::NPM_NetQualifiedNameOnly, tl::Variant (1));
|
|
if (! flat) {
|
|
EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), true);
|
|
}
|
|
db::Region rmetal2_nets = rmetal2.nets (*l2n, db::NPM_NetQualifiedNameOnly, tl::Variant (1));
|
|
|
|
db::Region res1 = rmetal1_nets.bool_and (rmetal2_nets, db::SamePropertiesConstraint);
|
|
db::Region res2 = rmetal1_nets.bool_and (rmetal2_nets, db::DifferentPropertiesConstraint);
|
|
db::Region res3 = rmetal1_nets.bool_and (rmetal2_nets, db::NoPropertyConstraint);
|
|
|
|
rmetal1_nets.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (100, 0)));
|
|
rmetal2_nets.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (101, 0)));
|
|
|
|
res1.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (1000, 0)));
|
|
res2.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (1001, 0)));
|
|
res3.insert_into (&ly, tc.cell_index (), ly.insert_layer (db::LayerProperties (1002, 0)));
|
|
|
|
// Test auto-unregistration
|
|
l2n.reset (0);
|
|
if (! flat) {
|
|
EXPECT_EQ (dss.has_net_builder_for (0, l2n.get ()), false);
|
|
}
|
|
|
|
std::string au_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), au_fn);
|
|
db::compare_layouts (_this, ly, au_path);
|
|
}
|
|
|
|
TEST(1_NetSpecificBoolFlat)
|
|
{
|
|
run_test (_this, false, true, "net_proc_au1.gds");
|
|
}
|
|
|
|
TEST(2_NetSpecificBoolFlatNets)
|
|
{
|
|
run_test (_this, false, true, "net_proc_au2.gds");
|
|
}
|
|
|
|
TEST(3_NetSpecificBoolFullyHier)
|
|
{
|
|
run_test (_this, false, false, "net_proc_au3.gds");
|
|
}
|