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:
Matthias Koefferlein 2019-08-19 22:51:22 +02:00
parent 207e44837c
commit 1bc03c3b79
3 changed files with 95 additions and 1 deletions

View File

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

View File

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

12
testdata/algo/nreader9.cir vendored Normal file
View File

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