ma-laforge / SpiceData.jl

A pure-Julia SPICE data file reader
https://ma-laforge.github.io/info/edatools
MIT License
5 stars 2 forks source link

Question: ngspice compatibility #2

Open ThomasChaffey opened 4 years ago

ThomasChaffey commented 4 years ago

Please excuse how basic this question is - I had a hunt, and I figured it was just quickest to ask.

Can I use this tool to read data saved from ngspice? The user manual (page 366 of http://ngspice.sourceforge.net/docs/ngspice-manual.pdf) calls the binary format Spice3f5. Just plugging it into SpiceData doesn't work (the test file test.tr0 works though).

I'd be happy to work on the implementation myself if you think it is worthwhile and not a huge extension.

ma-laforge commented 4 years ago

Hi Thomas,

Looking at the docs, can't really tell if this module supports data from ngspice.

Have you checked??

The manual seems to indicate the default save format of wrdata [file] [vecs] is text, whereas that of write [file] [expr] is binary.

SpiceData.jl only supports binary. I don't think I want it to support ASCII format anyways, because it is an inefficient format (unless maybe some program only has text output -- though I probably can be swayed here, especially if I have downtime).

So my question: Have you checked that you actually generated binary data files with ngspice?

FYI: I do want to support the ngspice format

But I would like to maintain a MIT licence on things, so I can't just port any code. The best thing would be to get a spec detailing the file format so that I can respect the license.

(Though I'm willing to change my own style if you figured out a super-awesome better way to write your code :) ).

What I do know

This SPICE reader expects a header of some sorts, whereas the ngspice manual seems to imply it just starts dumping out data. I'm not sure if this is an indication that SpiceData.jl can't read the Spice3f5 format, or if it just means the manual doesn't go into specific details of the file format.

In the meantime

If that takes too long, it seems like you can write out ASCII files for now. It should be fairly easy to build a Julia reader for that.

ThomasChaffey commented 4 years ago

rawspice.txt

Thanks for the detailed response!

As you say, ngspice can output ASCII files, and it is straightforward to read them into Julia. For what I wanted to do yesterday, that worked totally fine.

It would be cool to extend your package to work with ngspice though, as it is functionality that I'm likely to use in the future every now and again. I'm very short on time right at the moment, but I'd be happy to work on this myself when I've got a bit more time.

I did check that the file from ngspice is a binary format. See the attached file for a sample.

I had a look at the file in hexdump, and compared it to the test.tr0 file from your other project. The ngspice header doesn't have any version information (it begins with "Title: ...") and seems to be in quite a different format. For example, the signal names are in a tab delimited list, rather than each on one line. The end of the header is marked by a line of nulls. I assume the data is in the same format, but haven't verified.

I had a quick skim through your code too. It looks like it should be possible to write a new function to unpack an ngspice header using your existing utility functions. I'll look at this in more detail in the next couple of days! The question of how to detect the ngspice format remains though - it seems non-robust to simply assume the ngspice format if there is no version information. Perhaps an optional format argument to SpiceData._open?

(edit: rawspice.txt added, extension changed from the default .raw to allow upload).

ma-laforge commented 4 years ago

Sounds good. Agreed: It looks like the headers are different, and so the formats must be a bit different somehow.

SPICE3f5

I checked: Apparently SPICE3f comes from Berkely (http://bwrcs.eecs.berkeley.edu/Classes/IcBook/SPICE/). So it is likely the SPICE3f5 format probably originated there.

_open()

Actually, I think there is no (initial) reason to add an argument to _open. Instead, I suggest you pick a name like:

Please don't use "ngspice" in the name, because the format seems to be associated with Berkely SPICE3f.

To keep things more uniform:

FYI:

Your reader

Please don't try to mash your functionality with the current reader (don't use struct DataReader ). It can cause headaches down the road with code complexity. (Yes, I realize these readers are relatively simple, but still). Instead, you can make your own reader. Maybe use a name like:

mutable struct Spice3f5Reader
...
end

I'll rename my own reader later on for the sake of uniformity (unless you really want to do it).

NOTE: You MAY be able to sway me to re-use the DataReader structures if the two formats are REALLY that similar. But I typically find that causes code to be less readable/harder to maintain. We already know the header format is different, so that already adds an if format==:spice3f5 -> do something else. I find adding if cases much less desirable than just having two reader types, and building them from common read functions (when possible/appropriate).

Also note that we might eventually want to create an abstract type to get common functionality in both readers:

abstract type AbstractSPICEReader

mutable struct Spice3f5Reader <: AbstractSPICEReader
...
end

But I don't really think we need that right now - not unless it gets you to re-use some of my original algorithms in a clean fashion.

ma-laforge commented 4 years ago

By the way: Are you using ngspice through Qucs? I've tried it a little a few years ago, and it seemed nice.

ma-laforge commented 4 years ago

I hope that didn't sound too harsh

To a first order, what I want is to:

But if you have a different style to implement your algorithm, that's fine. You don't even need to use the Spice3f5Reader concept at all. That was just a suggestion for you because I, myself noticed that using an object to maintain state while reading works out really well.

As long as the bulk of your code is kept in a separate file (or maybe more), and you just add stuff required to link it with the rest, that should be ok.

I have already run through the idea of _open() being required to open different file types/readers, and I found it best to make a file/reader-sepecific open_myfileformat() function. Building a common _open() function can be messy, so I'd rather keep it for later (a higher-level interface for the user).

...Again that's unless you found a super-elegant solution to writing _open() with the proposed optional argument, or if having that common function call would make your calling code significantly easier to write.

ThomasChaffey commented 4 years ago

Hi, sorry for getting back to this so slowly. It didn't sound too harsh at all, very reasonable. I agree that simplicity and cleanliness are worth striving for. I like the idea of keeping all the 3f5 format stuff basically separate, and just using the same core functions.

I've been bogged down with work, but I might get a chance to look at this over the weekend.

I actually just use ngspice alone through the terminal, and write my netlists by hand, often with a pen-and-paper schematic. Seems crazy, I know, but I'm only ever simulating very simple circuits.