Hi all, newbie here! I want to simulate a transistor using PySpice. Can anyone tell me the proper wa...
w
Hi all, newbie here! I want to simulate a transistor using PySpice. Can anyone tell me the proper way of including "sky130_fd_pr__nfet_01v8_lvt" in my simple python code here? I use PySpice 1.5 / ngspice-32. Including a simple PTM model file and defining a MOSFET just works fine.
Copy code
circuit.include("./ptm_90nm.model")
circuit.M('1', 'node_drain', 'node_gate',  circuit.gnd, circuit.gnd, model='nmos', width=1e-6, length=1e-6)
However, including
sky130_fd_pr__nfet_01v8_lvt.pm3.spice
and defining a subcircuit does not work.
Copy code
circuit.include("../share/pdk/sky130A/libs.ref/sky130_fd_pr/spice/sky130_fd_pr__nfet_01v8_lvt.pm3.spice")
circuit.X('M1', d='node_drain', g='node_gate', s=circuit.gnd, b=circuit.gnd, model='sky130_fd_pr__nfet_01v8', w=1, l=1, subcircuit_name='nfet')
---
Error: unknown subckt: xm1 nfet b=0 d={node_drain} g={node_gate} l=1 model={sky130_fd_pr__nfet_01v8} s=0 w=1
    Simulation interrupted due to error!
Am I missing something? Please refer to the code below. It's just I-V plotting, but I'm lost. Haha
Copy code
import matplotlib.pyplot as plt
import numpy as np

import PySpice
from PySpice.Spice.Netlist import Circuit, SubCircuit, SubCircuitFactory
from PySpice.Unit import u_V, u_mA

import sys, os
if sys.platform =="linux" or sys.platform =="linux2":
    PySpice.Spice.Simulation.CircuitSimulator.DEFAULT_SIMULATOR = 'ngspice-subprocess'
circuit = Circuit('IVtest')

Vdrain = circuit.V('drain', 'node_drain', circuit.gnd, 1@u_V)
Vgate = circuit.V('gate', 'node_gate', circuit.gnd, 1@u_V)
Copy code
# circuit.include("./ptm_90nm.model")
# circuit.M('1', 'node_drain', 'node_gate',  circuit.gnd, circuit.gnd, model='nmos', width=1e-6, length=1e-6) # this just works fine

# circuit.lib('../share/pdk/sky130A/libs.tech/ngspice/sky130.lib.spice', 'tt')
# circuit.include("../share/pdk/sky130A/libs.tech/ngspice/corners/tt.spice")

circuit.include("../share/pdk/sky130A/libs.ref/sky130_fd_pr/spice/sky130_fd_pr__nfet_01v8_lvt.pm3.spice")
circuit.X('M1', d='node_drain', g='node_gate', s=circuit.gnd, b=circuit.gnd, model='sky130_fd_pr__nfet_01v8', w=1, l=1, subcircuit_name='nfet')
print(circuit)

simulator = circuit.simulator(temperature=27)
print(simulator)

analysis = simulator.dc(Vgate=slice(0, 2, 0.1))

figure, ax = plt.subplots(figsize=(6,3))
ax.plot(u_V(analysis.node_gate), u_mA(-analysis.Vdrain))
ax.grid()
ax.set_xlabel('Vgs [V]')
ax.set_ylabel('Id [mA]')
ax.set_yscale('log')
plt.tight_layout()
plt.show()
Including the library resulted in ~2000 lines of parsing error and >20min of running time, so I aborted it. Thanks in advance
a
you only need the .lib. No other includes or .libs. That is likely cause
also post the generated netlist as its easier to debug
one more thing: why do you use pyspice? Writing plain spice is just easier, or using xschem with the existing infrastructure of tutorials
w
Oh thanks! I'll just include the .lib. And generated netlist below.
Copy code
.title IVtest
.include /home/acelab1/share/pdk/sky130A/libs.ref/sky130_fd_pr/spice/sky130_fd_pr__nfet_01v8_lvt.pm3.spice
Vdrain node_drain 0 1V
Vgate node_gate 0 1V
XM1 nfet b=0 d=node_drain g=node_gate l=1 model=sky130_fd_pr__nfet_01v8 s=0 w=1
.options TEMP = 27C
.options TNOM = 27C
.options NOINIT
.options filetype = binary
.end
Some time ago I wrote the PySpice code which automatically generates and simulate an array of subcircuits, using PTM model file... Now I'm trying to use Sky130 PDK, so that's the reason!
Thanks, @Arman Avetisyan. I used the TT library. The running took about 2 mins but seems no problem. However, I got the same error when running the simulation,
unknown subckt.
Copy code
...
Error: unknown subckt: xm1 nfet b=0 d={node_drain} g={node_gate} l=1 model={sky130_fd_pr__nfet_01v8_lvt} s=0 w=1
    Simulation interrupted due to error!

Error: no circuit loaded!
This is my code below. Maybe I'm not using the subcircuit method the right way. Does anyone have guidance here? Thanks!
Copy code
circuit = Circuit('IVtest')

Vdrain = circuit.V('drain', 'node_drain', circuit.gnd, 1@u_V)
Vgate = circuit.V('gate', 'node_gate', circuit.gnd, 1@u_V)

circuit.lib('../share/pdk/sky130A/libs.tech/ngspice/sky130.lib.spice', 'tt')
circuit.X('M1', d='node_drain', g='node_gate', s=circuit.gnd, b=circuit.gnd, model='sky130_fd_pr__nfet_01v8_lvt', w=1, l=1, subcircuit_name='nfet')

print(circuit)
t
@Wonjae Ji:
Copy code
circuit.include("../share/pdk/sky130A/libs.ref/sky130_fd_pr/spice/sky130_fd_pr__nfet_01v8_lvt.pm3.spice")
circuit.X('M1', d='node_drain', g='node_gate', s=circuit.gnd, b=circuit.gnd, model='sky130_fd_pr__nfet_01v8', w=1, l=1, subcircuit_name='nfet')
---
Error: unknown subckt: xm1 nfet b=0 d={node_drain} g={node_gate} l=1 model={sky130_fd_pr__nfet_01v8} s=0 w=1
    Simulation interrupted due to error!
sky130_fd_pr__nfet_01v8_lvt
is not the same as
sky130_fd_pr__nfet_01v8
. But you are likely to have problems trying to include files if you don't start at the top with
sky130.lib.spice
. This needs a
.lib
statement, not
.include
, and I don't know how you do that with PySpice, but I assume there's a way. The output line should be
.lib /home/acelab1/share/pdk/sky130A/libs.tech/ngspice/sky130.lib.spice tt
. If you do not want the startup to take 30 minutes, then you need to copy the file ``/home/acelab1/share/pdk/sky130A/libs.tech/ngspice/spinit` to the local directory where you are running ngspice, and rename it to
.spiceinit
.
🙌 1
🌍 1
w
Thanks for your help, @Tim Edwards! Yes, now I did
.include
sky130 tt.
.spiceinint
tip also works fine. Thanks! But I'm still having trouble running my PySpice code. I believe now this is a PySpice matter, but I'm looking for any advice. My status: I get
NameError: Unexpected line: Scale set
. Below is the spice code generated by my PySpice code. I believe now there's no problem.
Copy code
.title IVtest
.lib /home/acelab1/share/pdk/sky130A/libs.tech/ngspice/sky130.lib.spice tt
XM1 node_drain node_gate GND GND sky130_fd_pr__nfet_01v8_lvt L=1 W=1 nf=1 ad='int((nf+1)/2) * W/nf * 0.29' as='int((nf+2)/2) * W/nf * 0.29' pd='2*int((nf+1)/2) * (W/nf + 0.29)' ps='2*int((nf+2)/2) * (W/nf + 0.29)' nrd='0.29 / W' nrs='0.29 / W' sa=0 sb=0 sd=0 mult=1 m=1
Vdrain node_drain 0 1V
Vgate node_gate 0 1V
.options TEMP = 27C
.options TNOM = 27C
.options NOINIT
.options filetype = binary
.end
However, I get the error below.
Copy code
NameError                                 Traceback (most recent call last)
/home/acelab1/Transistor/nfet_01v8_lvt_IV.ipynb cell 3 in <cell line: 4>()
      1 simulator = circuit.simulator(temperature=27)
      2 print(simulator)
----> 4 analysis = simulator.dc(Vgate=slice(0, 2, 0.1))

File ~/anaconda3/lib/python3.9/site-packages/PySpice/Spice/Simulation.py:1199, in CircuitSimulator.dc(self, *args, **kwargs)
   1198 def dc(self, *args, **kwargs):
-> 1199     return self._run('dc', *args, **kwargs)

File ~/anaconda3/lib/python3.9/site-packages/PySpice/Spice/NgSpice/Simulation.py:76, in NgSpiceSubprocessCircuitSimulator._run(self, analysis_method, *args, **kwargs)
     72 def _run(self, analysis_method, *args, **kwargs):
     74     super()._run(analysis_method, *args, **kwargs)
---> 76     raw_file = self._spice_server(spice_input=str(self))
     77     self.reset_analysis()
     78     raw_file.simulation = self

File ~/anaconda3/lib/python3.9/site-packages/PySpice/Spice/NgSpice/Server.py:162, in SpiceServer.__call__(self, spice_input)
    157 if number_of_points is None:
    158     raise NameError('The number of points was not found in the standard error buffer,'
    159                     ' ngspice returned:' + os.linesep +
    160                     stderr)
--> 162 return RawFile(stdout, number_of_points)
...
    221     return line
    222 else:
--> 223     raise NameError("Unexpected line: %s" % (line))

NameError: Unexpected line: Scale set
So, I think PySpice cannot handle the
Scale set
line. Anyone can point me out what to do if I wanna manage the ngspice output, i.e. disable that
Scale set
line? Maybe I'm asking odd questions... but any help will be very much appreciated!
I temporarily solved the issue. I manually printed out the ngspice output and selected lines that PySpice could not handle. Then, I modified PySpice's
_read_header
function to ignore the ngspice output lines I selected. Two statements couldn't be handled by PySpice
_read_header
. 1.
\n \n Compatibility modes selected: hs a \n
2.
Scale set to 1e-06
So, I modified the
_read_header
to ignore lines # 0, 1, 2, 3, and 6, which made the issue.
Copy code
File (path_to_PySpice)/PySpice-1.5/PySpice/Spice/NgSpice/Rawfile.py
line 192 : 
# header_line_iterator = iter(header_lines) 
header_line_iterator = iter(header_lines[4:5] + header_lines[7:])
Now, PySpice works fine. But I believe there must be a better solution. Is there anyone who runs ngspice simulation with PySpice, without any of these undesirable modifications? Thanks.
t
@Wonjae Ji: Seems like PySpice is supposed to be reading an output raw file, but is also capturing the stdout (stderr?) output from ngspice. It might just be a matter of properly separating stdout and stderr output streams. But that's just a guess.
a
Create an issue on GitHub of PySpice so that others can find it/it can be fixed. This is something pyspice should handle I assume
🌍 1
126 Views