klayout/src/db/unit_tests/dbNetlistWriterTests.cc

1436 lines
48 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2019 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 "dbNetlistWriter.h"
#include "dbNetlistSpiceWriter.h"
#include "dbNetlist.h"
#include "dbNetlistDeviceClasses.h"
#include "dbLayoutToNetlist.h"
#include "tlUnitTest.h"
#include "tlStream.h"
#include "tlFileUtils.h"
static void compare_netlists (tl::TestBase *_this, const std::string &path, const std::string &au_path)
{
tl::InputStream is (path);
tl::InputStream is_au (au_path);
std::string netlist = is.read_all ();
std::string netlist_au = is_au.read_all ();
// normalize "1.0e-005" to "1.0e-05" for compatibility
netlist = tl::replaced (netlist, "\r\n", "\n"); // for Windows
netlist = tl::replaced (netlist, "e-00", "e-0");
netlist = tl::replaced (netlist, "e-0", "e-");
netlist_au = tl::replaced (netlist_au, "\r\n", "\n"); // for Windows
netlist_au = tl::replaced (netlist_au, "e-00", "e-0");
netlist_au = tl::replaced (netlist_au, "e-0", "e-");
if (netlist != netlist_au) {
_this->raise (tl::sprintf ("Compare failed - see\n actual: %s\n golden: %s",
tl::absolute_file_path (path),
tl::absolute_file_path (au_path)));
}
}
TEST(1_WriterResistorDevices)
{
db::Netlist nl;
db::DeviceClass *rcls = new db::DeviceClassResistor ();
rcls->set_name ("RCLS");
nl.add_device_class (rcls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
db::Net *n1, *n2, *n3;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
db::Device *rdev1 = new db::Device (rcls);
rdev1->set_parameter_value (db::DeviceClassResistor::param_id_R, 1.7);
db::Device *rdev2 = new db::Device (rcls);
rdev2->set_parameter_value (db::DeviceClassResistor::param_id_R, 42e-6);
circuit1->add_device (rdev1);
circuit1->add_device (rdev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
rdev1->connect_terminal (rdev1->device_class ()->terminal_id_for_name ("A"), n1);
rdev1->connect_terminal (rdev1->device_class ()->terminal_id_for_name ("B"), n3);
rdev2->connect_terminal (rdev2->device_class ()->terminal_id_for_name ("A"), n3);
rdev2->connect_terminal (rdev2->device_class ()->terminal_id_for_name ("B"), n2);
// verify against the input
std::string path = tmp_file ("tmp_nwriter1.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter1_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(1_WriterResistorDevicesWithBulk)
{
db::Netlist nl;
db::DeviceClass *rcls = new db::DeviceClassResistorWithBulk ();
rcls->set_name ("RCLS");
nl.add_device_class (rcls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
db::Net *n1, *n2, *n3;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
db::Device *rdev1 = new db::Device (rcls);
rdev1->set_parameter_value (db::DeviceClassResistor::param_id_R, 1.7);
db::Device *rdev2 = new db::Device (rcls);
rdev2->set_parameter_value (db::DeviceClassResistor::param_id_R, 42e-6);
circuit1->add_device (rdev1);
circuit1->add_device (rdev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
rdev1->connect_terminal (rdev1->device_class ()->terminal_id_for_name ("A"), n1);
rdev1->connect_terminal (rdev1->device_class ()->terminal_id_for_name ("B"), n3);
rdev1->connect_terminal (rdev1->device_class ()->terminal_id_for_name ("W"), n3);
rdev2->connect_terminal (rdev2->device_class ()->terminal_id_for_name ("A"), n3);
rdev2->connect_terminal (rdev2->device_class ()->terminal_id_for_name ("B"), n2);
rdev2->connect_terminal (rdev2->device_class ()->terminal_id_for_name ("W"), n3);
// verify against the input
std::string path = tmp_file ("tmp_nwriter1.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter1_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(2_WriterCapacitorDevices)
{
db::Netlist nl;
db::DeviceClass *ccls = new db::DeviceClassCapacitor ();
ccls->set_name ("CCLS");
nl.add_device_class (ccls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
db::Net *n1, *n2, *n3;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
db::Device *cdev1 = new db::Device (ccls);
cdev1->set_parameter_value (db::DeviceClassCapacitor::param_id_C, 1.7e-12);
db::Device *cdev2 = new db::Device (ccls);
cdev2->set_parameter_value (db::DeviceClassCapacitor::param_id_C, 42e-15);
circuit1->add_device (cdev1);
circuit1->add_device (cdev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
cdev1->connect_terminal (cdev1->device_class ()->terminal_id_for_name ("A"), n1);
cdev1->connect_terminal (cdev1->device_class ()->terminal_id_for_name ("B"), n3);
cdev2->connect_terminal (cdev2->device_class ()->terminal_id_for_name ("A"), n3);
cdev2->connect_terminal (cdev2->device_class ()->terminal_id_for_name ("B"), n2);
// verify against the input
std::string path = tmp_file ("tmp_nwriter2.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter2_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(2_WriterCapacitorDevicesWithBulk)
{
db::Netlist nl;
db::DeviceClass *ccls = new db::DeviceClassCapacitorWithBulk ();
ccls->set_name ("CCLS");
nl.add_device_class (ccls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
db::Net *n1, *n2, *n3;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
db::Device *cdev1 = new db::Device (ccls);
cdev1->set_parameter_value (db::DeviceClassCapacitor::param_id_C, 1.7e-12);
db::Device *cdev2 = new db::Device (ccls);
cdev2->set_parameter_value (db::DeviceClassCapacitor::param_id_C, 42e-15);
circuit1->add_device (cdev1);
circuit1->add_device (cdev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
cdev1->connect_terminal (cdev1->device_class ()->terminal_id_for_name ("A"), n1);
cdev1->connect_terminal (cdev1->device_class ()->terminal_id_for_name ("B"), n3);
cdev1->connect_terminal (cdev1->device_class ()->terminal_id_for_name ("W"), n3);
cdev2->connect_terminal (cdev2->device_class ()->terminal_id_for_name ("A"), n3);
cdev2->connect_terminal (cdev2->device_class ()->terminal_id_for_name ("B"), n2);
cdev2->connect_terminal (cdev2->device_class ()->terminal_id_for_name ("W"), n3);
// verify against the input
std::string path = tmp_file ("tmp_nwriter2.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter2_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(3_WriterInductorDevices)
{
db::Netlist nl;
db::DeviceClass *rcls = new db::DeviceClassResistor ();
db::DeviceClass *ccls = new db::DeviceClassCapacitor ();
db::DeviceClass *lcls = new db::DeviceClassInductor ();
db::DeviceClass *dcls = new db::DeviceClassDiode ();
db::DeviceClass *m3cls = new db::DeviceClassMOS3Transistor ();
db::DeviceClass *m4cls = new db::DeviceClassMOS4Transistor ();
rcls->set_name ("RCLS");
lcls->set_name ("LCLS");
ccls->set_name ("CCLS");
dcls->set_name ("DCLS");
m3cls->set_name ("M3CLS");
m4cls->set_name ("M4CLS");
nl.add_device_class (rcls);
nl.add_device_class (lcls);
nl.add_device_class (ccls);
nl.add_device_class (dcls);
nl.add_device_class (m3cls);
nl.add_device_class (m4cls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
db::Net *n1, *n2, *n3;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
db::Device *ldev1 = new db::Device (lcls);
ldev1->set_parameter_value (db::DeviceClassInductor::param_id_L, 1.7e-10);
db::Device *ldev2 = new db::Device (lcls);
ldev2->set_parameter_value (db::DeviceClassInductor::param_id_L, 42e-9);
circuit1->add_device (ldev1);
circuit1->add_device (ldev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
ldev1->connect_terminal (ldev1->device_class ()->terminal_id_for_name ("A"), n1);
ldev1->connect_terminal (ldev1->device_class ()->terminal_id_for_name ("B"), n3);
ldev2->connect_terminal (ldev2->device_class ()->terminal_id_for_name ("A"), n3);
ldev2->connect_terminal (ldev2->device_class ()->terminal_id_for_name ("B"), n2);
// verify against the input
std::string path = tmp_file ("tmp_nwriter3.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter3_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(4_WriterDiodeDevices)
{
db::Netlist nl;
db::DeviceClass *rcls = new db::DeviceClassResistor ();
db::DeviceClass *ccls = new db::DeviceClassCapacitor ();
db::DeviceClass *lcls = new db::DeviceClassInductor ();
db::DeviceClass *dcls = new db::DeviceClassDiode ();
db::DeviceClass *m3cls = new db::DeviceClassMOS3Transistor ();
db::DeviceClass *m4cls = new db::DeviceClassMOS4Transistor ();
rcls->set_name ("RCLS");
lcls->set_name ("LCLS");
ccls->set_name ("CCLS");
dcls->set_name ("DCLS");
m3cls->set_name ("M3CLS");
m4cls->set_name ("M4CLS");
nl.add_device_class (rcls);
nl.add_device_class (lcls);
nl.add_device_class (ccls);
nl.add_device_class (dcls);
nl.add_device_class (m3cls);
nl.add_device_class (m4cls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
db::Net *n1, *n2, *n3;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
db::Device *ddev1 = new db::Device (dcls);
ddev1->set_parameter_value (db::DeviceClassDiode::param_id_A, 1.7);
db::Device *ddev2 = new db::Device (dcls);
ddev2->set_parameter_value (db::DeviceClassDiode::param_id_A, 0.42);
circuit1->add_device (ddev1);
circuit1->add_device (ddev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("A"), n1);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("C"), n3);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("A"), n3);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("C"), n2);
// verify against the input
std::string path = tmp_file ("tmp_nwriter4.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter4_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(5_WriterMOS3Devices)
{
db::Netlist nl;
db::DeviceClass *rcls = new db::DeviceClassResistor ();
db::DeviceClass *ccls = new db::DeviceClassCapacitor ();
db::DeviceClass *lcls = new db::DeviceClassInductor ();
db::DeviceClass *dcls = new db::DeviceClassDiode ();
db::DeviceClass *m3cls = new db::DeviceClassMOS3Transistor ();
db::DeviceClass *m4cls = new db::DeviceClassMOS4Transistor ();
rcls->set_name ("RCLS");
lcls->set_name ("LCLS");
ccls->set_name ("CCLS");
dcls->set_name ("DCLS");
m3cls->set_name ("M3CLS");
m4cls->set_name ("M4CLS");
nl.add_device_class (rcls);
nl.add_device_class (lcls);
nl.add_device_class (ccls);
nl.add_device_class (dcls);
nl.add_device_class (m3cls);
nl.add_device_class (m4cls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
db::Net *n1, *n2, *n3, *n4;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
n4 = new db::Net ();
n4->set_name ("n4");
circuit1->add_net (n4);
db::Device *ddev1 = new db::Device (m3cls);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, 0.25);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, 0.18);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AS, 1.2);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AD, 0.75);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PS, 2.2);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PD, 1.75);
db::Device *ddev2 = new db::Device (m3cls);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, 1.4);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, 0.25);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AS, 1.3);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AD, 0.85);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PS, 2.3);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PD, 1.85);
circuit1->add_device (ddev1);
circuit1->add_device (ddev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
size_t pid3 = circuit1->add_pin ("p3").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
circuit1->connect_pin (pid3, n4);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("S"), n1);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("G"), n4);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("D"), n3);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("S"), n3);
ddev2->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("G"), n4);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("D"), n2);
// verify against the input
std::string path = tmp_file ("tmp_nwriter5.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter5_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(6_WriterMOS4Devices)
{
db::Netlist nl;
db::DeviceClass *rcls = new db::DeviceClassResistor ();
db::DeviceClass *ccls = new db::DeviceClassCapacitor ();
db::DeviceClass *lcls = new db::DeviceClassInductor ();
db::DeviceClass *dcls = new db::DeviceClassDiode ();
db::DeviceClass *m3cls = new db::DeviceClassMOS3Transistor ();
db::DeviceClass *m4cls = new db::DeviceClassMOS4Transistor ();
rcls->set_name ("RCLS");
lcls->set_name ("LCLS");
ccls->set_name ("CCLS");
dcls->set_name ("DCLS");
m3cls->set_name ("M3CLS");
m4cls->set_name ("M4CLS");
nl.add_device_class (rcls);
nl.add_device_class (lcls);
nl.add_device_class (ccls);
nl.add_device_class (dcls);
nl.add_device_class (m3cls);
nl.add_device_class (m4cls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
db::Net *n1, *n2, *n3, *n4, *n5;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
n4 = new db::Net ();
n4->set_name ("n4");
circuit1->add_net (n4);
n5 = new db::Net ();
n5->set_name ("n5");
circuit1->add_net (n5);
db::Device *ddev1 = new db::Device (m4cls);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, 0.25);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, 0.18);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AS, 1.2);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AD, 0.75);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PS, 2.2);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PD, 1.75);
db::Device *ddev2 = new db::Device (m4cls);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, 1.4);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, 0.25);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AS, 1.3);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AD, 0.85);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PS, 2.3);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PD, 1.85);
circuit1->add_device (ddev1);
circuit1->add_device (ddev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
size_t pid3 = circuit1->add_pin ("p3").id ();
size_t pid4 = circuit1->add_pin ("p4").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
circuit1->connect_pin (pid3, n4);
circuit1->connect_pin (pid4, n5);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("S"), n1);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("G"), n4);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("D"), n3);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("B"), n5);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("S"), n3);
ddev2->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("G"), n4);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("D"), n2);
ddev2->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("B"), n5);
// verify against the input
std::string path = tmp_file ("tmp_nwriter6.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter6_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(7_WriterAnyDevices)
{
db::Netlist nl;
db::DeviceClass *cls = new db::DeviceClass ();
cls->add_terminal_definition (db::DeviceTerminalDefinition ("A", "a"));
cls->add_terminal_definition (db::DeviceTerminalDefinition ("B", "b"));
cls->add_parameter_definition (db::DeviceParameterDefinition ("U", "u"));
cls->add_parameter_definition (db::DeviceParameterDefinition ("V", "v"));
cls->set_name ("XCLS");
nl.add_device_class (cls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
db::Net *n1, *n2, *n3;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
db::Device *ddev1 = new db::Device (cls);
ddev1->set_parameter_value (0, -17);
ddev1->set_parameter_value (1, 42);
db::Device *ddev2 = new db::Device (cls);
ddev2->set_parameter_value (0, 17);
ddev2->set_parameter_value (1, -42);
circuit1->add_device (ddev1);
circuit1->add_device (ddev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("A"), n1);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("B"), n3);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("A"), n3);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("B"), n2);
// verify against the input
std::string path = tmp_file ("tmp_nwriter7.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter7_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(8_WriterSubcircuits)
{
db::Netlist nl;
db::DeviceClass *rcls = new db::DeviceClassResistor ();
db::DeviceClass *ccls = new db::DeviceClassCapacitor ();
db::DeviceClass *lcls = new db::DeviceClassInductor ();
db::DeviceClass *dcls = new db::DeviceClassDiode ();
db::DeviceClass *m3cls = new db::DeviceClassMOS3Transistor ();
db::DeviceClass *m4cls = new db::DeviceClassMOS4Transistor ();
rcls->set_name ("RCLS");
lcls->set_name ("LCLS");
ccls->set_name ("CCLS");
dcls->set_name ("DCLS");
m3cls->set_name ("M3CLS");
m4cls->set_name ("M4CLS");
nl.add_device_class (rcls);
nl.add_device_class (lcls);
nl.add_device_class (ccls);
nl.add_device_class (dcls);
nl.add_device_class (m3cls);
nl.add_device_class (m4cls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
{
db::Net *n1, *n2, *n3, *n4, *n5;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
n4 = new db::Net ();
n4->set_name ("n4");
circuit1->add_net (n4);
n5 = new db::Net ();
n5->set_name ("n5");
circuit1->add_net (n5);
db::Device *ddev1 = new db::Device (m4cls);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, 0.25);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, 0.18);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AS, 1.2);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AD, 0.75);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PS, 2.2);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PD, 1.75);
db::Device *ddev2 = new db::Device (m4cls);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, 1.4);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, 0.25);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AS, 1.3);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AD, 0.85);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PS, 2.3);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PD, 1.85);
circuit1->add_device (ddev1);
circuit1->add_device (ddev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
size_t pid3 = circuit1->add_pin ("p3").id ();
size_t pid4 = circuit1->add_pin ("p4").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
circuit1->connect_pin (pid3, n4);
circuit1->connect_pin (pid4, n5);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("S"), n1);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("G"), n4);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("D"), n3);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("B"), n5);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("S"), n3);
ddev2->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("G"), n4);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("D"), n2);
ddev2->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("B"), n5);
}
db::Circuit *circuit2 = new db::Circuit ();
circuit2->set_name ("C2");
nl.add_circuit (circuit2);
{
db::Net *n1, *n2, *n3, *n4, *n5;
n1 = new db::Net ();
n1->set_name ("n1");
circuit2->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit2->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit2->add_net (n3);
n4 = new db::Net ();
n4->set_name ("n4");
circuit2->add_net (n4);
n5 = new db::Net ();
n5->set_name ("n5");
circuit2->add_net (n5);
db::SubCircuit *sc1 = new db::SubCircuit (circuit1, "SC1");
circuit2->add_subcircuit (sc1);
sc1->connect_pin (0, n1);
sc1->connect_pin (1, n3);
sc1->connect_pin (2, n4);
sc1->connect_pin (3, n3);
db::SubCircuit *sc2 = new db::SubCircuit (circuit1, "SC2");
circuit2->add_subcircuit (sc2);
sc2->connect_pin (0, n3);
sc2->connect_pin (1, n2);
sc2->connect_pin (2, n4);
sc2->connect_pin (3, n3);
size_t pid1 = circuit2->add_pin ("p1").id ();
size_t pid2 = circuit2->add_pin ("p2").id ();
size_t pid3 = circuit2->add_pin ("p3").id ();
circuit2->connect_pin (pid1, n1);
circuit2->connect_pin (pid2, n2);
circuit2->connect_pin (pid3, n4);
}
// verify against the input
std::string path = tmp_file ("tmp_nwriter8.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter8_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(9_WriterNetNamesInsteadOfNumbers)
{
db::Netlist nl;
db::DeviceClass *cls = new db::DeviceClass ();
cls->add_terminal_definition (db::DeviceTerminalDefinition ("A", "a"));
cls->add_terminal_definition (db::DeviceTerminalDefinition ("B", "b"));
cls->add_parameter_definition (db::DeviceParameterDefinition ("U", "u"));
cls->add_parameter_definition (db::DeviceParameterDefinition ("V", "v"));
cls->set_name ("XCLS");
nl.add_device_class (cls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
{
db::Net *n1, *n2, *n3;
n1 = new db::Net ();
n1->set_name ("N1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("N 2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
db::Device *ddev1 = new db::Device (cls);
ddev1->set_parameter_value (0, -17);
ddev1->set_parameter_value (1, 42);
db::Device *ddev2 = new db::Device (cls);
ddev2->set_parameter_value (0, 17);
ddev2->set_parameter_value (1, -42);
circuit1->add_device (ddev1);
circuit1->add_device (ddev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("A"), n1);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("B"), n3);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("A"), n3);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("B"), n2);
}
db::Circuit *circuit2 = new db::Circuit ();
circuit2->set_name ("C2");
nl.add_circuit (circuit2);
{
db::Net *n1, *n2;
n1 = new db::Net ();
n1->set_name ("n1");
circuit2->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit2->add_net (n2);
db::SubCircuit *sc1 = new db::SubCircuit (circuit1, "SC1");
circuit2->add_subcircuit (sc1);
sc1->connect_pin (0, n1);
sc1->connect_pin (1, n2);
size_t pid1 = circuit2->add_pin ("p1").id ();
size_t pid2 = circuit2->add_pin ("p2").id ();
circuit2->connect_pin (pid1, n1);
circuit2->connect_pin (pid2, n2);
}
// verify against the input
std::string path = tmp_file ("tmp_nwriter9.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.set_use_net_names (true);
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter9_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(10_WriterLongLines)
{
db::Netlist nl;
db::DeviceClass *rcls = new db::DeviceClassResistor ();
rcls->set_name ("RCLS");
nl.add_device_class (rcls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1withaverylongextensionthatgoesbeyondmultiplelinesunlessipasteeverythingtogetherwhichmakesithardtoreadbutexactlythatisthereasonwhyiwriteitthisway");
nl.add_circuit (circuit1);
db::Net *n0 = new db::Net ();
n0->set_name ("n0");
circuit1->add_net (n0);
size_t pid0 = circuit1->add_pin ("p0").id ();
circuit1->connect_pin (pid0, n0);
for (int i = 0; i < 100; ++i) {
db::Net *n = new db::Net ();
n->set_name ("n" + tl::to_string (i + 1));
circuit1->add_net (n);
size_t pid = circuit1->add_pin ("p" + tl::to_string (i + 1)).id ();
circuit1->connect_pin (pid, n);
db::Device *ddev = new db::Device (rcls);
circuit1->add_device (ddev);
ddev->connect_terminal (db::DeviceClassResistor::terminal_id_A, n0);
ddev->connect_terminal (db::DeviceClassResistor::terminal_id_B, n);
}
// verify against the input
std::string path = tmp_file ("tmp_nwriter10.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter10_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(11_WriterNonConnectedPins)
{
db::Netlist nl;
db::DeviceClass *rcls = new db::DeviceClassResistor ();
db::DeviceClass *ccls = new db::DeviceClassCapacitor ();
db::DeviceClass *lcls = new db::DeviceClassInductor ();
db::DeviceClass *dcls = new db::DeviceClassDiode ();
db::DeviceClass *m3cls = new db::DeviceClassMOS3Transistor ();
db::DeviceClass *m4cls = new db::DeviceClassMOS4Transistor ();
rcls->set_name ("RCLS");
lcls->set_name ("LCLS");
ccls->set_name ("CCLS");
dcls->set_name ("DCLS");
m3cls->set_name ("M3CLS");
m4cls->set_name ("M4CLS");
nl.add_device_class (rcls);
nl.add_device_class (lcls);
nl.add_device_class (ccls);
nl.add_device_class (dcls);
nl.add_device_class (m3cls);
nl.add_device_class (m4cls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
{
db::Net *n1, *n2, *n3, *n4, *n5;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
n4 = new db::Net ();
n4->set_name ("n4");
circuit1->add_net (n4);
n5 = new db::Net ();
n5->set_name ("n5");
circuit1->add_net (n5);
db::Device *ddev1 = new db::Device (m4cls);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, 0.25);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, 0.18);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AS, 1.2);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AD, 0.75);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PS, 2.2);
ddev1->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PD, 1.75);
db::Device *ddev2 = new db::Device (m4cls);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, 1.4);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, 0.25);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AS, 1.3);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_AD, 0.85);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PS, 2.3);
ddev2->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_PD, 1.85);
circuit1->add_device (ddev1);
circuit1->add_device (ddev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
size_t pid3 = circuit1->add_pin ("p3").id ();
size_t pid4 = circuit1->add_pin ("p4").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
circuit1->connect_pin (pid3, n4);
circuit1->connect_pin (pid4, n5);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("S"), n1);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("G"), n4);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("D"), n3);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("B"), n5);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("S"), n3);
ddev2->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("G"), n4);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("D"), n2);
ddev2->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("B"), n5);
}
db::Circuit *circuit2 = new db::Circuit ();
circuit2->set_name ("C2");
nl.add_circuit (circuit2);
{
db::Net *n1, *n2, *n3, *n4, *n5;
n1 = new db::Net ();
// this gives a clash with the auto-generated node names with non-connected subcircuit pins
// and terminals - we test proper generation of such names this way
n1->set_name ("nc_10");
circuit2->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit2->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit2->add_net (n3);
n4 = new db::Net ();
n4->set_name ("n4");
circuit2->add_net (n4);
n5 = new db::Net ();
n5->set_name ("n5");
circuit2->add_net (n5);
db::SubCircuit *sc1 = new db::SubCircuit (circuit1, "SC1");
circuit2->add_subcircuit (sc1);
sc1->connect_pin (0, n1);
sc1->connect_pin (1, n3);
// pin 2 unconnected
sc1->connect_pin (3, n3);
db::SubCircuit *sc2 = new db::SubCircuit (circuit1, "SC2");
circuit2->add_subcircuit (sc2);
sc2->connect_pin (0, n3);
// pin 1 unconnected
sc2->connect_pin (2, n4);
sc2->connect_pin (3, n3);
size_t pid1 = circuit2->add_pin ("p1").id ();
size_t pid2 = circuit2->add_pin ("p2").id ();
size_t pid3 = circuit2->add_pin ("p3").id ();
circuit2->connect_pin (pid1, n1);
circuit2->connect_pin (pid2, n2);
circuit2->connect_pin (pid3, n4);
}
// verify against the input
std::string path = tmp_file ("tmp_nwriter11.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter11_au.txt");
compare_netlists (_this, path, au_path);
path = tmp_file ("tmp_nwriter11b.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.set_use_net_names (true);
writer.write (stream, nl, "written by unit test");
}
au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter11b_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(12_UniqueNetNames)
{
db::LayoutToNetlist l2n;
std::string l2n_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "same_net_names.l2n");
l2n.load (l2n_path);
// verify against the input
std::string path = tmp_file ("tmp_nwriter12.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, *l2n.netlist (), "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter12_au.txt");
compare_netlists (_this, path, au_path);
path = tmp_file ("tmp_nwriter12b.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.set_use_net_names (true);
writer.write (stream, *l2n.netlist (), "written by unit test");
}
au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter12b_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(13_WriterBJT3Devices)
{
db::Netlist nl;
db::DeviceClass *rcls = new db::DeviceClassResistor ();
db::DeviceClass *ccls = new db::DeviceClassCapacitor ();
db::DeviceClass *lcls = new db::DeviceClassInductor ();
db::DeviceClass *dcls = new db::DeviceClassDiode ();
db::DeviceClass *b3cls = new db::DeviceClassBJT3Transistor ();
db::DeviceClass *b4cls = new db::DeviceClassBJT4Transistor ();
rcls->set_name ("RCLS");
lcls->set_name ("LCLS");
ccls->set_name ("CCLS");
dcls->set_name ("DCLS");
b3cls->set_name ("B3CLS");
b4cls->set_name ("B4CLS");
nl.add_device_class (rcls);
nl.add_device_class (lcls);
nl.add_device_class (ccls);
nl.add_device_class (dcls);
nl.add_device_class (b3cls);
nl.add_device_class (b4cls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
db::Net *n1, *n2, *n3, *n4;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
n4 = new db::Net ();
n4->set_name ("n4");
circuit1->add_net (n4);
db::Device *ddev1 = new db::Device (b3cls);
ddev1->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_AE, 0.25);
ddev1->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_PE, 0.18);
ddev1->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_AB, 1.2);
ddev1->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_PB, 0.75);
ddev1->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_AC, 1.0);
ddev1->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_PC, 0.6);
db::Device *ddev2 = new db::Device (b3cls);
ddev2->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_AE, 1.2);
ddev2->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_PE, 2.5);
ddev2->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_AB, 1.4);
ddev2->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_PB, 2.8);
ddev2->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_AC, 1.5);
ddev2->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_PC, 3.0);
circuit1->add_device (ddev1);
circuit1->add_device (ddev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
size_t pid3 = circuit1->add_pin ("p3").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
circuit1->connect_pin (pid3, n4);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("E"), n1);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("B"), n4);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("C"), n3);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("E"), n3);
ddev2->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("B"), n4);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("C"), n2);
// verify against the input
std::string path = tmp_file ("tmp_nwriter13.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter13_au.txt");
compare_netlists (_this, path, au_path);
}
TEST(14_WriterBJT4Devices)
{
db::Netlist nl;
db::DeviceClass *rcls = new db::DeviceClassResistor ();
db::DeviceClass *ccls = new db::DeviceClassCapacitor ();
db::DeviceClass *lcls = new db::DeviceClassInductor ();
db::DeviceClass *dcls = new db::DeviceClassDiode ();
db::DeviceClass *b3cls = new db::DeviceClassBJT3Transistor ();
db::DeviceClass *b4cls = new db::DeviceClassBJT4Transistor ();
rcls->set_name ("RCLS");
lcls->set_name ("LCLS");
ccls->set_name ("CCLS");
dcls->set_name ("DCLS");
b3cls->set_name ("B3CLS");
b4cls->set_name ("B4CLS");
nl.add_device_class (rcls);
nl.add_device_class (lcls);
nl.add_device_class (ccls);
nl.add_device_class (dcls);
nl.add_device_class (b3cls);
nl.add_device_class (b4cls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
db::Net *n1, *n2, *n3, *n4, *n5;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
n4 = new db::Net ();
n4->set_name ("n4");
circuit1->add_net (n4);
n5 = new db::Net ();
n5->set_name ("n5");
circuit1->add_net (n5);
db::Device *ddev1 = new db::Device (b4cls);
ddev1->set_parameter_value (db::DeviceClassBJT4Transistor::param_id_AE, 0.25);
ddev1->set_parameter_value (db::DeviceClassBJT4Transistor::param_id_PE, 0.18);
ddev1->set_parameter_value (db::DeviceClassBJT4Transistor::param_id_AB, 1.2);
ddev1->set_parameter_value (db::DeviceClassBJT4Transistor::param_id_PB, 0.75);
ddev1->set_parameter_value (db::DeviceClassBJT4Transistor::param_id_AC, 1.0);
ddev1->set_parameter_value (db::DeviceClassBJT4Transistor::param_id_PC, 0.6);
db::Device *ddev2 = new db::Device (b4cls);
ddev2->set_parameter_value (db::DeviceClassBJT4Transistor::param_id_AE, 1.2);
ddev2->set_parameter_value (db::DeviceClassBJT4Transistor::param_id_PE, 2.5);
ddev2->set_parameter_value (db::DeviceClassBJT4Transistor::param_id_AB, 1.4);
ddev2->set_parameter_value (db::DeviceClassBJT4Transistor::param_id_PB, 2.8);
ddev2->set_parameter_value (db::DeviceClassBJT4Transistor::param_id_AC, 1.5);
ddev2->set_parameter_value (db::DeviceClassBJT4Transistor::param_id_PC, 3.0);
circuit1->add_device (ddev1);
circuit1->add_device (ddev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
size_t pid3 = circuit1->add_pin ("p3").id ();
size_t pid4 = circuit1->add_pin ("p4").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
circuit1->connect_pin (pid3, n4);
circuit1->connect_pin (pid4, n5);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("E"), n1);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("B"), n4);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("C"), n3);
ddev1->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("S"), n5);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("E"), n3);
ddev2->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("B"), n4);
ddev2->connect_terminal (ddev2->device_class ()->terminal_id_for_name ("C"), n2);
ddev2->connect_terminal (ddev1->device_class ()->terminal_id_for_name ("S"), n5);
// verify against the input
std::string path = tmp_file ("tmp_nwriter14.txt");
{
tl::OutputStream stream (path);
db::NetlistSpiceWriter writer;
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter14_au.txt");
compare_netlists (_this, path, au_path);
}
namespace {
class MyDelegate
: public db::NetlistSpiceWriterDelegate
{
public:
MyDelegate ()
: db::NetlistSpiceWriterDelegate ()
{ }
void write_header () const
{
emit_line ("*** My special header");
}
void write_device_intro (const db::DeviceClass &cls) const
{
emit_line ("*** My intro for class " + cls.name ());
}
void write_device (const db::Device &dev) const
{
emit_line ("*** Before device " + dev.expanded_name ());
db::NetlistSpiceWriterDelegate::write_device (dev);
emit_line ("*** After device " + dev.expanded_name ());
}
};
}
TEST(20_Delegate)
{
db::Netlist nl;
db::DeviceClass *rcls = new db::DeviceClassResistor ();
db::DeviceClass *ccls = new db::DeviceClassCapacitor ();
db::DeviceClass *lcls = new db::DeviceClassInductor ();
db::DeviceClass *dcls = new db::DeviceClassDiode ();
db::DeviceClass *m3cls = new db::DeviceClassMOS3Transistor ();
db::DeviceClass *m4cls = new db::DeviceClassMOS4Transistor ();
rcls->set_name ("RCLS");
lcls->set_name ("LCLS");
ccls->set_name ("CCLS");
dcls->set_name ("DCLS");
m3cls->set_name ("M3CLS");
m4cls->set_name ("M4CLS");
nl.add_device_class (rcls);
nl.add_device_class (lcls);
nl.add_device_class (ccls);
nl.add_device_class (dcls);
nl.add_device_class (m3cls);
nl.add_device_class (m4cls);
db::Circuit *circuit1 = new db::Circuit ();
circuit1->set_name ("C1");
nl.add_circuit (circuit1);
db::Net *n1, *n2, *n3;
n1 = new db::Net ();
n1->set_name ("n1");
circuit1->add_net (n1);
n2 = new db::Net ();
n2->set_name ("n2");
circuit1->add_net (n2);
n3 = new db::Net ();
n3->set_name ("n3");
circuit1->add_net (n3);
db::Device *rdev1 = new db::Device (rcls);
rdev1->set_parameter_value (db::DeviceClassResistor::param_id_R, 1.7);
db::Device *rdev2 = new db::Device (rcls);
rdev2->set_parameter_value (db::DeviceClassResistor::param_id_R, 42e-6);
circuit1->add_device (rdev1);
circuit1->add_device (rdev2);
size_t pid1 = circuit1->add_pin ("p1").id ();
size_t pid2 = circuit1->add_pin ("p2").id ();
circuit1->connect_pin (pid1, n1);
circuit1->connect_pin (pid2, n2);
rdev1->connect_terminal (rdev1->device_class ()->terminal_id_for_name ("A"), n1);
rdev1->connect_terminal (rdev1->device_class ()->terminal_id_for_name ("B"), n3);
rdev2->connect_terminal (rdev2->device_class ()->terminal_id_for_name ("A"), n3);
rdev2->connect_terminal (rdev2->device_class ()->terminal_id_for_name ("B"), n2);
// verify against the input
std::string path = tmp_file ("tmp_nwriter20.txt");
{
tl::OutputStream stream (path);
MyDelegate delegate;
db::NetlistSpiceWriter writer (&delegate);
writer.write (stream, nl, "written by unit test");
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nwriter20_au.txt");
compare_netlists (_this, path, au_path);
}