This commit is contained in:
Matthias Koefferlein 2020-05-28 00:44:49 +02:00
commit bea3e29421
5 changed files with 163 additions and 52 deletions

View File

@ -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;

View File

@ -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 ();
};
}

View File

@ -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"
);
}

42
testdata/algo/nreader13.cir vendored Normal file
View File

@ -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

View File

@ -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)