Giter Site home page Giter Site logo

Comments (20)

eps82 avatar eps82 commented on June 12, 2024 1

Sure, as soon as I know what I'm doing I'll post something more concise.

And no need for excuses, really! It's a very nice piece of work as it is and I'm sure many including myself are very happy it exists. Front-ends always take time and effort.

from pyspice.

eps82 avatar eps82 commented on June 12, 2024

I've been doing some more tinkering and I found the causes for my (multiple) problems, mostly due to silent errors:

  • Some of the parameters I wanted to extract were not defined in the model level I was using as a dummy example; I changed it to BSIM4 and everything seemed to work
  • At some point I mislabeled one of the models. For some reason this still allowed to return GM but not other transistor parameters (probably because of using a default transistor model when not finding the good one)
  • Some errata in the .SAVE options

I think now I can keep customizing the code but any comments on this will be welcome :)

from pyspice.

FabriceSalvaire avatar FabriceSalvaire commented on June 12, 2024

The code implements an automatic conversion from simulation output to waveform object.

  1. There is some hacks to fix Ngspice case/naming folk
  2. Code is probably not complete (type of simulation and variable)

I never tried to get such variables. Could you post some code ?

from pyspice.

eps82 avatar eps82 commented on June 12, 2024

Thanks for the reply. I'd been tracking NgSpiceShared.plot() because it was were most of the magic was happening. Basically I just created my own method to insert .SAVE statements such as

M1 yaddah yaddah
.DC Vsomething VSTART VEND VSTEP
.SAVE DC @m1[VTH]

Currently, without any extra tricks, this is identified as a voltage and stored as if it was a node, so it can be read using the corresponding label @m1[vth]. I've noticed ngspice outputs have unit identifiers so VTH (a voltage) is saved as if it was a node; same for M1[ID] for example as a current. Saving a capacitance such as CGG, however, would make it crash, because the unit type (21 for capacitances) is not defined in PySpice.

My solution at the moment is to try to intercept all outputs and store them in a separate dictionary regardless of the unit, then drop them if their units are not properly handled in pyspice before passing them on to the rest of the code (so currents and voltages will still be recorded as nodes/branches too). I'm not concerned about having some extra entries in those dictionaries (for example when VTH is also stored as a node voltage) because it won't cause me any trouble (unless I wanted to just go through all of them, but I'm not interested for now).

It's still a bit hard for me to track the flow at times because I'm not familiar with the class hierarchy but I think implementing this in a cleaner manner (my coding elegance is the equivalent of opening a can with an axe at this point) should be pretty straightforward given how easily I'm getting some results. I could post some code once I remove all the test points if you're interested, or maybe we can share impressions if you already have your own.

From what I've seen, doing it properly would take modifying is_voltage_node()/is_branch_current to make it smarter (so it doesn't just check units but whether the names are actual nodes/branches), and then expand the unit definitions. Also I'd check SIMULATION_TYPE because the enumeration I'm looking at doesn't add up (voltage is indeed code 3, but ngspice returns capacitance and charge as 21 and 22, yet they are 19 and 20 in the enumeration in NgSpiceShared)

from pyspice.

FabriceSalvaire avatar FabriceSalvaire commented on June 12, 2024

If I am right @ variable require an explicit call to save, thus I have to enhance the dc simualtion code.

Yes post your code or things to be fixed (bullet list) Ngspice manual is impressive, so things are implemented incrementally

from pyspice.

FabriceSalvaire avatar FabriceSalvaire commented on June 12, 2024

Basic examples are also welcome, for example advanced dc simulation to show to newcomers what they can do with spice

from pyspice.

eps82 avatar eps82 commented on June 12, 2024

I could post some diffs but instead I'll just post directly here (all code comments are mine):

First in Spice/Simulation.py I made the following changes to allow raw spice code:

class CircuitSimulation:
  def __init__():
    ...
    self._raw = [] # List of strings to be inserted in the netlist
    ...
 
  def raw(self, r):  # New
    self._raw.append(str_spice(r))
  
  def __str__(self):
    ...
    for raw in self._raw:  # Insert raw Spice code before closing netlist
      netlist += raw + os.linesep
    netlist += '.end' + os.linesep
    # It might save some time if it was a list, returning os.linesep.join(line_list) instead
    return netlist 

Then in Spice/NgSpice/Shared.py I did the following:

class Plot(dict):
    ...
   def to_analysis(self):
        # Don't return immediately, save as 'analysis' for now instead
        if self.plot_name.startswith('op'):
            analysis = self._to_operating_point_analysis()
        elif self.plot_name.startswith('sens'):
            analysis = self._to_sensitivity_analysis()
        elif self.plot_name.startswith('dc'):
            analysis = self._to_dc_analysis()
        elif self.plot_name.startswith('ac'):
            analysis = self._to_ac_analysis()
        elif self.plot_name.startswith('tran'):
            analysis = self._to_transient_analysis()
        else:
            raise NotImplementedError("Unsupported plot name {}".format(self.plot_name))
        # Attach raw data before returning
        analysis.raw = {key : self[key].data for key in self}
        return analysis

class NgSpiceShared:

    _logger = _module_logger.getChild('NgSpiceShared')

    SIMULATION_TYPE = EnumFactory('SimulationType', ( 
        # Fixed from include/ngspice/sim.h
        # 2 units were inserted, explaining why capacitance was breaking it
        'no_type',
        'time',
        'frequency',
        'voltage',
        'current',
        'voltage_density',  # inserted
        'current_density',  # inserted. 
        'sqr_voltage_density',  # changed from input/output noise/density etc
        'sqr_current_density',  # changed
        'sqr_voltage',  # changed
        'sqr_current',  # changed
        'pole',
        'zero',
        's_parameter',  # maybe should be sparam? I don't wanna break anything
        'temperature',  # same with temp
        'res',
        'impedance',
        'admittance',
        'power',
        'phase',
        'db',
        'capacitance',
        'charge'))

This is enough to allow me to do things like:

simulator.raw('.save dc @m1[cgg]')
analysis = simulator.dc(VG=slice(0, 1, 0.01)) # some generator of Vgs somewhere
cgg_data = analysis.raw['@m1[cgg]']  
# actually I made some functions to avoid using @m1[] every time, but just for the idea

I haven't tried nested sweeps or anything like that yet so I'm not sure how this would work (or if), but I think this would be enough for now for what I was trying to do. Also note I'm not filtering nodes/branches so voltages and currents will be stored there too.

I think in general it would be good to allow "low level channels" for data through the class stack. I imagine the kind of person who wants to script spice already has a very powerful reason to do so, so they have in general lower requirements when it comes to functionality. Having full access to both netlisting and data retrieval as a clean/simplified ngspice wrapper in a slightly less barbaric way than what I propose above would be attractive to such users (they're likely to write their own ad-hoc netlisters too), while the higher level tools would still make it usable to a wider public but without discouraging the first group when something hasn't been fully implemented (since they won't really need it even if they'd welcome it). But of course I was the one looking for a wrapper in the first place so I may be -cough- biased.

from pyspice.

FabriceSalvaire avatar FabriceSalvaire commented on June 12, 2024

Reference

  • Chapter 31
  • Model and Device Parameters
  • 31.1 Accessing internal device parameters
  • p. 549

Output parameters are those additional parameters that are available for many types of instances
for the output of operating point and debugging information. These parameters are specified as
@device[keyword] and are available for the most recent point computed or, if specified in
a .save statement, for an entire simulation as a normal output vector. Thus, to monitor the
gate-to-source capacitance of a MOSFET, a command

save @m1[cgs]

given before a transient simulation causes the specified capacitance value to be saved at each
time-point.

General form:

.save all <@...>

@device_identifier.subcircuit_name.< subcircuit_name_nn >
+.device_name[parameter]

e.g.

save all @m. xmos1.xmos2.m1[vdsat]

from pyspice.

FabriceSalvaire avatar FabriceSalvaire commented on June 12, 2024

Simulation type are Ngspice version dependent

fixed in 09cb29c

from pyspice.

GProtoZeroW avatar GProtoZeroW commented on June 12, 2024

@FabriceSalvaire @eps82 so I am also needing the @ to access device parameters, particularly MOSFET level 8 (BSIM 3.3.). Also having used Virtuoso this what there "Calculator " is doing in the background. So getting this into PySpice would be very powerful

So first off I have looked at the Berkely docs and for a level, 8 gm is not explicitly listed. So how are things like the transconductance being calculated by NgSpice? In the following doc https://class.ee.washington.edu/cadta/hspice/chapter_15.pdf for gm, they are calculating it via definition as seen on page 18. While for Cgg the same doc has it calculating from BSIM eqs and also from a measurement of charge. So then are all these @ just doing the BSIM class or are they acutely taking a measure during the simulation.

That brings me to the second questions. If there @ are just being calculated from def should they just be integrated into the PySpice BaseElement classes? Or on the other hand, they are measuring simulated things such as charge during the simulation should then effort be made to add this to the simulation as @eps82 has done.

Sorry for the degradation into spice theory but it's not taught so had to ask the question.

from pyspice.

eps82 avatar eps82 commented on June 12, 2024

@GProtoZeroW Beware this is a frontend for ngspice and not the simulator itself, so questions about "internals" should really be addressed to ngspice's lists https://sourceforge.net/p/ngspice/mailman/

Regarding transistor parameters, some of these are explicit variables inside the models, some aren't (in which case they are computed by the simulator). For example the transconductance gm or the output conductance gds measure how the transistor, as a whole, behaves, instead of being simple internal parameters or direct functions of them.

For the second part, if you're doing too low level stuff it may be simpler to just take the raw data (on my own github I uploaded a version of the simplified library I'm using). It all boils down to whether you take advantage of the high level functions and it's worth adding some extras for your own stuff, or on the contrary it's better to go up from the basics building only what you need on top of it.

from pyspice.

GProtoZeroW avatar GProtoZeroW commented on June 12, 2024

@eps82 okay thanks for clearing some of that info. So first off as someone who has had to use Virtuoso without docs in school, and has had its simulator try to outsmart me. I want to have a viable means of telling these non to fab Spice systems to F-Off. And I also want to try leveraging other Python libs like say machine learning to as Boris Murmann put it "kill the spice Monkey ".

So @eps82 I will take a look at your work. But I think moving forward in terms of PySpice. Would be to identify some values that are being done by NgSpice and are independent of say the Berkley simulation for exsample, and get calls to that wrapped into PySpice Circuit.Simulation. For other stuff that is calculated from the model that is not as dynamic things like Cgg. Do some updates to the SpiceLibary parser function to extract the model parameters to a class attributes to the instance of the device in the circuit or even a dic. So that users can then call in those values dynamically without having to do text processing on a model file. And then add to the example how to do those calculations.

from pyspice.

eps82 avatar eps82 commented on June 12, 2024

Just to explain myself better, in case there’s any misunderstanding:

some of these are explicit variables inside the models, some aren't (in which case they are computed by the simulator)

I meant there are some (usually physical) parameters that are directly linked to the model equations, still functions of voltage/current (for example the threshold voltage), but this is different from gm or gds, which are small signal parameters that define the behaviour of the transistor (you can define the DC transconductance for any 2-port network regardless of physics), and this comes from a small signal analysis, not the model equations themselves. In both cases you need the simulator to calculate this stuff for you, but they’re slightly different in origin.

As for the rest, I don’t quite understand what you mean to do, but from personal experience, my first impulse when I started doing design was to despise netlist-based interfaces compared to ADS or Cadence Virtuoso. Over time however I realised there were many situations where I needed to get my hands dirty as graphical interfaces only take us so far, and some cases that are still doable from a GUI can actually be more convenient in text because of the freedom with which one can script simulations.

In this sense, ngspice having an interface as a shared library one can call from python is very helpful for many tasks even when having access to commercial/professional tools. But of course anything you do often enough is worth wrapping with higher level functions.

from pyspice.

FabriceSalvaire avatar FabriceSalvaire commented on June 12, 2024

done in 9cfbce

from pyspice.

GProtoZeroW avatar GProtoZeroW commented on June 12, 2024

@FabriceSalvaire how do I call the data from that
using the NMOS from http://www.ece.umd.edu/~newcomb/courses/spring2010/303/tsmc180nmcmos.lib file needs to be modified to LEVEL=8, VERSION=3.3

TestCir=Circuit('DCBench')
Vgs=TestCir.V('gs', 'gate', TestCir.gnd, 1.8@u_V)
Vbs=TestCir.V('bs', 'base', TestCir.gnd, 0@u_V)
Vds=TestCir.V('ds', 'drain', TestCir.gnd, 1.8@u_V)

TestCir.include(spice_library['TSMC180nmN'])

M0=TestCir.MOSFET('0', 'drain', 'gate', TestCir.gnd, 'base',
                          model='TSMC180nmN', length=200@u_nm, width=200@u_nm)
print(TestCir)

TempC=27
TestCirSim=TestCir.simulator(temperature=TempC, nominal_temperature=TempC)
TestCirSim.save('@M0[gm], @M0[id]')
TestCirSimData=TestCirSim.dc(Vgs=slice(0, 5, .01))

So now how do I exstract the @M0[gm] data to a np array. ?

from pyspice.

FabriceSalvaire avatar FabriceSalvaire commented on June 12, 2024

First you have to upgrade PySpice to the master version v1.2, see installation page:

pip install git+https://github.com/FabriceSalvaire/PySpice

from PySpice.Spice.Netlist import Circuit
from PySpice.Spice.Library import SpiceLibrary
from PySpice.Unit import *

####################################################################################################

import PySpice.Logging.Logging as Logging
logger = Logging.setup_logging()

####################################################################################################

spice_library = SpiceLibrary('.')

####################################################################################################

circuit = Circuit('DCBench')
Vgs = circuit.V('gs', 'gate', circuit.gnd, 1.8@u_V)
Vbs = circuit.V('bs', 'base', circuit.gnd, 0@u_V)
Vds = circuit.V('ds', 'drain', circuit.gnd, 1.8@u_V)

circuit.include(spice_library['TSMC180nmN'])

M0 = circuit.MOSFET('0', 'drain', 'gate', circuit.gnd, 'base',
                  model='TSMC180nmN', length=200@u_nm, width=200@u_nm)
print(circuit)

TempC = 27
simulator = circuit.simulator(temperature=TempC, nominal_temperature=TempC)
simulator.save_internal_parameters('@M0[gm]', '@M0[id]')
analysis = simulator.dc(Vgs=slice(0, 5, .01))

print(analysis['@M0[gm]'].str_data()[:100])
print(analysis['@M0[id]'].str_data()[:100])

from pyspice.

GProtoZeroW avatar GProtoZeroW commented on June 12, 2024

Can a subcircuits internal device parameter be accessed from the main circuit sim? Say monitoring the power of 'RP1' in the OpAmp ex https://pyspice.fabrice-salvaire.fr/examples/operational-amplifier/operational-amplifier.html . I have tried adding 'Xop' in various to '@rp1[p]' with no luck

from pyspice.

FabriceSalvaire avatar FabriceSalvaire commented on June 12, 2024

I believe we can do it, but check ngspice manual

from pyspice.

SahilJain122 avatar SahilJain122 commented on June 12, 2024

in what paths are these libraries searched?

from pyspice.

nataraj-pinakapani avatar nataraj-pinakapani commented on June 12, 2024

Can a subcircuits internal device parameter be accessed from the main circuit sim? Say monitoring the power of 'RP1' in the OpAmp ex https://pyspice.fabrice-salvaire.fr/examples/operational-amplifier/operational-amplifier.html . I have tried adding 'Xop' in various to '@rp1[p]' with no luck

The following code prints the current through the resistor R1 which is inside the subcircuit X1
import PySpice.Logging.Logging as Logging
logger = Logging.setup_logging()

from PySpice.Spice.Netlist import Circuit, SubCircuit, SubCircuitFactory
from PySpice.Unit import *
class ParallelResistor(SubCircuitFactory):
NAME = 'parallel_resistor'
NODES = ('n1', 'n2')
def init(self, R1=1@u_Ω, R2=2@u_Ω):
super().init()
self.R(1, 'n1', 'n2', R1)
self.R(2, 'n1', 'n2', R2)

circuit = Circuit('Test')
circuit.subcircuit(ParallelResistor(R2=3@u_Ω))
circuit.X('1', 'parallel_resistor', 1, circuit.gnd)
circuit.V('1', 1, circuit.gnd, 1)

print(circuit)

simulator = circuit.simulator(temperature=25, nominal_temperature=25)
simulator.save_internal_parameters('@v1[i]', '@R.X1.R1[i]')
analysis = simulator.dc(V1=slice(5,5,5))

print(analysis['@v1[i]'].str_data())
print(analysis['@R.X1.R1[i]'].str_data())

from pyspice.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.