PySpice-org / PySpice

Simulate electronic circuit using Python and the Ngspice / Xyce simulators
https://pyspice.fabrice-salvaire.fr
GNU General Public License v3.0
650 stars 170 forks source link

Can't parse MOSFET sizes in SPICE netlist files #142

Closed aiifabbf closed 5 years ago

aiifabbf commented 5 years ago

Environment (OS, Python version, PySpice version, simulator)

Ubuntu 16.04, Python 3.6.5, PySpice 1.2.0, ngspice 26 as subprocess

Expected Behaviour

This is a SPICE netlist file for a two-stage amplifier.

*Sheet Name:/OPA_SR
V1  vp GND dc 1.65 ac 0.5
V2  vn GND dc 1.65 ac -0.5
C2  Vout GND 4p
C1  /3 Vout 6.9p
M7  Vout /6 VDD VDD p_33 W=25.9u L=0.9u
M6  Vout /3 GND GND n_33 W=92.04u L=1.4u
M2  /3 vp /1 VDD p_33 W=51.78u L=0.9u
M1  /2 vn /1 VDD p_33 W=51.78u L=0.9u
M4  /3 /2 GND GND n_33 W=46.02u L=1.4u
M3  /2 /2 GND GND n_33 W=46.02u L=1.4u
M5  /1 /6 VDD VDD p_33 W=12.95u L=0.9u
V0  VDD GND 3.3
M8  /6 /6 VDD VDD p_33 W=1.3u L=0.9u
I1  /6 GND 10u

.lib CMOS_035_Spice_Model.lib tt

.end

I have defined every parameter for each component in this netlist file, including the size(width and length) for each MOSFET. After SpiceParser("foo.cir").build_circuit(), the generated circuit should include all parameters specified in the netlist file.

Actual Behaviour

However, when I try to parse this netlist, and build the circuit

In [41]: circuit = SpiceParser("two-stage-amp.cir").build_circuit()
.lib CMOS_035_Spice_Model.lib tt

In [42]: print(circuit)
.title
V1 vp GND dc 1.65 ac 0.5
V2 vn GND dc 1.65 ac -0.5
C2 Vout GND 4p
C1 /3 Vout 6.9p
M7 Vout /6 VDD VDD p_33
M6 Vout /3 GND GND n_33
M2 /3 vp /1 VDD p_33
M1 /2 vn /1 VDD p_33
M4 /3 /2 GND GND n_33
M3 /2 /2 GND GND n_33
M5 /1 /6 VDD VDD p_33
V0 VDD GND 3.3
M8 /6 /6 VDD VDD p_33
I1 /6 GND 10u

...all widths and lengths of MOSFETs seem to be lost. (The .lib expression is lost too, but that is another issue...)

If I try to access one particular MOSFET

In [54]: circuit.elements
Out[54]: odict_values([VoltageSource V1, VoltageSource V2, BehavioralCapacitor C2, BehavioralCapacitor C1, Mosfet M7, Mosfet M6, Mosfet M2, Mosfet M1, Mosfet M4, Mosfet M3, Mosfet M5, VoltageSource V0, Mosfet M8, CurrentSource I1])

In [55]: list(circuit.elements)[-2]
Out[55]: Mosfet M8

In [56]: print(list(circuit.elements)[-2].width)
None

its width is None.

Steps to reproduce the behaviour

Save the netlist aforementioned to a file foo.cir and then

from PySpice.Spice.Parser import SpiceParser
circuit = SpiceParser("foo.cir").build_circuit()
print(circuit)
aiifabbf commented 5 years ago

I tried more cases just now. This netlist file works though

*Sheet Name:/OPA_SR
V1  vp GND dc 1.65 ac 0.5
V2  vn GND dc 1.65 ac -0.5
C2  Vout GND 4e-12
C1  /3 Vout 6.9e-12
M7  Vout /6 VDD VDD p_33 width=25.9e-6 length=0.9e-6
M6  Vout /3 GND GND n_33 width=92.04e-6 length=1.4e-6
M2  /3 vp /1 VDD p_33 width=51.78e-6 length=0.9e-6
M1  /2 vn /1 VDD p_33 width=51.78e-6 length=0.9e-6
M4  /3 /2 GND GND n_33 width=46.02e-6 length=1.4e-6
M3  /2 /2 GND GND n_33 width=46.02e-6 length=1.4e-6
M5  /1 /6 VDD VDD p_33 width=12.95e-6 length=0.9e-6
V0  VDD GND 3.3
M8  /6 /6 VDD VDD p_33 width=1.3e-6 length=0.9e-6
I1  /6 GND 10e-6

.lib CMOS_035_Spice_Model.lib tt

.end

Below is what I get from the parser

In [61]: !cat two-stage-amp\ \(copy\).cir
*Sheet Name:/OPA_SR
V1  vp GND dc 1.65 ac 0.5
V2  vn GND dc 1.65 ac -0.5
C2  Vout GND 4e-12
C1  /3 Vout 6.9e-12
M7  Vout /6 VDD VDD p_33 width=25.9e-6 length=0.9e-6
M6  Vout /3 GND GND n_33 width=92.04e-6 length=1.4e-6
M2  /3 vp /1 VDD p_33 width=51.78e-6 length=0.9e-6
M1  /2 vn /1 VDD p_33 width=51.78e-6 length=0.9e-6
M4  /3 /2 GND GND n_33 width=46.02e-6 length=1.4e-6
M3  /2 /2 GND GND n_33 width=46.02e-6 length=1.4e-6
M5  /1 /6 VDD VDD p_33 width=12.95e-6 length=0.9e-6
V0  VDD GND 3.3
M8  /6 /6 VDD VDD p_33 width=1.3e-6 length=0.9e-6
I1  /6 GND 10e-6

.lib CMOS_035_Spice_Model.lib tt

.end

In [62]: circuit = SpiceParser("two-stage-amp (copy).cir").build_circ
    ...: uit()
.lib CMOS_035_Spice_Model.lib tt

In [63]: print(circuit)
.title
V1 vp GND dc 1.65 ac 0.5
V2 vn GND dc 1.65 ac -0.5
C2 Vout GND 4e-12
C1 /3 Vout 6.9e-12
M7 Vout /6 VDD VDD p_33 l=0.9e-6 w=25.9e-6
M6 Vout /3 GND GND n_33 l=1.4e-6 w=92.04e-6
M2 /3 vp /1 VDD p_33 l=0.9e-6 w=51.78e-6
M1 /2 vn /1 VDD p_33 l=0.9e-6 w=51.78e-6
M4 /3 /2 GND GND n_33 l=1.4e-6 w=46.02e-6
M3 /2 /2 GND GND n_33 l=1.4e-6 w=46.02e-6
M5 /1 /6 VDD VDD p_33 l=0.9e-6 w=12.95e-6
V0 VDD GND 3.3
M8 /6 /6 VDD VDD p_33 l=0.9e-6 w=1.3e-6
I1 /6 GND 10e-6

Looks like the parser ignores size definition that starts with w= and l= but successfully identifies width= and length=.

FabriceSalvaire commented 5 years ago

Thanks to report !

aiifabbf commented 5 years ago

You are welcome. Thank you for the fix!