2019-01-19 22:19:08 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
KLayout Layout Viewer
|
2025-01-04 19:28:56 +01:00
|
|
|
Copyright (C) 2006-2025 Matthias Koefferlein
|
2019-01-19 22:19:08 +01:00
|
|
|
|
|
|
|
|
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 "dbLayoutToNetlist.h"
|
|
|
|
|
#include "dbLayoutToNetlistReader.h"
|
|
|
|
|
#include "dbLayoutToNetlistWriter.h"
|
|
|
|
|
#include "dbStream.h"
|
|
|
|
|
#include "dbCommonReader.h"
|
|
|
|
|
#include "dbNetlistDeviceExtractorClasses.h"
|
2019-01-20 02:50:23 +01:00
|
|
|
#include "dbTestSupport.h"
|
2019-01-19 22:19:08 +01:00
|
|
|
|
|
|
|
|
#include "tlUnitTest.h"
|
|
|
|
|
#include "tlStream.h"
|
|
|
|
|
#include "tlFileUtils.h"
|
|
|
|
|
|
|
|
|
|
TEST(1_ReaderBasic)
|
|
|
|
|
{
|
2019-01-20 23:12:27 +01:00
|
|
|
db::LayoutToNetlist l2n;
|
2019-01-19 22:19:08 +01:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string in_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_in.txt");
|
2019-01-19 22:19:08 +01:00
|
|
|
tl::InputStream is_in (in_path);
|
|
|
|
|
|
|
|
|
|
db::LayoutToNetlistStandardReader reader (is_in);
|
|
|
|
|
reader.read (&l2n);
|
|
|
|
|
|
|
|
|
|
// verify against the input
|
|
|
|
|
|
|
|
|
|
std::string path = tmp_file ("tmp_l2nreader_1.txt");
|
|
|
|
|
{
|
|
|
|
|
tl::OutputStream stream (path);
|
|
|
|
|
db::LayoutToNetlistStandardWriter writer (stream, false);
|
|
|
|
|
writer.write (&l2n);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_in.txt");
|
2019-01-19 22:19:08 +01:00
|
|
|
|
2019-07-16 00:40:43 +02:00
|
|
|
compare_text_files (path, au_path);
|
2019-01-19 23:00:19 +01:00
|
|
|
|
2019-01-20 02:50:23 +01:00
|
|
|
// test build_all_nets from read l2n
|
2019-01-19 23:00:19 +01:00
|
|
|
|
2019-01-20 02:50:23 +01:00
|
|
|
{
|
|
|
|
|
db::Layout ly2;
|
2019-01-20 23:12:27 +01:00
|
|
|
ly2.dbu (l2n.internal_layout ()->dbu ());
|
2019-01-20 02:50:23 +01:00
|
|
|
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
|
|
|
|
|
|
|
|
|
|
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/);
|
|
|
|
|
|
2025-03-09 19:22:04 +01:00
|
|
|
std::map<unsigned int, unsigned int> lmap;
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_index_by_name ("psd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_index_by_name ("nsd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_index_by_name ("poly").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_index_by_name ("diff_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_index_by_name ("poly_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_index_by_name ("metal1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_index_by_name ("via1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_index_by_name ("metal2").value ();
|
2019-01-20 02:50:23 +01:00
|
|
|
|
2023-01-19 12:08:50 +01:00
|
|
|
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_Disconnected, 0, "DEVICE_");
|
2019-01-20 02:50:23 +01:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au = tl::testdata ();
|
2019-01-20 02:50:23 +01:00
|
|
|
au = tl::combine_path (au, "algo");
|
2019-06-12 22:55:24 +02:00
|
|
|
au = tl::combine_path (au, "l2n_reader_au_1.gds");
|
|
|
|
|
|
|
|
|
|
db::compare_layouts (_this, ly2, au);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
db::Layout ly2;
|
|
|
|
|
ly2.dbu (l2n.internal_layout ()->dbu ());
|
|
|
|
|
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
|
|
|
|
|
|
2025-03-09 19:22:04 +01:00
|
|
|
std::map<unsigned int, unsigned int> lmap;
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_index_by_name ("psd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_index_by_name ("nsd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_index_by_name ("poly").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_index_by_name ("diff_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_index_by_name ("poly_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_index_by_name ("metal1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_index_by_name ("via1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_index_by_name ("metal2").value ();
|
2019-06-12 22:55:24 +02:00
|
|
|
|
|
|
|
|
std::vector<const db::Net *> nets;
|
|
|
|
|
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VSS"));
|
2019-12-15 01:29:56 +01:00
|
|
|
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("FB"));
|
2019-06-12 22:55:24 +02:00
|
|
|
|
|
|
|
|
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, nets);
|
|
|
|
|
|
2023-01-19 12:08:50 +01:00
|
|
|
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_Disconnected, 0, "DEVICE_");
|
2019-06-12 22:55:24 +02:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au = tl::testdata ();
|
2019-06-12 22:55:24 +02:00
|
|
|
au = tl::combine_path (au, "algo");
|
|
|
|
|
au = tl::combine_path (au, "l2n_reader_au_1b.gds");
|
|
|
|
|
|
|
|
|
|
db::compare_layouts (_this, ly2, au);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
db::Layout ly2;
|
|
|
|
|
ly2.dbu (l2n.internal_layout ()->dbu ());
|
|
|
|
|
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
|
|
|
|
|
|
2025-03-09 19:22:04 +01:00
|
|
|
std::map<unsigned int, unsigned int> lmap;
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_index_by_name ("psd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_index_by_name ("nsd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_index_by_name ("poly").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_index_by_name ("diff_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_index_by_name ("poly_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_index_by_name ("metal1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_index_by_name ("via1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_index_by_name ("metal2").value ();
|
2019-06-12 22:55:24 +02:00
|
|
|
|
|
|
|
|
std::vector<const db::Net *> nets;
|
|
|
|
|
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VSS"));
|
|
|
|
|
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VDD"));
|
|
|
|
|
|
|
|
|
|
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, nets);
|
|
|
|
|
|
2023-01-19 12:08:50 +01:00
|
|
|
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_Flatten, 0, "DEVICE_");
|
2019-06-12 22:55:24 +02:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au = tl::testdata ();
|
2019-06-12 22:55:24 +02:00
|
|
|
au = tl::combine_path (au, "algo");
|
|
|
|
|
au = tl::combine_path (au, "l2n_reader_au_1c.gds");
|
|
|
|
|
|
|
|
|
|
db::compare_layouts (_this, ly2, au);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
db::Layout ly2;
|
|
|
|
|
ly2.dbu (l2n.internal_layout ()->dbu ());
|
|
|
|
|
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
|
|
|
|
|
|
2025-03-09 19:22:04 +01:00
|
|
|
std::map<unsigned int, unsigned int> lmap;
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_index_by_name ("psd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_index_by_name ("nsd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_index_by_name ("poly").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_index_by_name ("diff_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_index_by_name ("poly_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_index_by_name ("metal1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_index_by_name ("via1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_index_by_name ("metal2").value ();
|
2019-06-12 22:55:24 +02:00
|
|
|
|
|
|
|
|
std::vector<const db::Net *> nets;
|
|
|
|
|
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VSS"));
|
|
|
|
|
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VDD"));
|
|
|
|
|
|
|
|
|
|
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, nets);
|
|
|
|
|
|
2023-01-19 12:08:50 +01:00
|
|
|
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
|
2019-06-12 22:55:24 +02:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au = tl::testdata ();
|
2019-06-12 22:55:24 +02:00
|
|
|
au = tl::combine_path (au, "algo");
|
|
|
|
|
au = tl::combine_path (au, "l2n_reader_au_1d.gds");
|
|
|
|
|
|
|
|
|
|
db::compare_layouts (_this, ly2, au);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
db::Layout ly2;
|
|
|
|
|
ly2.dbu (l2n.internal_layout ()->dbu ());
|
|
|
|
|
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
|
|
|
|
|
|
2025-03-09 19:22:04 +01:00
|
|
|
std::map<unsigned int, unsigned int> lmap;
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_index_by_name ("psd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_index_by_name ("nsd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_index_by_name ("poly").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_index_by_name ("diff_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_index_by_name ("poly_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_index_by_name ("metal1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_index_by_name ("via1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_index_by_name ("metal2").value ();
|
2019-06-12 22:55:24 +02:00
|
|
|
|
|
|
|
|
std::vector<const db::Net *> nets;
|
|
|
|
|
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VSS"));
|
|
|
|
|
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VDD"));
|
|
|
|
|
nets.push_back (l2n.netlist ()->circuit_by_name ("INV2")->net_by_name ("IN"));
|
|
|
|
|
|
|
|
|
|
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, nets);
|
|
|
|
|
|
2023-01-19 12:08:50 +01:00
|
|
|
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", 0);
|
2019-06-12 22:55:24 +02:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au = tl::testdata ();
|
2019-06-12 22:55:24 +02:00
|
|
|
au = tl::combine_path (au, "algo");
|
|
|
|
|
au = tl::combine_path (au, "l2n_reader_au_1e.gds");
|
|
|
|
|
|
|
|
|
|
db::compare_layouts (_this, ly2, au);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
db::Layout ly2;
|
|
|
|
|
ly2.dbu (l2n.internal_layout ()->dbu ());
|
|
|
|
|
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
|
|
|
|
|
|
2025-03-09 19:22:04 +01:00
|
|
|
std::map<unsigned int, unsigned int> lmap;
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_index_by_name ("psd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_index_by_name ("nsd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_index_by_name ("poly").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_index_by_name ("diff_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_index_by_name ("poly_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_index_by_name ("metal1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_index_by_name ("via1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_index_by_name ("metal2").value ();
|
2019-06-12 22:55:24 +02:00
|
|
|
|
|
|
|
|
std::vector<const db::Net *> nets;
|
|
|
|
|
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VSS"));
|
|
|
|
|
nets.push_back (l2n.netlist ()->circuit_by_name ("RINGO")->net_by_name ("VDD"));
|
|
|
|
|
nets.push_back (l2n.netlist ()->circuit_by_name ("INV2")->net_by_name ("IN"));
|
|
|
|
|
|
|
|
|
|
db::CellMapping cm = l2n.const_cell_mapping_into (ly2, top2);
|
|
|
|
|
|
2023-01-19 12:08:50 +01:00
|
|
|
l2n.build_nets (&nets, cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
|
2019-06-12 22:55:24 +02:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au = tl::testdata ();
|
2019-06-12 22:55:24 +02:00
|
|
|
au = tl::combine_path (au, "algo");
|
|
|
|
|
au = tl::combine_path (au, "l2n_reader_au_1f.gds");
|
2019-01-20 02:50:23 +01:00
|
|
|
|
|
|
|
|
db::compare_layouts (_this, ly2, au);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-20 17:31:58 +01:00
|
|
|
TEST(1b_ReaderBasicShort)
|
2019-01-20 02:50:23 +01:00
|
|
|
{
|
2021-07-17 00:20:55 +02:00
|
|
|
EXPECT_EQ (true, true); // removes "unreferenced _this" compiler warning
|
|
|
|
|
|
2019-01-20 23:12:27 +01:00
|
|
|
db::LayoutToNetlist l2n;
|
2019-01-19 23:00:19 +01:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string in_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_in_s.txt");
|
2019-01-20 02:50:23 +01:00
|
|
|
tl::InputStream is_in (in_path);
|
|
|
|
|
|
|
|
|
|
db::LayoutToNetlistStandardReader reader (is_in);
|
|
|
|
|
reader.read (&l2n);
|
|
|
|
|
|
|
|
|
|
// verify against the input
|
|
|
|
|
|
2019-11-13 00:06:29 +01:00
|
|
|
std::string path = tmp_file ("tmp.txt");
|
2019-01-19 23:00:19 +01:00
|
|
|
{
|
|
|
|
|
tl::OutputStream stream (path);
|
2019-01-20 02:50:23 +01:00
|
|
|
db::LayoutToNetlistStandardWriter writer (stream, true);
|
2019-01-19 23:00:19 +01:00
|
|
|
writer.write (&l2n);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_in_s.txt");
|
2019-01-19 23:00:19 +01:00
|
|
|
|
2019-07-16 00:40:43 +02:00
|
|
|
compare_text_files (path, au_path);
|
2019-01-19 22:19:08 +01:00
|
|
|
}
|
2019-01-20 17:31:58 +01:00
|
|
|
|
2019-11-13 00:06:29 +01:00
|
|
|
TEST(1c_ReaderBasicShortWithProps)
|
|
|
|
|
{
|
|
|
|
|
db::LayoutToNetlist l2n;
|
|
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string in_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_in_p.txt");
|
2019-11-13 00:06:29 +01:00
|
|
|
tl::InputStream is_in (in_path);
|
|
|
|
|
|
|
|
|
|
db::LayoutToNetlistStandardReader reader (is_in);
|
|
|
|
|
reader.read (&l2n);
|
|
|
|
|
|
|
|
|
|
// verify against the input
|
|
|
|
|
|
|
|
|
|
std::string path = tmp_file ("tmp.txt");
|
|
|
|
|
{
|
|
|
|
|
tl::OutputStream stream (path);
|
|
|
|
|
db::LayoutToNetlistStandardWriter writer (stream, true);
|
|
|
|
|
writer.write (&l2n);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_in_p.txt");
|
2019-11-13 00:06:29 +01:00
|
|
|
|
|
|
|
|
compare_text_files (path, au_path);
|
2019-11-13 23:09:09 +01:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
db::Layout ly2;
|
|
|
|
|
ly2.dbu (l2n.internal_layout ()->dbu ());
|
|
|
|
|
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
|
|
|
|
|
|
2025-03-09 19:22:04 +01:00
|
|
|
std::map<unsigned int, unsigned int> lmap;
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (3, 0))] = l2n.layer_index_by_name ("poly").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (3, 1))] = l2n.layer_index_by_name ("poly_lbl").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (4, 0))] = l2n.layer_index_by_name ("diff_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (5, 0))] = l2n.layer_index_by_name ("poly_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (6, 0))] = l2n.layer_index_by_name ("metal1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (6, 1))] = l2n.layer_index_by_name ("metal1_lbl").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (7, 0))] = l2n.layer_index_by_name ("via1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (8, 0))] = l2n.layer_index_by_name ("metal2").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (8, 1))] = l2n.layer_index_by_name ("metal2_lbl").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_index_by_name ("psd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_index_by_name ("nsd").value ();
|
2019-11-13 23:09:09 +01:00
|
|
|
|
|
|
|
|
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2);
|
|
|
|
|
|
2023-01-19 12:08:50 +01:00
|
|
|
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_AllProperties, tl::Variant (), db::BNH_Disconnected, 0, "DEVICE_");
|
2019-11-13 23:09:09 +01:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au = tl::testdata ();
|
2019-11-13 23:09:09 +01:00
|
|
|
au = tl::combine_path (au, "algo");
|
2020-05-22 00:58:46 +02:00
|
|
|
au = tl::combine_path (au, "l2n_reader_au_p.oas");
|
2019-11-13 23:09:09 +01:00
|
|
|
|
2023-01-14 23:46:48 +01:00
|
|
|
db::compare_layouts (_this, ly2, au, db::NormalizationMode (db::WriteOAS | db::AsPolygons));
|
2019-11-13 23:09:09 +01:00
|
|
|
}
|
2019-11-13 00:06:29 +01:00
|
|
|
}
|
|
|
|
|
|
2019-01-20 17:31:58 +01:00
|
|
|
TEST(2_ReaderWithGlobalNets)
|
|
|
|
|
{
|
2019-01-20 23:12:27 +01:00
|
|
|
db::LayoutToNetlist l2n;
|
2019-01-20 17:31:58 +01:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string in_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_au.txt");
|
2019-01-20 17:31:58 +01:00
|
|
|
tl::InputStream is_in (in_path);
|
|
|
|
|
|
|
|
|
|
db::LayoutToNetlistStandardReader reader (is_in);
|
|
|
|
|
reader.read (&l2n);
|
|
|
|
|
|
|
|
|
|
// verify against the input
|
|
|
|
|
|
2019-11-13 00:06:29 +01:00
|
|
|
std::string path = tmp_file ("tmp.txt");
|
2019-01-20 17:31:58 +01:00
|
|
|
{
|
|
|
|
|
tl::OutputStream stream (path);
|
|
|
|
|
db::LayoutToNetlistStandardWriter writer (stream, false);
|
|
|
|
|
writer.write (&l2n);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_au.txt");
|
2019-01-20 17:31:58 +01:00
|
|
|
|
2019-07-16 00:40:43 +02:00
|
|
|
compare_text_files (path, au_path);
|
2019-05-04 23:06:18 +02:00
|
|
|
|
|
|
|
|
// test build_all_nets from read l2n
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
db::Layout ly2;
|
|
|
|
|
ly2.dbu (l2n.internal_layout ()->dbu ());
|
|
|
|
|
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
|
|
|
|
|
|
|
|
|
|
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/);
|
|
|
|
|
|
2025-03-09 19:22:04 +01:00
|
|
|
std::map<unsigned int, unsigned int> lmap;
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_index_by_name ("psd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_index_by_name ("nsd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (12, 0))] = l2n.layer_index_by_name ("rbulk").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (13, 0))] = l2n.layer_index_by_name ("ptie").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (14, 0))] = l2n.layer_index_by_name ("ntie").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (1, 0)) ] = l2n.layer_index_by_name ("nwell").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_index_by_name ("poly").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_index_by_name ("diff_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_index_by_name ("poly_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_index_by_name ("metal1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_index_by_name ("via1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_index_by_name ("metal2").value ();
|
2019-05-04 23:06:18 +02:00
|
|
|
|
2023-01-19 12:08:50 +01:00
|
|
|
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
|
2019-05-04 23:06:18 +02:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au = tl::testdata ();
|
2019-05-04 23:06:18 +02:00
|
|
|
au = tl::combine_path (au, "algo");
|
2019-08-30 10:52:51 +02:00
|
|
|
au = tl::combine_path (au, "l2n_reader_au_2r.gds");
|
2019-05-04 23:06:18 +02:00
|
|
|
|
|
|
|
|
db::compare_layouts (_this, ly2, au);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(3_ReaderAbsoluteCoordinates)
|
|
|
|
|
{
|
|
|
|
|
db::LayoutToNetlist l2n;
|
|
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string in_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_au_abs.txt");
|
2019-05-04 23:06:18 +02:00
|
|
|
tl::InputStream is_in (in_path);
|
|
|
|
|
|
|
|
|
|
db::LayoutToNetlistStandardReader reader (is_in);
|
|
|
|
|
reader.read (&l2n);
|
|
|
|
|
|
|
|
|
|
// verify against the input
|
|
|
|
|
|
2019-11-13 00:06:29 +01:00
|
|
|
std::string path = tmp_file ("tmp.txt");
|
2019-05-04 23:06:18 +02:00
|
|
|
{
|
|
|
|
|
tl::OutputStream stream (path);
|
|
|
|
|
db::LayoutToNetlistStandardWriter writer (stream, false);
|
|
|
|
|
writer.write (&l2n);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_au.txt");
|
2019-05-04 23:06:18 +02:00
|
|
|
|
2019-07-16 00:40:43 +02:00
|
|
|
compare_text_files (path, au_path);
|
2019-01-20 17:31:58 +01:00
|
|
|
|
|
|
|
|
// test build_all_nets from read l2n
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
db::Layout ly2;
|
2019-01-20 23:12:27 +01:00
|
|
|
ly2.dbu (l2n.internal_layout ()->dbu ());
|
2019-01-20 17:31:58 +01:00
|
|
|
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
|
|
|
|
|
|
|
|
|
|
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/);
|
|
|
|
|
|
2025-03-09 19:22:04 +01:00
|
|
|
std::map<unsigned int, unsigned int> lmap;
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = l2n.layer_index_by_name ("psd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = l2n.layer_index_by_name ("nsd").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (12, 0))] = l2n.layer_index_by_name ("rbulk").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (13, 0))] = l2n.layer_index_by_name ("ptie").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (14, 0))] = l2n.layer_index_by_name ("ntie").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (1, 0)) ] = l2n.layer_index_by_name ("nwell").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = l2n.layer_index_by_name ("poly").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = l2n.layer_index_by_name ("diff_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = l2n.layer_index_by_name ("poly_cont").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = l2n.layer_index_by_name ("metal1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = l2n.layer_index_by_name ("via1").value ();
|
|
|
|
|
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = l2n.layer_index_by_name ("metal2").value ();
|
2019-01-20 17:31:58 +01:00
|
|
|
|
2023-01-19 12:08:50 +01:00
|
|
|
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
|
2019-01-20 17:31:58 +01:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au = tl::testdata ();
|
2019-01-20 17:31:58 +01:00
|
|
|
au = tl::combine_path (au, "algo");
|
2019-08-30 10:52:51 +02:00
|
|
|
au = tl::combine_path (au, "l2n_reader_au_2r.gds");
|
2019-01-20 17:31:58 +01:00
|
|
|
|
|
|
|
|
db::compare_layouts (_this, ly2, au);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-10 00:15:51 +02:00
|
|
|
TEST(4_ReaderCombinedDevices)
|
|
|
|
|
{
|
|
|
|
|
db::LayoutToNetlist l2n;
|
|
|
|
|
|
|
|
|
|
// build from: testdata/algo/l2n_reader_4.gds
|
|
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string in_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_4.l2n");
|
2019-05-10 00:15:51 +02:00
|
|
|
tl::InputStream is_in (in_path);
|
|
|
|
|
|
|
|
|
|
db::LayoutToNetlistStandardReader reader (is_in);
|
|
|
|
|
reader.read (&l2n);
|
|
|
|
|
|
|
|
|
|
// verify against the input
|
|
|
|
|
|
2019-11-13 00:06:29 +01:00
|
|
|
std::string path = tmp_file ("tmp.txt");
|
2019-05-10 00:15:51 +02:00
|
|
|
{
|
|
|
|
|
tl::OutputStream stream (path);
|
|
|
|
|
db::LayoutToNetlistStandardWriter writer (stream, false);
|
|
|
|
|
writer.write (&l2n);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_au_4.l2n");
|
2019-05-10 00:15:51 +02:00
|
|
|
|
2019-07-16 00:40:43 +02:00
|
|
|
compare_text_files (path, au_path);
|
2019-05-10 00:15:51 +02:00
|
|
|
|
|
|
|
|
// test build_all_nets from read l2n
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
db::Layout ly2;
|
|
|
|
|
ly2.dbu (l2n.internal_layout ()->dbu ());
|
|
|
|
|
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
|
|
|
|
|
|
|
|
|
|
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/);
|
|
|
|
|
|
2025-03-09 19:22:04 +01:00
|
|
|
std::map<unsigned int, unsigned int> lmap = l2n.create_layermap (ly2, 1000);
|
2019-05-10 00:15:51 +02:00
|
|
|
|
2023-01-19 12:08:50 +01:00
|
|
|
l2n.build_all_nets (cm, ly2, lmap, "NET_", db::NPM_NoProperties, tl::Variant (), db::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_");
|
2019-05-10 00:15:51 +02:00
|
|
|
|
2021-05-01 21:36:52 +02:00
|
|
|
std::string au = tl::testdata ();
|
2019-05-10 00:15:51 +02:00
|
|
|
au = tl::combine_path (au, "algo");
|
|
|
|
|
au = tl::combine_path (au, "l2n_reader_au_4.gds");
|
|
|
|
|
|
|
|
|
|
db::compare_layouts (_this, ly2, au);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-06 23:44:06 +02:00
|
|
|
TEST(5_ReaderFuture)
|
|
|
|
|
{
|
|
|
|
|
db::LayoutToNetlist l2n;
|
|
|
|
|
|
|
|
|
|
std::string in_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_5.l2n");
|
|
|
|
|
tl::InputStream is_in (in_path);
|
|
|
|
|
|
|
|
|
|
db::LayoutToNetlistStandardReader reader (is_in);
|
|
|
|
|
reader.read (&l2n);
|
|
|
|
|
|
|
|
|
|
// verify against the input
|
|
|
|
|
|
|
|
|
|
std::string path = tmp_file ("tmp.txt");
|
|
|
|
|
{
|
|
|
|
|
tl::OutputStream stream (path);
|
|
|
|
|
db::LayoutToNetlistStandardWriter writer (stream, false);
|
|
|
|
|
writer.write (&l2n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string au_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_au_5.l2n");
|
|
|
|
|
|
|
|
|
|
compare_text_files (path, au_path);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-17 19:58:22 +02:00
|
|
|
TEST(6_ReaderLog)
|
|
|
|
|
{
|
|
|
|
|
db::LayoutToNetlist l2n;
|
|
|
|
|
|
|
|
|
|
std::string in_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_6.l2n");
|
|
|
|
|
tl::InputStream is_in (in_path);
|
|
|
|
|
|
|
|
|
|
db::LayoutToNetlistStandardReader reader (is_in);
|
|
|
|
|
reader.read (&l2n);
|
|
|
|
|
|
|
|
|
|
// verify against the input
|
|
|
|
|
|
|
|
|
|
std::string path = tmp_file ("tmp.txt");
|
|
|
|
|
{
|
|
|
|
|
tl::OutputStream stream (path);
|
|
|
|
|
db::LayoutToNetlistStandardWriter writer (stream, false);
|
|
|
|
|
writer.write (&l2n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string au_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_au_6.l2n");
|
|
|
|
|
|
|
|
|
|
compare_text_files (path, au_path);
|
|
|
|
|
|
|
|
|
|
std::string in_path_s = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_6s.l2n");
|
|
|
|
|
tl::InputStream is_in_s (in_path_s);
|
|
|
|
|
|
|
|
|
|
l2n.clear_log_entries ();
|
|
|
|
|
db::LayoutToNetlistStandardReader reader_s (is_in_s);
|
|
|
|
|
reader_s.read (&l2n);
|
|
|
|
|
|
|
|
|
|
// verify against the input
|
|
|
|
|
|
|
|
|
|
path = tmp_file ("tmp2.txt");
|
|
|
|
|
{
|
|
|
|
|
tl::OutputStream stream (path);
|
|
|
|
|
db::LayoutToNetlistStandardWriter writer (stream, false);
|
|
|
|
|
writer.write (&l2n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
compare_text_files (path, au_path);
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-29 19:18:39 +02:00
|
|
|
// issue #1696
|
|
|
|
|
TEST(7_CustomDevice)
|
|
|
|
|
{
|
|
|
|
|
db::LayoutToNetlist l2n;
|
|
|
|
|
|
|
|
|
|
std::string in_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_7.l2n");
|
|
|
|
|
tl::InputStream is_in (in_path);
|
|
|
|
|
|
|
|
|
|
db::LayoutToNetlistStandardReader reader (is_in);
|
|
|
|
|
reader.read (&l2n);
|
|
|
|
|
|
|
|
|
|
// verify against the input
|
|
|
|
|
|
|
|
|
|
std::string path = tmp_file ("tmp.txt");
|
|
|
|
|
{
|
|
|
|
|
tl::OutputStream stream (path);
|
|
|
|
|
db::LayoutToNetlistStandardWriter writer (stream, false);
|
|
|
|
|
writer.write (&l2n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string au_path = tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "l2n_reader_au_7.l2n");
|
|
|
|
|
|
|
|
|
|
compare_text_files (path, au_path);
|
|
|
|
|
}
|