mirror of https://github.com/KLayout/klayout.git
* Fixed #652 (M scaling not working sometimes for Spice), provided testcases * One more patch (bugfix, Spice reader)
This commit is contained in:
parent
051a8bdc77
commit
591d4a5c37
|
|
@ -104,46 +104,66 @@ bool NetlistSpiceReaderDelegate::element (db::Circuit *circuit, const std::strin
|
|||
std::string cn = model;
|
||||
db::DeviceClass *cls = circuit->netlist ()->device_class_by_name (cn);
|
||||
|
||||
if (cls) {
|
||||
if (element == "R") {
|
||||
|
||||
// use given class
|
||||
|
||||
} else if (element == "R") {
|
||||
|
||||
if (cn.empty ()) {
|
||||
cn = "RES";
|
||||
if (cls) {
|
||||
if (! dynamic_cast<db::DeviceClassResistor *>(cls)) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Class %s not a resistor device class as required by 'R' element")), cn));
|
||||
}
|
||||
} else {
|
||||
if (cn.empty ()) {
|
||||
cn = "RES";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassResistor> (circuit, cn);
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassResistor> (circuit, cn);
|
||||
|
||||
// Apply multiplier
|
||||
value /= mult;
|
||||
|
||||
} else if (element == "L") {
|
||||
|
||||
if (cn.empty ()) {
|
||||
cn = "IND";
|
||||
if (cls) {
|
||||
if (! dynamic_cast<db::DeviceClassInductor *>(cls)) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Class %s not a inductor device class as required by 'L' element")), cn));
|
||||
}
|
||||
} else {
|
||||
if (cn.empty ()) {
|
||||
cn = "IND";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassInductor> (circuit, cn);
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassInductor> (circuit, cn);
|
||||
|
||||
// Apply multiplier
|
||||
value /= mult;
|
||||
|
||||
} else if (element == "C") {
|
||||
|
||||
if (cn.empty ()) {
|
||||
cn = "CAP";
|
||||
if (cls) {
|
||||
if (! dynamic_cast<db::DeviceClassCapacitor *>(cls)) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Class %s not a capacitor device class as required by 'C' element")), cn));
|
||||
}
|
||||
} else {
|
||||
if (cn.empty ()) {
|
||||
cn = "CAP";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassCapacitor> (circuit, cn);
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassCapacitor> (circuit, cn);
|
||||
|
||||
// Apply multiplier
|
||||
value *= mult;
|
||||
|
||||
} else if (element == "D") {
|
||||
|
||||
if (cn.empty ()) {
|
||||
cn = "DIODE";
|
||||
if (cls) {
|
||||
if (! dynamic_cast<db::DeviceClassDiode *>(cls)) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Class %s not a diode device class as required by 'D' element")), cn));
|
||||
}
|
||||
} else {
|
||||
if (cn.empty ()) {
|
||||
cn = "DIODE";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassDiode> (circuit, cn);
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassDiode> (circuit, cn);
|
||||
|
||||
// Apply multiplier to "A"
|
||||
std::map<std::string, double>::iterator p;
|
||||
|
|
@ -154,18 +174,30 @@ bool NetlistSpiceReaderDelegate::element (db::Circuit *circuit, const std::strin
|
|||
|
||||
} else if (element == "Q") {
|
||||
|
||||
if (nets.size () == 3) {
|
||||
if (cn.empty ()) {
|
||||
cn = "BJT3";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassBJT3Transistor> (circuit, cn);
|
||||
} else if (nets.size () == 4) {
|
||||
if (cn.empty ()) {
|
||||
cn = "BJT4";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassBJT4Transistor> (circuit, cn);
|
||||
} else {
|
||||
if (nets.size () != 3 && nets.size () != 4) {
|
||||
error (tl::to_string (tr ("'Q' element needs to have 3 or 4 terminals")));
|
||||
} else if (cls) {
|
||||
if (nets.size () == 3) {
|
||||
if (! dynamic_cast<db::DeviceClassBJT3Transistor *>(cls)) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Class %s not a 3-terminal BJT device class as required by 'Q' element")), cn));
|
||||
}
|
||||
} else {
|
||||
if (! dynamic_cast<db::DeviceClassBJT4Transistor *>(cls)) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Class %s not a 4-terminal BJT device class as required by 'Q' element")), cn));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (nets.size () == 3) {
|
||||
if (cn.empty ()) {
|
||||
cn = "BJT3";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassBJT3Transistor> (circuit, cn);
|
||||
} else {
|
||||
if (cn.empty ()) {
|
||||
cn = "BJT4";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassBJT4Transistor> (circuit, cn);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply multiplier to "AE"
|
||||
|
|
@ -177,22 +209,28 @@ bool NetlistSpiceReaderDelegate::element (db::Circuit *circuit, const std::strin
|
|||
|
||||
} else if (element == "M") {
|
||||
|
||||
if (nets.size () == 4) {
|
||||
if (cn.empty ()) {
|
||||
cn = "MOS4";
|
||||
if (cls) {
|
||||
if (! dynamic_cast<db::DeviceClassMOS4Transistor *>(cls)) {
|
||||
error (tl::sprintf (tl::to_string (tr ("Class %s not a 4-terminal MOS device class as required by 'M' element")), cn));
|
||||
}
|
||||
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")));
|
||||
if (nets.size () == 4) {
|
||||
if (cn.empty ()) {
|
||||
cn = "MOS4";
|
||||
}
|
||||
cls = make_device_class<db::DeviceClassMOS4Transistor> (circuit, cn);
|
||||
} else {
|
||||
error (tl::to_string (tr ("'M' element needs to have 4 terminals")));
|
||||
}
|
||||
}
|
||||
|
||||
// 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::sprintf (tl::to_string (tr ("Not a known element type: '%s'")), element));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -359,28 +359,75 @@ TEST(9_DeviceMultipliers)
|
|||
|
||||
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);
|
||||
{
|
||||
db::NetlistSpiceReader reader;
|
||||
tl::InputStream is (path);
|
||||
reader.read (is, nl);
|
||||
|
||||
std::string nl_string = nl.to_string ();
|
||||
// normalization of exponential representation:
|
||||
nl_string = tl::replaced (nl_string, "e-009", "e-09");
|
||||
std::string nl_string = nl.to_string ();
|
||||
// normalization of exponential representation:
|
||||
nl_string = tl::replaced (nl_string, "e-009", "e-09");
|
||||
|
||||
EXPECT_EQ (nl_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"
|
||||
);
|
||||
EXPECT_EQ (nl_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 RMODEL $3 (A='1',B='2') (R=850,L=0,W=0,A=0,P=0);\n"
|
||||
" device RMODEL $4 (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 CMODEL $3 (A='1',B='2') (C=2e-09,A=0,P=0);\n"
|
||||
" device CMODEL $4 (A='3',B='4') (C=1e-09,A=0,P=0);\n"
|
||||
" device IND $1 (A='1',B='2') (L=5e-10);\n"
|
||||
" device IND $2 (A='3',B='4') (L=1e-09);\n"
|
||||
" device LMODEL $3 (A='1',B='2') (L=5e-10);\n"
|
||||
" device LMODEL $4 (A='3',B='4') (L=1e-09);\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"
|
||||
);
|
||||
}
|
||||
|
||||
db::Circuit *top = nl.circuit_by_name (".TOP");
|
||||
nl.remove_circuit (top);
|
||||
|
||||
// read once again, this time with known classes (must not trigger issue-652)
|
||||
{
|
||||
db::NetlistSpiceReader reader;
|
||||
tl::InputStream is (path);
|
||||
reader.read (is, nl);
|
||||
|
||||
std::string nl_string = nl.to_string ();
|
||||
// normalization of exponential representation:
|
||||
nl_string = tl::replaced (nl_string, "e-009", "e-09");
|
||||
|
||||
EXPECT_EQ (nl_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 RMODEL $3 (A='1',B='2') (R=850,L=0,W=0,A=0,P=0);\n"
|
||||
" device RMODEL $4 (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 CMODEL $3 (A='1',B='2') (C=2e-09,A=0,P=0);\n"
|
||||
" device CMODEL $4 (A='3',B='4') (C=1e-09,A=0,P=0);\n"
|
||||
" device IND $1 (A='1',B='2') (L=5e-10);\n"
|
||||
" device IND $2 (A='3',B='4') (L=1e-09);\n"
|
||||
" device LMODEL $3 (A='1',B='2') (L=5e-10);\n"
|
||||
" device LMODEL $4 (A='3',B='4') (L=1e-09);\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"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(10_SubcircuitsNoPins)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,18 @@
|
|||
|
||||
R$1 1 2 1.7k M=2
|
||||
R$2 3 4 1.7k
|
||||
R$3 1 2 1.7k RMODEL M=2
|
||||
R$4 3 4 1.7k RMODEL
|
||||
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
|
||||
C$3 1 2 1e-9 CMODEL M=2
|
||||
C$4 3 4 1e-9 CMODEL
|
||||
L$1 1 2 1e-9 M=2
|
||||
L$2 3 4 1e-9
|
||||
L$3 1 2 1e-9 LMODEL M=2
|
||||
L$4 3 4 1e-9 LMODEL
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue