mirror of https://github.com/KLayout/klayout.git
Added .global to Spice reader.
This commit is contained in:
parent
9d250d6df9
commit
14d9689498
|
|
@ -195,6 +195,7 @@ void NetlistSpiceReader::read (tl::InputStream &stream, db::Netlist &netlist)
|
|||
mp_netlist = &netlist;
|
||||
mp_circuit = 0;
|
||||
mp_nets_by_name.reset (0);
|
||||
m_global_nets.clear ();
|
||||
|
||||
try {
|
||||
|
||||
|
|
@ -343,6 +344,11 @@ bool NetlistSpiceReader::read_card ()
|
|||
|
||||
// ignore model statements
|
||||
|
||||
} else if (ex.test_without_case ("global")) {
|
||||
|
||||
std::string n = read_name (ex);
|
||||
m_global_nets.push_back (n);
|
||||
|
||||
} else if (ex.test_without_case ("subckt")) {
|
||||
|
||||
std::string nc = read_name (ex);
|
||||
|
|
@ -497,6 +503,10 @@ void NetlistSpiceReader::ensure_circuit ()
|
|||
mp_circuit->set_name (".TOP");
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -737,16 +747,25 @@ void NetlistSpiceReader::read_subcircuit (const std::string &sc_name, const std:
|
|||
|
||||
db::Circuit *cc = mp_netlist->circuit_by_name (nc_name);
|
||||
if (! cc) {
|
||||
|
||||
cc = new db::Circuit ();
|
||||
mp_netlist->add_circuit (cc);
|
||||
cc->set_name (nc_name);
|
||||
|
||||
// we'll make the names later ...
|
||||
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 ()) {
|
||||
|
||||
if (cc->pin_count () != nets.size () + m_global_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 ())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
db::SubCircuit *sc = new db::SubCircuit (cc, sc_name);
|
||||
|
|
@ -755,6 +774,11 @@ 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*/)
|
||||
|
|
@ -789,16 +813,23 @@ void NetlistSpiceReader::read_circuit (tl::Extractor &ex, const std::string &nc)
|
|||
|
||||
db::Circuit *cc = mp_netlist->circuit_by_name (nc);
|
||||
if (! cc) {
|
||||
|
||||
cc = new db::Circuit ();
|
||||
mp_netlist->add_circuit (cc);
|
||||
cc->set_name (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 ()) {
|
||||
|
||||
if (cc->pin_count () != nn.size () + m_global_nets.size ()) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Pin count mismatch between implicit (through call) and explicit circuit definition: %d expected, got %d")), int (cc->pin_count ()), int (nn.size ())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::auto_ptr<std::map<std::string, db::Net *> > n2n (mp_nets_by_name.release ());
|
||||
|
|
@ -806,13 +837,23 @@ void NetlistSpiceReader::read_circuit (tl::Extractor &ex, const std::string &nc)
|
|||
|
||||
std::swap (cc, mp_circuit);
|
||||
|
||||
// produce the explicit pins
|
||||
for (std::vector<std::string>::const_iterator i = nn.begin (); i != nn.end (); ++i) {
|
||||
db::Net *net = make_net (*i);
|
||||
// use the net name to name the pin (otherwise SPICE pins are always unnamed)
|
||||
size_t pin_id = i - nn.begin ();
|
||||
if (! i->empty ()) {
|
||||
mp_circuit->rename_pin (i - nn.begin (), net->name ());
|
||||
mp_circuit->rename_pin (pin_id, net->name ());
|
||||
}
|
||||
mp_circuit->connect_pin (i - nn.begin (), net);
|
||||
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 ()) {
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ private:
|
|||
std::auto_ptr<std::map<std::string, db::Net *> > mp_nets_by_name;
|
||||
std::string m_stored_line;
|
||||
std::map<std::string, bool> m_captured;
|
||||
std::vector<std::string> m_global_nets;
|
||||
|
||||
void push_stream (const std::string &path);
|
||||
void pop_stream ();
|
||||
|
|
|
|||
|
|
@ -255,3 +255,42 @@ TEST(6_ReaderWithDelegate)
|
|||
"end;\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(7_GlobalNets)
|
||||
{
|
||||
db::Netlist nl;
|
||||
|
||||
std::string path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nreader7.cir");
|
||||
|
||||
MyNetlistReaderDelegate delegate;
|
||||
db::NetlistSpiceReader reader (&delegate);
|
||||
tl::InputStream is (path);
|
||||
reader.read (is, nl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit RINGO (FB=FB,OUT=OUT,ENABLE=ENABLE,VDD=VDD,VSS=VSS);\n"
|
||||
" subcircuit ND2X1 $1 (OUT='1',B=FB,A=ENABLE,VDD=VDD,VSS=VSS);\n"
|
||||
" subcircuit INVX1 $2 (OUT='2',IN='1',VDD=VDD,VSS=VSS);\n"
|
||||
" subcircuit INVX1 $3 (OUT='3',IN='2',VDD=VDD,VSS=VSS);\n"
|
||||
" subcircuit INVX1 $4 (OUT='4',IN='3',VDD=VDD,VSS=VSS);\n"
|
||||
" subcircuit INVX1 $5 (OUT='5',IN='4',VDD=VDD,VSS=VSS);\n"
|
||||
" subcircuit INVX1 $6 (OUT='6',IN='5',VDD=VDD,VSS=VSS);\n"
|
||||
" subcircuit INVX1 $7 (OUT='7',IN='6',VDD=VDD,VSS=VSS);\n"
|
||||
" subcircuit INVX1 $8 (OUT='8',IN='7',VDD=VDD,VSS=VSS);\n"
|
||||
" subcircuit INVX1 $9 (OUT='9',IN='8',VDD=VDD,VSS=VSS);\n"
|
||||
" subcircuit INVX1 $10 (OUT='10',IN='9',VDD=VDD,VSS=VSS);\n"
|
||||
" subcircuit INVX1 $11 (OUT=FB,IN='10',VDD=VDD,VSS=VSS);\n"
|
||||
" subcircuit INVX1 $12 (OUT=OUT,IN=FB,VDD=VDD,VSS=VSS);\n"
|
||||
"end;\n"
|
||||
"circuit ND2X1 (OUT=OUT,B=B,A=A,VDD=VDD,VSS=VSS);\n"
|
||||
" device MLVPMOS $1 (S=OUT,G=A,D=VDD,B=VDD) (L=0.25,W=1.5,AS=0.6375,AD=0.3375,PS=3.85,PD=1.95);\n"
|
||||
" device MLVPMOS $2 (S=VDD,G=B,D=OUT,B=VDD) (L=0.25,W=1.5,AS=0.3375,AD=0.6375,PS=1.95,PD=3.85);\n"
|
||||
" device MLVNMOS $3 (S=VSS,G=A,D=INT,B=VSS) (L=0.25,W=0.95,AS=0.40375,AD=0.21375,PS=2.75,PD=1.4);\n"
|
||||
" device MLVNMOS $4 (S=INT,G=B,D=OUT,B=VSS) (L=0.25,W=0.95,AS=0.21375,AD=0.40375,PS=1.4,PD=2.75);\n"
|
||||
"end;\n"
|
||||
"circuit INVX1 (OUT=OUT,IN=IN,VDD=VDD,VSS=VSS);\n"
|
||||
" device MLVPMOS $1 (S=VDD,G=IN,D=OUT,B=VDD) (L=0.25,W=1.5,AS=0.6375,AD=0.6375,PS=3.85,PD=3.85);\n"
|
||||
" device MLVNMOS $2 (S=VSS,G=IN,D=OUT,B=VSS) (L=0.25,W=0.95,AS=0.40375,AD=0.40375,PS=2.75,PD=2.75);\n"
|
||||
"end;\n"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
* RINGO netlist with global nets
|
||||
|
||||
.GLOBAL VDD
|
||||
.GLOBAL VSS
|
||||
|
||||
.SUBCKT RINGO FB OUT ENABLE
|
||||
X$1 1 FB ENABLE ND2X1
|
||||
X$2 2 1 INVX1
|
||||
X$3 3 2 INVX1
|
||||
X$4 4 3 INVX1
|
||||
X$5 5 4 INVX1
|
||||
X$6 6 5 INVX1
|
||||
X$7 7 6 INVX1
|
||||
X$8 8 7 INVX1
|
||||
X$9 9 8 INVX1
|
||||
X$10 10 9 INVX1
|
||||
X$11 FB 10 INVX1
|
||||
X$12 OUT FB INVX1
|
||||
.ENDS RINGO
|
||||
|
||||
.SUBCKT ND2X1 OUT B A
|
||||
M$1 OUT A VDD VDD MLVPMOS L=0.25U W=1.5U AS=0.6375P AD=0.3375P PS=3.85U PD=1.95U
|
||||
M$2 VDD B OUT VDD MLVPMOS L=0.25U W=1.5U AS=0.3375P AD=0.6375P PS=1.95U PD=3.85U
|
||||
M$3 VSS A INT VSS MLVNMOS L=0.25U W=0.95U AS=0.40375P AD=0.21375P PS=2.75U PD=1.4U
|
||||
M$4 INT B OUT VSS MLVNMOS L=0.25U W=0.95U AS=0.21375P AD=0.40375P PS=1.4U PD=2.75U
|
||||
.ENDS ND2X1
|
||||
|
||||
.SUBCKT INVX1 OUT IN
|
||||
M$1 VDD IN OUT VDD MLVPMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U
|
||||
M$2 VSS IN OUT VSS MLVNMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U
|
||||
.ENDS INVX1
|
||||
Loading…
Reference in New Issue