-
Notifications
You must be signed in to change notification settings - Fork 118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
xspice simulation #76
Comments
I think the |
I made some modifications to support XSPICE components in SKiDL. You can try them out by installing:
Here's your example rewritten using the new SKiDL features: from skidl.pyspice import *
# component declaration
vin = sinev(offset=1.65 @ u_V, amplitude=1.65 @ u_V, frequency=100e6)
adc = A("[anlg_in]", "[dig_out]", model=XspiceModel("adc", "adc_bridge", in_low=0.05 @ u_V, in_high=0.1 @ u_V, rise_delay=1e-9 @ u_s, fall_delay=1e-9 @ u_s))
buf = A("buf_in", "buf_out", model=XspiceModel("buf", "d_buffer", rise_delay=1e-9 @ u_s, fall_delay=1e-9 @ u_s, input_load=1e-12 @ u_s,))
dac = A("[dig_in]", "[anlg_out]", model=XspiceModel("dac", "dac_bridge", out_low=1.0 @ u_V, out_high=3.3 @ u_V))
r = R(value=1 @ u_kOhm)
# component connections
vin["n"] += gnd, r["n"]
vin["p"] += adc["anlg_in"][0] # Attach to first pin in ADC anlg_in vector of pins.
adc["dig_out"][0] += buf["buf_in"] # Attach first pin of ADC dig_out vector to buffer.
buf["buf_out"] += dac["dig_in"][0] # Attach buffer output to first pin of DAC dig_in vector of pins.
r["p"] += dac["anlg_out"][0] # Attach DAC first pin of anlg_out vector to load resistor.
circ = generate_netlist(libs='SpiceLib')
print(circ)
sim = circ.simulator()
waveforms = sim.transient(step_time=0.1 @ u_ns, end_time=50 @ u_ns)
time = waveforms.time
vin = waveforms[node(vin["p"])]
vout = waveforms[node(r["p"])]
print(time)
print(vin)
print(vout) Here are the primary modifications to SKiDL:
One caveat on this is I haven't been able to get this to simulate correctly: even though ngspice doesn't complain about any problems, all the outputs of the XSPICE components are stuck at zero. However, this is also true when I tried running your PySpice file, so I suspect it's something to do with my ngspice executable. I did compare the SPICE netlist output by my program to the one from your PySpice program and they were topologically the same (i.e., the node names were different), so I have hope that this will actually function once the ngspice problem is solved. Let me know if this works for you. I think that's about it. |
I'm getting the following backtrace when running your example:
This seems to happen with the "adc" xspice model ( As for your issue with xspice, did you enable xspice support when compiling ngspice ( |
I was able to bypass that issue temporarily with |
Yeah, sorry. Looks like I introduced an error at the end when I was trying t support Part copying. I'll look into it and see what's going on. Are you getting all-zero outputs even with your original PySpice version? I'm using ngspice 30 under Windows 10. Everything I've read says you don't need the --enable-xspice on Windows because it's already compiled with it enabled. |
I fixed the problem with SKiDL. My example doesn't throw an error for me, anymore. XSPICE simulation still returns all zeroes. |
Great, thanks for fixing. I'm currently trying to figure out the pyspice issue/reproduce what I had before. I'll post back with updates. |
This appears to be a bug with Ngspice (in particular, I believe its the same as this one). I was able to get the correct behavior with my old version of Ngspice (30, maybe you have a later commit, I don't know). If you're curious about the intended results, the netlist is something like this
This line is the problem:
Changing it to
or
Should give you the correct output. In other words, as far as I can tell, skidl is doing the right thing here. |
That may need fixing in ngspice, but it also looks like PySpice might need some modification. I can't see why it's putting the That said, do you think the current way that SKiDL handles XSPICE parts is adequate? Do you see the need for any improvements/additions? |
You’re right that some of what PySpice emits is unnecessary. However, I looked at the Ngspice manual and technically it’s in accordance with the syntax. For instance, the ac magnitude is assumed to be 1 if omitted, which is the case here. Since I haven’t spent much time looking through the code, maybe the author has a reason for it that I don’t know. In regard to the way skidl handles xspice it seems good so far, but I haven’t used it much yet. Let me use it to model some more stuff and then I’ll make another post with thoughts. Thanks for all the work you’ve put into this and for implementing the xspice feature so quickly. |
Is it possible to use the Part-style interface for xspice? For example, from skidl.pyspice import Part, XspiceModel
adc = Part(
"pyspice",
"A",
"[anlg_in]",
"[dig_out]",
model=XspiceModel(
"adc",
"adc_bridge",
in_low=3.3 / 3,
in_high=2 * 3.3 / 3,
rise_delay=1e-9,
fall_delay=1e-9,
),
) Fails with
|
I've checked in the updated SKiDL. You should be able to instantiate XSPICE parts using the from skidl.pyspice import *
# component declaration
vin = sinev(offset=1.65 @ u_V, amplitude=1.65 @ u_V, frequency=100e6)
adc = Part('pyspice', 'A', io="[anlg_in],[dig_out]", model=XspiceModel("adc", "adc_bridge", in_low=0.05 @ u_V, in_high=0.1 @ u_V, rise_delay=1e-9 @ u_s, fall_delay=1e-9 @ u_s))
buf = A(io=["buf_in, buf_out"], model=XspiceModel("buf", "d_buffer", rise_delay=1e-9 @ u_s, fall_delay=1e-9 @ u_s, input_load=1e-12 @ u_s,))
dac = A(io=["[dig_in]", "[anlg_out]"], model=XspiceModel("dac", "dac_bridge", out_low=1.0 @ u_V, out_high=3.3 @ u_V))
r = R(value=1 @ u_kOhm)
# component connections
vin["n"] += gnd, r["n"]
vin["p"] += adc["anlg_in"][0] # Attach to first pin in ADC anlg_in vector of pins.
adc["dig_out"][0] += buf["buf_in"] # Attach first pin of ADC dig_out vector to buffer.
buf["buf_out"] += dac["dig_in"][0] # Attach buffer output to first pin of DAC dig_in vector of pins.
r["p"] += dac["anlg_out"][0] # Attach DAC first pin of anlg_out vector to load resistor.
circ = generate_netlist(libs='SpiceLib')
print(circ)
sim = circ.simulator()
waveforms = sim.transient(step_time=0.1 @ u_ns, end_time=50 @ u_ns)
time = waveforms.time
vin = waveforms[node(vin["p"])]
vout = waveforms[node(r["p"])]
print(time)
print(vin)
print(vout) |
Works great, thanks! I'll continue to test this out and will provide feedback if anything comes up, but I've tried this out with a few simulations and so far everything works very well and the interface is easy to use. |
Do you see any other needed modifications before I close the issue and document the feature? |
I'm wondering a bit about the interface to vector pins. The current method feels a bit counter-intuitive. For instance, if I declare something like xor = Part(
"pyspice",
"A",
io=["[in1 in2]", "out"],
model=XspiceModel(
"xor", "d_xor", rise_delay=1e-12, fall_delay=1e-12, input_load=1e-12,
),
) I would then access in2 with xor["in1"][1]
# or
xor["in2"][1] whereas when writing the netlist directly in spice I would just write the internal node name directly to make a connection to the pin. In that vein, it might be nice to be able to access the pins in a flat way. I.e. xor["in2"] I currently don't see any use to being able to access the pin in a vector-like format. However, I'm very new to xspice, so that use case may be obvious to someone with more experience. From what I can tell reading the documentation, it seems like the vector format is mostly useful for declaring the pin interface but is not used after that. Do you have any experience with this? Any thoughts? |
Yeah, you can't name vector I/O using names like When you created the vector input using |
That makes a lot more sense, and now I see the benefit of the vector notation. Thanks for clearing that up. I have no further feedback at this time. Feel free to close and document. |
Thanks for this great program!
How can I perform an ngspice, xspice simulation with skidl? Here's a simple example (buffer driven by a sinusoidal voltage source) that works using just PySpice.
However, I'm having trouble translating this to the equivalent skidl syntax. From the documentation/code I see that
A()
is used for this, but I don't see how I can set the ports and model with this. Here's an example of something I've tried, although unsurprisingly it doesn't work.It complains starting at the
adc=A(...
line, which I guess is expected since the only valid attribute ismodel
. However, I'm confused about how to actually define this model, and also how to define the ports. Thanks.The text was updated successfully, but these errors were encountered: