mirror of https://github.com/KLayout/klayout.git
Merge branch 'master' of https://github.com/KLayout/klayout
This commit is contained in:
commit
bea3e29421
|
|
@ -256,6 +256,7 @@ void NetlistSpiceReader::read (tl::InputStream &stream, db::Netlist &netlist)
|
|||
mp_stream.reset (new tl::TextInputStream (stream));
|
||||
mp_netlist = &netlist;
|
||||
mp_circuit = 0;
|
||||
mp_anonymous_top_circuit = 0;
|
||||
mp_nets_by_name.reset (0);
|
||||
m_global_nets.clear ();
|
||||
m_circuits_read.clear ();
|
||||
|
|
@ -268,6 +269,8 @@ void NetlistSpiceReader::read (tl::InputStream &stream, db::Netlist &netlist)
|
|||
read_card ();
|
||||
}
|
||||
|
||||
build_global_nets ();
|
||||
|
||||
mp_delegate->finish (&netlist);
|
||||
finish ();
|
||||
|
||||
|
|
@ -287,6 +290,48 @@ void NetlistSpiceReader::read (tl::InputStream &stream, db::Netlist &netlist)
|
|||
}
|
||||
}
|
||||
|
||||
void NetlistSpiceReader::build_global_nets ()
|
||||
{
|
||||
for (std::vector<std::string>::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) {
|
||||
|
||||
for (db::Netlist::bottom_up_circuit_iterator c = mp_netlist->begin_bottom_up (); c != mp_netlist->end_bottom_up (); ++c) {
|
||||
|
||||
if (c.operator-> () == mp_anonymous_top_circuit) {
|
||||
// no pins for the anonymous top circuit
|
||||
continue;
|
||||
}
|
||||
|
||||
db::Net *net = c->net_by_name (*gn);
|
||||
if (! net || net->pin_count () > 0) {
|
||||
// only add a pin for a global net if there is a net with this name
|
||||
// don't add a pin if it already has one
|
||||
continue;
|
||||
}
|
||||
|
||||
const db::Pin &pin = c->add_pin (*gn);
|
||||
c->connect_pin (pin.id (), net);
|
||||
|
||||
for (db::Circuit::refs_iterator r = c->begin_refs (); r != c->end_refs (); ++r) {
|
||||
|
||||
db::SubCircuit &sc = *r;
|
||||
|
||||
db::Net *pnet = sc.circuit ()->net_by_name (*gn);
|
||||
if (! pnet) {
|
||||
pnet = new db::Net ();
|
||||
pnet->set_name (*gn);
|
||||
sc.circuit ()->add_net (pnet);
|
||||
}
|
||||
|
||||
sc.connect_pin (pin.id (), pnet);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NetlistSpiceReader::finish ()
|
||||
{
|
||||
while (! m_streams.empty ()) {
|
||||
|
|
@ -577,12 +622,9 @@ void NetlistSpiceReader::ensure_circuit ()
|
|||
mp_circuit = new db::Circuit ();
|
||||
// TODO: make top name configurable
|
||||
mp_circuit->set_name (".TOP");
|
||||
mp_anonymous_top_circuit = mp_circuit;
|
||||
mp_netlist->add_circuit (mp_circuit);
|
||||
|
||||
for (std::vector<std::string>::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) {
|
||||
make_net (*gn);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -828,13 +870,10 @@ void NetlistSpiceReader::read_subcircuit (const std::string &sc_name, const std:
|
|||
for (std::vector<db::Net *>::const_iterator i = nets.begin (); i != nets.end (); ++i) {
|
||||
cc->add_pin (std::string ());
|
||||
}
|
||||
for (std::vector<std::string>::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) {
|
||||
cc->add_pin (std::string ());
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (cc->pin_count () != nets.size () + m_global_nets.size ()) {
|
||||
if (cc->pin_count () != nets.size ()) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Pin count mismatch between circuit definition and circuit call: %d expected, got %d")), int (cc->pin_count ()), int (nets.size ())));
|
||||
}
|
||||
|
||||
|
|
@ -846,11 +885,6 @@ void NetlistSpiceReader::read_subcircuit (const std::string &sc_name, const std:
|
|||
for (std::vector<db::Net *>::const_iterator i = nets.begin (); i != nets.end (); ++i) {
|
||||
sc->connect_pin (i - nets.begin (), *i);
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) {
|
||||
db::Net *net = make_net (*gn);
|
||||
sc->connect_pin (gn - m_global_nets.begin () + nets.size (), net);
|
||||
}
|
||||
}
|
||||
|
||||
void NetlistSpiceReader::skip_circuit (tl::Extractor & /*ex*/)
|
||||
|
|
@ -892,13 +926,10 @@ void NetlistSpiceReader::read_circuit (tl::Extractor &ex, const std::string &nc)
|
|||
for (std::vector<std::string>::const_iterator i = nn.begin (); i != nn.end (); ++i) {
|
||||
cc->add_pin (std::string ());
|
||||
}
|
||||
for (std::vector<std::string>::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) {
|
||||
cc->add_pin (std::string ());
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (cc->pin_count () != nn.size () + m_global_nets.size ()) {
|
||||
if (cc->pin_count () != nn.size ()) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Pin count mismatch between implicit (through call) and explicit circuit definition: %d expected, got %d in circuit %s")), int (cc->pin_count ()), int (nn.size ()), nc));
|
||||
}
|
||||
|
||||
|
|
@ -925,14 +956,6 @@ void NetlistSpiceReader::read_circuit (tl::Extractor &ex, const std::string &nc)
|
|||
mp_circuit->connect_pin (pin_id, net);
|
||||
}
|
||||
|
||||
// produce pins for the global nets
|
||||
for (std::vector<std::string>::const_iterator gn = m_global_nets.begin (); gn != m_global_nets.end (); ++gn) {
|
||||
db::Net *net = make_net (*gn);
|
||||
size_t pin_id = gn - m_global_nets.begin () + nn.size ();
|
||||
mp_circuit->rename_pin (pin_id, net->name ());
|
||||
mp_circuit->connect_pin (pin_id, net);
|
||||
}
|
||||
|
||||
while (! at_end ()) {
|
||||
if (read_card ()) {
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ public:
|
|||
private:
|
||||
db::Netlist *mp_netlist;
|
||||
db::Circuit *mp_circuit;
|
||||
db::Circuit *mp_anonymous_top_circuit;
|
||||
std::auto_ptr<tl::TextInputStream> mp_stream;
|
||||
tl::weak_ptr<NetlistSpiceReaderDelegate> mp_delegate;
|
||||
std::vector<std::pair<tl::InputStream *, tl::TextInputStream *> > m_streams;
|
||||
|
|
@ -157,6 +158,7 @@ private:
|
|||
db::Net *make_net (const std::string &name);
|
||||
void ensure_circuit ();
|
||||
bool subcircuit_captured (const std::string &nc_name);
|
||||
void build_global_nets ();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -443,3 +443,47 @@ TEST(12_IgnoreDuplicateGlobals)
|
|||
);
|
||||
}
|
||||
|
||||
TEST(13_NoGlobalNetsIfNotUsed)
|
||||
{
|
||||
db::Netlist nl;
|
||||
|
||||
std::string path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nreader13.cir");
|
||||
|
||||
db::NetlistSpiceReader reader;
|
||||
tl::InputStream is (path);
|
||||
reader.read (is, nl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit .TOP ();\n"
|
||||
" device RES $1 (A=VDD,B=NC) (R=1000,L=0,W=0,A=0,P=0);\n"
|
||||
" subcircuit C10 '1' (VDD=VDD,GND=GND);\n"
|
||||
"end;\n"
|
||||
"circuit C10 (VDD=VDD,GND=GND);\n"
|
||||
" subcircuit C1 '1' (VDD=VDD,GND=GND);\n"
|
||||
" subcircuit C2 '2' ();\n"
|
||||
" subcircuit C3 '3' (VDD=VDD,GND=GND);\n"
|
||||
" subcircuit C4 '4' (VDD=VDD,GND=GND);\n"
|
||||
"end;\n"
|
||||
"circuit FILLER_CAP (VDD=VDD,GND=GND);\n"
|
||||
" device NMOS '1' (S=GND,G=VDD,D=GND,B=GND) (L=10,W=10,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
"end;\n"
|
||||
"circuit DUMMY ();\n"
|
||||
" device NMOS '1' (S=A,G=A,D=A,B=B) (L=1,W=1,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
"end;\n"
|
||||
"circuit C1 (VDD=VDD,GND=GND);\n"
|
||||
" subcircuit FILLER_CAP '1' (VDD=VDD,GND=GND);\n"
|
||||
" subcircuit DUMMY '2' ();\n"
|
||||
"end;\n"
|
||||
"circuit C2 ();\n"
|
||||
" subcircuit DUMMY '1' ();\n"
|
||||
"end;\n"
|
||||
"circuit C3 (VDD=VDD,GND=GND);\n"
|
||||
" device NMOS '1' (S=GND,G=VDD,D=GND,B=GND) (L=10,W=10,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
" subcircuit FILLER_CAP '1' (VDD=VDD,GND=GND);\n"
|
||||
"end;\n"
|
||||
"circuit C4 (VDD=VDD,GND=GND);\n"
|
||||
" subcircuit C1 '3' (VDD=VDD,GND=GND);\n"
|
||||
"end;\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
.global vdd gnd
|
||||
|
||||
X1 C10
|
||||
R$1 vdd nc 1k
|
||||
|
||||
.subckt FILLER_CAP
|
||||
M1 gnd vdd gnd gnd NMOS W=10u L=10u
|
||||
.ends FILLER_CAP
|
||||
|
||||
.subckt DUMMY
|
||||
M1 a a a b NMOS W=1u L=1u
|
||||
.ends DUMMY
|
||||
|
||||
.subckt C10
|
||||
X1 C1
|
||||
X2 C2
|
||||
X3 C3
|
||||
X4 C4
|
||||
.ends C10
|
||||
|
||||
.subckt C4
|
||||
X3 C1
|
||||
.ends C4
|
||||
|
||||
.subckt C1
|
||||
* generates gnd and vdd
|
||||
X1 FILLER_CAP
|
||||
X2 DUMMY
|
||||
.ends C1
|
||||
|
||||
.subckt C2
|
||||
* does not generate gnd or vdd
|
||||
X1 DUMMY
|
||||
.ends C2
|
||||
|
||||
.subckt C3
|
||||
* generates gnd and vdd too
|
||||
X1 FILLER_CAP
|
||||
M1 gnd vdd gnd gnd NMOS W=10u L=10u
|
||||
.ends C3
|
||||
|
||||
|
|
@ -266,14 +266,14 @@ reference(
|
|||
# Nets
|
||||
net(1 name(A))
|
||||
net(2 name(Z))
|
||||
net(3 name(VDD))
|
||||
net(4 name(VSS))
|
||||
net(3 name(VSS))
|
||||
net(4 name(VDD))
|
||||
|
||||
# Outgoing pins and their connections to nets
|
||||
pin(1 name(A))
|
||||
pin(2 name(Z))
|
||||
pin(3 name(VDD))
|
||||
pin(4 name(VSS))
|
||||
pin(4 name(VDD))
|
||||
pin(3 name(VSS))
|
||||
|
||||
# Devices and their connections
|
||||
device(1 NMOS
|
||||
|
|
@ -286,8 +286,8 @@ reference(
|
|||
param(PD 0)
|
||||
terminal(S 2)
|
||||
terminal(G 1)
|
||||
terminal(D 4)
|
||||
terminal(B 4)
|
||||
terminal(D 3)
|
||||
terminal(B 3)
|
||||
)
|
||||
device(2 PMOS
|
||||
name('1')
|
||||
|
|
@ -299,8 +299,8 @@ reference(
|
|||
param(PD 0)
|
||||
terminal(S 2)
|
||||
terminal(G 1)
|
||||
terminal(D 3)
|
||||
terminal(B 3)
|
||||
terminal(D 4)
|
||||
terminal(B 4)
|
||||
)
|
||||
|
||||
)
|
||||
|
|
@ -343,32 +343,32 @@ reference(
|
|||
net(1 name(A))
|
||||
net(2 name(C))
|
||||
net(3 name(D))
|
||||
net(4 name(VDD))
|
||||
net(5 name(VSS))
|
||||
net(6 name(B))
|
||||
net(7 name(E))
|
||||
net(4 name(B))
|
||||
net(5 name(E))
|
||||
net(6 name(VDD))
|
||||
net(7 name(VSS))
|
||||
|
||||
# Outgoing pins and their connections to nets
|
||||
pin(1 name(A))
|
||||
pin(2 name(C))
|
||||
pin(3 name(D))
|
||||
pin(4 name(VDD))
|
||||
pin(5 name(VSS))
|
||||
pin(6 name(VDD))
|
||||
pin(7 name(VSS))
|
||||
|
||||
# Subcircuits and their connections
|
||||
circuit(1 DINV name('0')
|
||||
pin(0 1)
|
||||
pin(1 2)
|
||||
pin(2 6)
|
||||
pin(3 7)
|
||||
pin(4 4)
|
||||
pin(5 5)
|
||||
)
|
||||
circuit(2 INVX1 name('1')
|
||||
pin(0 7)
|
||||
pin(1 3)
|
||||
pin(2 4)
|
||||
pin(3 5)
|
||||
pin(4 6)
|
||||
pin(5 7)
|
||||
)
|
||||
circuit(2 INVX1 name('1')
|
||||
pin(0 5)
|
||||
pin(1 3)
|
||||
pin(2 6)
|
||||
pin(3 7)
|
||||
)
|
||||
|
||||
)
|
||||
|
|
@ -398,8 +398,8 @@ xref(
|
|||
xref(
|
||||
net(3 1 match)
|
||||
net(1 2 match)
|
||||
net(2 3 match)
|
||||
net(4 4 match)
|
||||
net(2 4 match)
|
||||
net(4 3 match)
|
||||
pin(2 0 match)
|
||||
pin(0 1 match)
|
||||
pin(1 2 match)
|
||||
|
|
@ -411,11 +411,11 @@ xref(
|
|||
circuit(TOP TOP match
|
||||
xref(
|
||||
net(5 3 match)
|
||||
net(1 7 match)
|
||||
net(6 4 match)
|
||||
net(1 5 match)
|
||||
net(6 6 match)
|
||||
net(2 1 match)
|
||||
net(3 2 match)
|
||||
net(4 5 match)
|
||||
net(4 7 match)
|
||||
pin(() 2 match)
|
||||
pin(() 3 match)
|
||||
pin(0 0 match)
|
||||
|
|
|
|||
Loading…
Reference in New Issue