mirror of https://github.com/KLayout/klayout.git
Implement "M" parameter for Spice
This implementation is pretty simplistic and applies "M" the following way: * R: R(final) = R/M * L: L(final) = L/M * C: C(final) = C*M * M: W(final) = W*M * D: A(final) = A*M * Q: AE(final) = AE*M The other parameters (specifically the other geometry parameters) are not scaled yet.
This commit is contained in:
parent
207e44837c
commit
1bc03c3b79
|
|
@ -85,34 +85,73 @@ static db::DeviceClass *make_device_class (db::Circuit *circuit, const std::stri
|
|||
return cls;
|
||||
}
|
||||
|
||||
bool NetlistSpiceReaderDelegate::element (db::Circuit *circuit, const std::string &element, const std::string &name, const std::string &model, double value, const std::vector<db::Net *> &nets, const std::map<std::string, double> ¶ms)
|
||||
bool NetlistSpiceReaderDelegate::element (db::Circuit *circuit, const std::string &element, const std::string &name, const std::string &model, double value, const std::vector<db::Net *> &nets, const std::map<std::string, double> &pv)
|
||||
{
|
||||
std::map<std::string, double> params = pv;
|
||||
|
||||
double mult = 1.0;
|
||||
std::map<std::string, double>::const_iterator mp = params.find ("M");
|
||||
if (mp != params.end ()) {
|
||||
mult = mp->second;
|
||||
}
|
||||
|
||||
if (mult < 1e-10) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Invalid multiplier value (M=%.12g) - must not be zero or negative")), mult));
|
||||
}
|
||||
|
||||
std::string cn = model;
|
||||
db::DeviceClass *cls = circuit->netlist ()->device_class_by_name (cn);
|
||||
|
||||
if (cls) {
|
||||
|
||||
// use given class
|
||||
|
||||
} else if (element == "R") {
|
||||
|
||||
if (cn.empty ()) {
|
||||
cn = "RES";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassResistor> (circuit, cn);
|
||||
|
||||
// Apply multiplier
|
||||
value /= mult;
|
||||
|
||||
} else if (element == "L") {
|
||||
|
||||
if (cn.empty ()) {
|
||||
cn = "IND";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassInductor> (circuit, cn);
|
||||
|
||||
// Apply multiplier
|
||||
value /= mult;
|
||||
|
||||
} else if (element == "C") {
|
||||
|
||||
if (cn.empty ()) {
|
||||
cn = "CAP";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassCapacitor> (circuit, cn);
|
||||
|
||||
// Apply multiplier
|
||||
value *= mult;
|
||||
|
||||
} else if (element == "D") {
|
||||
|
||||
if (cn.empty ()) {
|
||||
cn = "DIODE";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassDiode> (circuit, cn);
|
||||
|
||||
// Apply multiplier to "A"
|
||||
std::map<std::string, double>::iterator p;
|
||||
p = params.find ("A");
|
||||
if (p != params.end ()) {
|
||||
p->second *= mult;
|
||||
}
|
||||
|
||||
} else if (element == "Q") {
|
||||
|
||||
if (nets.size () == 3) {
|
||||
if (cn.empty ()) {
|
||||
cn = "BJT3";
|
||||
|
|
@ -126,12 +165,29 @@ bool NetlistSpiceReaderDelegate::element (db::Circuit *circuit, const std::strin
|
|||
} else {
|
||||
error (tl::to_string (tr ("'Q' element needs to have 3 or 4 terminals")));
|
||||
}
|
||||
|
||||
// Apply multiplier to "AE"
|
||||
std::map<std::string, double>::iterator p;
|
||||
p = params.find ("AE");
|
||||
if (p != params.end ()) {
|
||||
p->second *= mult;
|
||||
}
|
||||
|
||||
} else if (element == "M") {
|
||||
|
||||
if (nets.size () == 4) {
|
||||
if (cn.empty ()) {
|
||||
cn = "MOS4";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassMOS4Transistor> (circuit, cn);
|
||||
|
||||
// Apply multiplier to "W"
|
||||
std::map<std::string, double>::iterator p;
|
||||
p = params.find ("W");
|
||||
if (p != params.end ()) {
|
||||
p->second *= mult;
|
||||
}
|
||||
|
||||
} else {
|
||||
error (tl::to_string (tr ("'M' element needs to have 4 terminals")));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -333,3 +333,29 @@ TEST(8_Include)
|
|||
);
|
||||
}
|
||||
|
||||
TEST(9_DeviceMultipliers)
|
||||
{
|
||||
db::Netlist nl;
|
||||
|
||||
std::string path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "nreader9.cir");
|
||||
|
||||
db::NetlistSpiceReader reader;
|
||||
tl::InputStream is (path);
|
||||
reader.read (is, nl);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit .TOP ();\n"
|
||||
" device RES $1 (A='1',B='2') (R=850,L=0,W=0,A=0,P=0);\n"
|
||||
" device RES $2 (A='3',B='4') (R=1700,L=0,W=0,A=0,P=0);\n"
|
||||
" device NMOS $1 (S='1',G='2',D='3',B='4') (L=7,W=4,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
" device PMOS $2 (S='1',G='2',D='3',B='4') (L=7,W=2,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
" device CAP $1 (A='1',B='2') (C=2e-09,A=0,P=0);\n"
|
||||
" device CAP $2 (A='3',B='4') (C=1e-09,A=0,P=0);\n"
|
||||
" device DIODE $1 (A='1',C='2') (A=20,P=0);\n"
|
||||
" device DIODE $2 (A='3',C='4') (A=10,P=0);\n"
|
||||
" device BIP $1 (C='1',B='2',E='3',S='4') (AE=20,PE=0,AB=0,PB=0,AC=0,PC=0,NE=1);\n"
|
||||
" device BIP $2 (C='1',B='2',E='3',S='4') (AE=10,PE=0,AB=0,PB=0,AC=0,PC=0,NE=1);\n"
|
||||
"end;\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
R$1 1 2 1.7k M=2
|
||||
R$2 3 4 1.7k
|
||||
M$1 1 2 3 4 NMOS W=2u L=7u M=2
|
||||
M$2 1 2 3 4 PMOS W=2u L=7u
|
||||
C$1 1 2 1e-9 M=2
|
||||
C$2 3 4 1e-9
|
||||
D$1 1 2 DIODE A=10P M=2
|
||||
D$2 3 4 DIODE A=10P
|
||||
Q$1 1 2 3 4 BIP AE=10P M=2
|
||||
Q$2 1 2 3 4 BIP AE=10P
|
||||
|
||||
Loading…
Reference in New Issue