mirror of https://github.com/KLayout/klayout.git
Unique net names for Spice netlist writer
This commit is contained in:
parent
c684633dd6
commit
985cffc099
|
|
@ -25,8 +25,10 @@
|
||||||
#include "dbNetlistDeviceClasses.h"
|
#include "dbNetlistDeviceClasses.h"
|
||||||
|
|
||||||
#include "tlStream.h"
|
#include "tlStream.h"
|
||||||
|
#include "tlUniqueName.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace db
|
namespace db
|
||||||
{
|
{
|
||||||
|
|
@ -258,7 +260,10 @@ std::string NetlistSpiceWriter::net_to_string (const db::Net *net) const
|
||||||
// It does not like: , ;
|
// It does not like: , ;
|
||||||
// We translate , to | for the net separator
|
// We translate , to | for the net separator
|
||||||
|
|
||||||
std::string n = net->expanded_name ();
|
std::map<const db::Net *, std::string>::const_iterator ni = m_net_to_spice_name.find (net);
|
||||||
|
tl_assert (ni != m_net_to_spice_name.end ());
|
||||||
|
|
||||||
|
const std::string &n = ni->second;
|
||||||
std::string nn;
|
std::string nn;
|
||||||
nn.reserve (n.size () + 1);
|
nn.reserve (n.size () + 1);
|
||||||
if (!isalnum (*n.c_str ())) {
|
if (!isalnum (*n.c_str ())) {
|
||||||
|
|
@ -369,6 +374,8 @@ void NetlistSpiceWriter::do_write (const std::string &description)
|
||||||
|
|
||||||
// assign internal node numbers to the nets
|
// assign internal node numbers to the nets
|
||||||
m_net_to_spice_id.clear ();
|
m_net_to_spice_id.clear ();
|
||||||
|
m_net_to_spice_name.clear ();
|
||||||
|
|
||||||
m_next_net_id = 0;
|
m_next_net_id = 0;
|
||||||
if (! m_use_net_names) {
|
if (! m_use_net_names) {
|
||||||
|
|
||||||
|
|
@ -378,14 +385,22 @@ void NetlistSpiceWriter::do_write (const std::string &description)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
// create unique names for those nets with a name
|
||||||
|
std::set<std::string> names;
|
||||||
|
for (db::Circuit::const_net_iterator n = circuit.begin_nets (); n != circuit.end_nets (); ++n) {
|
||||||
|
std::string nn = tl::unique_name (n->expanded_name (), names);
|
||||||
|
names.insert (nn);
|
||||||
|
m_net_to_spice_name.insert (std::make_pair (n.operator-> (), nn));
|
||||||
|
}
|
||||||
|
|
||||||
// determine the next net id for non-connected nets such that there is no clash with
|
// determine the next net id for non-connected nets such that there is no clash with
|
||||||
// existing names
|
// existing names
|
||||||
size_t prefix_len = strlen (not_connect_prefix);
|
size_t prefix_len = strlen (not_connect_prefix);
|
||||||
|
|
||||||
for (db::Circuit::const_net_iterator n = circuit.begin_nets (); n != circuit.end_nets (); ++n) {
|
for (std::set<std::string>::const_iterator n = names.begin (); n != names.end (); ++n) {
|
||||||
if (n->name ().find (not_connect_prefix) == 0 && n->name ().size () > prefix_len) {
|
if (n->find (not_connect_prefix) == 0 && n->size () > prefix_len) {
|
||||||
size_t num = 0;
|
size_t num = 0;
|
||||||
tl::from_string (n->name ().c_str () + prefix_len, num);
|
tl::from_string (n->c_str () + prefix_len, num);
|
||||||
m_next_net_id = std::max (m_next_net_id, num);
|
m_next_net_id = std::max (m_next_net_id, num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ private:
|
||||||
tl::OutputStream *mp_stream;
|
tl::OutputStream *mp_stream;
|
||||||
tl::weak_ptr<NetlistSpiceWriterDelegate> mp_delegate;
|
tl::weak_ptr<NetlistSpiceWriterDelegate> mp_delegate;
|
||||||
std::map<const db::Net *, size_t> m_net_to_spice_id;
|
std::map<const db::Net *, size_t> m_net_to_spice_id;
|
||||||
|
std::map<const db::Net *, std::string> m_net_to_spice_name;
|
||||||
mutable size_t m_next_net_id;
|
mutable size_t m_next_net_id;
|
||||||
bool m_use_net_names;
|
bool m_use_net_names;
|
||||||
bool m_with_comments;
|
bool m_with_comments;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "dbNetlistSpiceWriter.h"
|
#include "dbNetlistSpiceWriter.h"
|
||||||
#include "dbNetlist.h"
|
#include "dbNetlist.h"
|
||||||
#include "dbNetlistDeviceClasses.h"
|
#include "dbNetlistDeviceClasses.h"
|
||||||
|
#include "dbLayoutToNetlist.h"
|
||||||
|
|
||||||
#include "tlUnitTest.h"
|
#include "tlUnitTest.h"
|
||||||
#include "tlStream.h"
|
#include "tlStream.h"
|
||||||
|
|
@ -1024,7 +1025,37 @@ TEST(11_WriterNonConnectedPins)
|
||||||
compare_netlists (_this, path, au_path);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,8 @@ SOURCES = \
|
||||||
tlLongInt.cc \
|
tlLongInt.cc \
|
||||||
tlUniqueId.cc \
|
tlUniqueId.cc \
|
||||||
tlList.cc \
|
tlList.cc \
|
||||||
tlEquivalenceClusters.cc
|
tlEquivalenceClusters.cc \
|
||||||
|
tlUniqueName.cc
|
||||||
|
|
||||||
HEADERS = \
|
HEADERS = \
|
||||||
tlAlgorithm.h \
|
tlAlgorithm.h \
|
||||||
|
|
@ -98,7 +99,8 @@ HEADERS = \
|
||||||
tlLongInt.h \
|
tlLongInt.h \
|
||||||
tlUniqueId.h \
|
tlUniqueId.h \
|
||||||
tlList.h \
|
tlList.h \
|
||||||
tlEquivalenceClusters.h
|
tlEquivalenceClusters.h \
|
||||||
|
tlUniqueName.h
|
||||||
|
|
||||||
equals(HAVE_CURL, "1") {
|
equals(HAVE_CURL, "1") {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
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 "tlUniqueName.h"
|
||||||
|
|
||||||
|
namespace tl
|
||||||
|
{
|
||||||
|
|
||||||
|
// .. nothing yet ..
|
||||||
|
|
||||||
|
} // namespace tl
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HDR_tlUniqueName
|
||||||
|
#define HDR_tlUniqueName
|
||||||
|
|
||||||
|
#include "tlCommon.h"
|
||||||
|
#include "tlString.h"
|
||||||
|
|
||||||
|
namespace tl
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief An object delivering a unique name given a set of existing names
|
||||||
|
*
|
||||||
|
* If no object with the given name exists, the original name is returned.
|
||||||
|
* Otherwise, the unique name is built from the original name plus
|
||||||
|
* the separator and an integer disambiguator.
|
||||||
|
*/
|
||||||
|
template <class Set>
|
||||||
|
TL_PUBLIC std::string unique_name (const std::string &org_name, const Set &present_names, const std::string &sep = "$")
|
||||||
|
{
|
||||||
|
if (present_names.find (org_name) == present_names.end ()) {
|
||||||
|
return org_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string b;
|
||||||
|
|
||||||
|
unsigned int j = 0;
|
||||||
|
for (unsigned int m = (unsigned int) 1 << (sizeof (unsigned int) * 8 - 2); m > 0; m >>= 1) {
|
||||||
|
j += m;
|
||||||
|
b = org_name + sep + tl::to_string (j);
|
||||||
|
if (present_names.find (b) == present_names.end ()) {
|
||||||
|
j -= m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return org_name + sep + tl::to_string (j + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tl
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
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 "tlUniqueName.h"
|
||||||
|
#include "tlUnitTest.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// basic tests
|
||||||
|
TEST(1)
|
||||||
|
{
|
||||||
|
std::set<std::string> names;
|
||||||
|
|
||||||
|
EXPECT_EQ (tl::unique_name ("A", names), "A");
|
||||||
|
names.insert ("A");
|
||||||
|
EXPECT_EQ (tl::unique_name ("A", names), "A$1");
|
||||||
|
EXPECT_EQ (tl::unique_name ("A", names, "_"), "A_1");
|
||||||
|
names.insert ("A$1");
|
||||||
|
EXPECT_EQ (tl::unique_name ("A", names), "A$2");
|
||||||
|
names.insert ("A$2");
|
||||||
|
names.insert ("A$5");
|
||||||
|
EXPECT_EQ (tl::unique_name ("A", names), "A$3");
|
||||||
|
names.insert ("A$3");
|
||||||
|
EXPECT_EQ (tl::unique_name ("A", names), "A$4");
|
||||||
|
names.insert ("A$4");
|
||||||
|
EXPECT_EQ (tl::unique_name ("A", names), "A$6");
|
||||||
|
names.insert ("A$6");
|
||||||
|
EXPECT_EQ (tl::unique_name ("B", names), "B");
|
||||||
|
names.insert ("B");
|
||||||
|
EXPECT_EQ (tl::unique_name ("", names), "");
|
||||||
|
names.insert ("");
|
||||||
|
EXPECT_EQ (tl::unique_name ("", names), "$1");
|
||||||
|
}
|
||||||
|
|
@ -37,7 +37,8 @@ SOURCES = \
|
||||||
tlLongInt.cc \
|
tlLongInt.cc \
|
||||||
tlUniqueIdTests.cc \
|
tlUniqueIdTests.cc \
|
||||||
tlListTests.cc \
|
tlListTests.cc \
|
||||||
tlEquivalenceClustersTests.cc
|
tlEquivalenceClustersTests.cc \
|
||||||
|
tlUniqueNameTests.cc
|
||||||
|
|
||||||
!equals(HAVE_QT, "0") {
|
!equals(HAVE_QT, "0") {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
* written by unit test
|
||||||
|
|
||||||
|
* cell SUBCKT
|
||||||
|
* pin
|
||||||
|
* pin A
|
||||||
|
* pin V42
|
||||||
|
* pin Z
|
||||||
|
* pin gnd
|
||||||
|
* pin gnd
|
||||||
|
.SUBCKT SUBCKT 1 2 4 5 6 7
|
||||||
|
* net 2 A
|
||||||
|
* net 4 V42
|
||||||
|
* net 5 Z
|
||||||
|
* net 6 gnd
|
||||||
|
* net 7 gnd
|
||||||
|
* device instance $1 r0 *1 0,0 HVPMOS
|
||||||
|
XD_$1 4 3 5 1 HVPMOS PARAMS: L=0.2 W=1 AS=0.18 AD=0.18 PS=2.16 PD=2.16
|
||||||
|
* device instance $2 r0 *1 0,0 HVPMOS
|
||||||
|
XD_$2 4 2 3 1 HVPMOS PARAMS: L=0.2 W=1 AS=0.18 AD=0.18 PS=2.16 PD=2.16
|
||||||
|
* device instance $3 r0 *1 0,0 HVNMOS
|
||||||
|
XD_$3 6 3 6 7 HVNMOS PARAMS: L=1.13 W=2.12 PS=6 PD=6 AS=0 AD=0
|
||||||
|
* device instance $4 r0 *1 0,0 HVNMOS
|
||||||
|
XD_$4 6 3 5 7 HVNMOS PARAMS: L=0.4 W=0.4 PS=1.16 PD=1.16 AS=0.19 AD=0.19
|
||||||
|
* device instance $5 r0 *1 0,0 HVNMOS
|
||||||
|
XD_$5 6 2 3 7 HVNMOS PARAMS: L=0.4 W=0.4 PS=1.76 PD=1.76 AS=0.19 AD=0.19
|
||||||
|
.ENDS SUBCKT
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
* written by unit test
|
||||||
|
|
||||||
|
* cell SUBCKT
|
||||||
|
* pin
|
||||||
|
* pin A
|
||||||
|
* pin V42
|
||||||
|
* pin Z
|
||||||
|
* pin gnd
|
||||||
|
* pin gnd
|
||||||
|
.SUBCKT SUBCKT \$1 A V42 Z gnd gnd$1
|
||||||
|
* device instance $1 r0 *1 0,0 HVPMOS
|
||||||
|
XD_$1 V42 \$3 Z \$1 HVPMOS PARAMS: L=0.2 W=1 AS=0.18 AD=0.18 PS=2.16 PD=2.16
|
||||||
|
* device instance $2 r0 *1 0,0 HVPMOS
|
||||||
|
XD_$2 V42 A \$3 \$1 HVPMOS PARAMS: L=0.2 W=1 AS=0.18 AD=0.18 PS=2.16 PD=2.16
|
||||||
|
* device instance $3 r0 *1 0,0 HVNMOS
|
||||||
|
XD_$3 gnd \$3 gnd gnd$1 HVNMOS PARAMS: L=1.13 W=2.12 PS=6 PD=6 AS=0 AD=0
|
||||||
|
* device instance $4 r0 *1 0,0 HVNMOS
|
||||||
|
XD_$4 gnd \$3 Z gnd$1 HVNMOS PARAMS: L=0.4 W=0.4 PS=1.16 PD=1.16 AS=0.19 AD=0.19
|
||||||
|
* device instance $5 r0 *1 0,0 HVNMOS
|
||||||
|
XD_$5 gnd A \$3 gnd$1 HVNMOS PARAMS: L=0.4 W=0.4 PS=1.76 PD=1.76 AS=0.19 AD=0.19
|
||||||
|
.ENDS SUBCKT
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
#%l2n-klayout
|
||||||
|
W(CIRCUIT)
|
||||||
|
U(0.001)
|
||||||
|
D(D$HVPMOS HVPMOS
|
||||||
|
T(S
|
||||||
|
)
|
||||||
|
T(G
|
||||||
|
)
|
||||||
|
T(D
|
||||||
|
)
|
||||||
|
T(B
|
||||||
|
)
|
||||||
|
)
|
||||||
|
D(D$HVNMOS HVNMOS
|
||||||
|
T(S
|
||||||
|
)
|
||||||
|
T(G
|
||||||
|
)
|
||||||
|
T(D
|
||||||
|
)
|
||||||
|
T(B
|
||||||
|
)
|
||||||
|
)
|
||||||
|
X(SUBCKT
|
||||||
|
N(1
|
||||||
|
)
|
||||||
|
N(2 I(A)
|
||||||
|
)
|
||||||
|
N(3
|
||||||
|
)
|
||||||
|
N(4 I(V42)
|
||||||
|
)
|
||||||
|
N(5 I(Z)
|
||||||
|
)
|
||||||
|
N(6 I(gnd)
|
||||||
|
)
|
||||||
|
N(7 I(gnd)
|
||||||
|
)
|
||||||
|
P(1)
|
||||||
|
P(2 I(A))
|
||||||
|
P(4 I(V42))
|
||||||
|
P(5 I(Z))
|
||||||
|
P(6 I(gnd))
|
||||||
|
P(7 I(gnd))
|
||||||
|
D(1 D$HVPMOS
|
||||||
|
E(L 0.2)
|
||||||
|
E(W 1)
|
||||||
|
E(AS 0.18)
|
||||||
|
E(AD 0.18)
|
||||||
|
E(PS 2.16)
|
||||||
|
E(PD 2.16)
|
||||||
|
T(S 4)
|
||||||
|
T(G 3)
|
||||||
|
T(D 5)
|
||||||
|
T(B 1)
|
||||||
|
)
|
||||||
|
D(2 D$HVPMOS
|
||||||
|
E(L 0.2)
|
||||||
|
E(W 1)
|
||||||
|
E(AS 0.18)
|
||||||
|
E(AD 0.18)
|
||||||
|
E(PS 2.16)
|
||||||
|
E(PD 2.16)
|
||||||
|
T(S 4)
|
||||||
|
T(G 2)
|
||||||
|
T(D 3)
|
||||||
|
T(B 1)
|
||||||
|
)
|
||||||
|
D(3 D$HVNMOS
|
||||||
|
E(L 1.13)
|
||||||
|
E(W 2.12)
|
||||||
|
E(PS 6)
|
||||||
|
E(PD 6)
|
||||||
|
T(S 6)
|
||||||
|
T(G 3)
|
||||||
|
T(D 6)
|
||||||
|
T(B 7)
|
||||||
|
)
|
||||||
|
D(4 D$HVNMOS
|
||||||
|
E(L 0.4)
|
||||||
|
E(W 0.4)
|
||||||
|
E(AS 0.19)
|
||||||
|
E(AD 0.19)
|
||||||
|
E(PS 1.16)
|
||||||
|
E(PD 1.16)
|
||||||
|
T(S 6)
|
||||||
|
T(G 3)
|
||||||
|
T(D 5)
|
||||||
|
T(B 7)
|
||||||
|
)
|
||||||
|
D(5 D$HVNMOS
|
||||||
|
E(L 0.4)
|
||||||
|
E(W 0.4)
|
||||||
|
E(AS 0.19)
|
||||||
|
E(AD 0.19)
|
||||||
|
E(PS 1.76)
|
||||||
|
E(PD 1.76)
|
||||||
|
T(S 6)
|
||||||
|
T(G 2)
|
||||||
|
T(D 3)
|
||||||
|
T(B 7)
|
||||||
|
)
|
||||||
|
)
|
||||||
Loading…
Reference in New Issue