nunobrum / spicelib

Python library to interact with spice simulators such as LTSpice, QSPICE, NGSpice and others.
GNU General Public License v3.0
34 stars 10 forks source link

Issue with encoding + subcircuit from a lib #94

Closed J-escandon closed 1 month ago

J-escandon commented 1 month ago

Hi. I have encountered two different issues while trying to simulate a circuit. For context, I am using the following:

I do have a .asc which I am trying to obtain the netlist by using netlist = AscEditor("PA98_power.asc") This always gives me an encoding issue: LookupError: unknown encoding: encoding

I have tried to override it by using the following: netlist = AscEditor("PA98_power.asc", encoding='utf-8') This seems to solve that issue. However in this case I get another error. Within the .asc I do have a component with its .asy whose model is located inside a .lib. I have no issues on simulating this directly on LTSpice. However, when generating the netlist, it aparantly looks for a .asc within the folder, which obviously does not find since its defined in the .lib, and outputs an error.

I have tried to reproduce this with some of the examples that you have. I have tried to run the TRAN.asc. However I get the exact same issue with the encoding. When I tried to set the encoding to 'utf-8' I got the following issue: 'utf-8' codec can't decode byte 0xb5 in position 530: invalid start byte Using 'cp1252' encoding seems to work, but once runningrunner.run_now(netlist=netlist) does not seem to do nothing.

hb020 commented 1 month ago

@J-escandon : What version of spicelib do you have?

The version in github throws no error on the TRAN.asc file during my tests. The pip version (1.2.1) is somewhat behind, but mostly regarding documentation. It should have no impact on this issue.

How I tested it:

In console/terminal, go to the directory where spicelib is installed

cd unittests
python test_spicelib.py

(that file runs a test on TRAN.asc) The first line on the console should say skip_ltspice_tests False and at the end, it should say something like

Ran 11 tests in 20.430s

OK

Older versions of spicelib had issues with encoding, so it may be that you have an old version.

J-escandon commented 1 month ago

Hi. I am indeed using the 1.2.1 installed through pip in a .venv.

I have now cloned the git repository and run the test_spicelib.py. I got the following:

Ran 11 tests in 11.337s
FAILED (errors=5)
======================================================================
ERROR: test_batch_test (__main__.test_spicelib.test_batch_test)
@note   inits class
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<mypath>\spicelib\unittests\test_spicelib.py", line 139, in test_batch_test
    log = LTSpiceLogReader(log_file)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<mypath>\spicelib\spicelib\log\ltsteps.py", line 303, in __init__
    self.encoding = detect_encoding(log_filename, "^(.*\n)?Circuit:")
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<mypath>\spicelib\spicelib\utils\detect_encoding.py", line 77, in detect_encoding
    raise EncodingDetectError(f"Expected pattern \"{expected_pattern}\" not found in file:{file_path}")
spicelib.utils.detect_encoding.EncodingDetectError: Expected pattern "^(.*
)?Circuit:" not found in file:output\no_callback.log

======================================================================
ERROR: test_fourier_log_read (__main__.test_spicelib.test_fourier_log_read)
Fourier Analysis Test
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<mypath>\spicelib\unittests\test_spicelib.py", line 524, in test_fourier_log_read
    log = LTSpiceLogReader(log_file)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<mypath>\spicelib\spicelib\log\ltsteps.py", line 303, in __init__
    self.encoding = detect_encoding(log_filename, "^(.*\n)?Circuit:")
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<mypath>\spicelib\spicelib\utils\detect_encoding.py", line 77, in detect_encoding
    raise EncodingDetectError(f"Expected pattern \"{expected_pattern}\" not found in file:{file_path}")
spicelib.utils.detect_encoding.EncodingDetectError: Expected pattern "^(.*
)?Circuit:" not found in file:..\examples\testfiles\temp\Fourier_30MHz_1.log

======================================================================
ERROR: test_ltsteps_measures (__main__.test_spicelib.test_ltsteps_measures)
LTSpiceLogReader Measures from Batch_Test.asc
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<mypath>\spicelib\unittests\test_spicelib.py", line 359, in test_ltsteps_measures
    log = LTSpiceLogReader(log_file)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<mypath>\spicelib\spicelib\log\ltsteps.py", line 303, in __init__
    self.encoding = detect_encoding(log_filename, "^(.*\n)?Circuit:")
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<mypath>\spicelib\spicelib\utils\detect_encoding.py", line 77, in detect_encoding
    raise EncodingDetectError(f"Expected pattern \"{expected_pattern}\" not found in file:{file_path}")
spicelib.utils.detect_encoding.EncodingDetectError: Expected pattern "^(.*
)?Circuit:" not found in file:..\examples\testfiles\temp\Batch_Test_1.log

======================================================================
ERROR: test_transient (__main__.test_spicelib.test_transient)
Transient Simulation test
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<mypath>\spicelib\unittests\test_spicelib.py", line 411, in test_transient
    log = LTSpiceLogReader(log_file)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<mypath>\spicelib\spicelib\log\ltsteps.py", line 303, in __init__
    self.encoding = detect_encoding(log_filename, "^(.*\n)?Circuit:")
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<mypath>\spicelib\spicelib\utils\detect_encoding.py", line 77, in detect_encoding
    raise EncodingDetectError(f"Expected pattern \"{expected_pattern}\" not found in file:{file_path}")
spicelib.utils.detect_encoding.EncodingDetectError: Expected pattern "^(.*
)?Circuit:" not found in file:..\examples\testfiles\temp\TRAN_1.log

======================================================================
ERROR: test_transient_steps (__main__.test_spicelib.test_transient_steps)
Transient simulation with stepped data.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<mypath>\spicelib\unittests\test_spicelib.py", line 433, in test_transient_steps
    log = LTSpiceLogReader(log_file)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<mypath>\spicelib\spicelib\log\ltsteps.py", line 303, in __init__
    self.encoding = detect_encoding(log_filename, "^(.*\n)?Circuit:")
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<mypath>\spicelib\spicelib\utils\detect_encoding.py", line 77, in detect_encoding
    raise EncodingDetectError(f"Expected pattern \"{expected_pattern}\" not found in file:{file_path}")
spicelib.utils.detect_encoding.EncodingDetectError: Expected pattern "^(.*
)?Circuit:" not found in file:..\examples\testfiles\temp\TRAN - STEP_1.log
hb020 commented 1 month ago

That indicates a problem with the simulator. Can you see what is written in those log files that are mentioned?

J-escandon commented 1 month ago

This is one of the .logs.

LTspice 24.0.12 for Windows
Start Time: Tue Sep 24 16:34:59 2024

   --- Expanded Deck Component Count ---
C's 1
R's 1
V's 1
tot: 3

    --- Expanded Netlist ---
* <mypath>\spicelib\examples\testfiles\temp\TRAN - STEP_1.asc
vin in 0 pwl(0 0 10n 1)
r1 in out 1000 
c1 out 0 1µ
.tran 5m
.end

solver = Normal
Maximum thread count: 20

bypass = 1
.OP point found by inspection.
.step vin=1 r1=1000

.step vin=10 r1=1000

.step vin=1 r1=10000
tnom = 27
temp = 27
method = modified trap
.step vin=10 r1=10000

Measurement: t1
  step  v(out)  at
     1  0.632016    0.001
     2  6.31901 0.001
     3  0.094948    0.001
     4  0.950013    0.001

Measurement: t2
  step  v(out)  at
     1  0.864411    0.002
     2  8.64432 0.002
     3  0.180818    0.002
     4  1.81244 0.002

Measurement: t3
  step  v(out)  at
     1  0.950097    0.003
     2  9.50098 0.003
     3  0.258697    0.003
     4  2.58607 0.003

Measurement: t4
  step  v(out)  at
     1  0.981639    0.004
     2  9.81665 0.004
     3  0.329238    0.004
     4  3.28877 0.004

Measurement: t5
  step  v(out)  at
     1  0.993262    0.005
     2  9.93262 0.005
     3  0.393469    0.005
     4  3.93469 0.005

Total elapsed time: 0.022 seconds.

Could it be that the first line does not start with that * but it does appear later at the expended netlist?

hb020 commented 1 month ago

aha, can you check what are your settings in ltspice? We've seen something like this before. You probably have "Generate Expanded Listing" activated. But spicelib should be compatible with that. Any other settings that are not default values?

Edit: Confirmed, "Generate Expanded Listing" still breaks simulation file interpretation. Will check why.

In the meantime, can you uncheck that option? It should work, unless there is another setting that breaks it.

hb020 commented 1 month ago

PR #95 prepared

J-escandon commented 1 month ago

Now I can indeed run python test_spicelib.py without any problem, however there was no change in the original issue that I had. First the encoding issue (apparently solved if I select a specific enconding), and the subcircuit not found.

hb020 commented 1 month ago

So you say that without "Generate Expanded Listing" (or on that new branch I made?), test_spiclelib.py works, but you still have an issue with your .asc file? Can you share that file?

J-escandon commented 1 month ago

Hi.

You can find an example of the file in here: https://www.apexanalog.com/products/pa98.html under the spice model.

I have done some modifications around the components (resistors and supplies) but the rest is quite the same, being the main element the operational PA98. Note that I changed the name of the PA98.asc for something different. Not sure if that would affect the searching for the subcircuit.

hb020 commented 1 month ago

The PA98.asc file is BOM less UTF-16 LE. Will look, thanks.

Edit:

@nunobrum : we should probably provide some protection against that. There are other cases like this. Examples: ADAQ7767-1.asy (points to a .sub) and LTC6605-14.asy (points to a .lib with another name)

Proposals: 1) if it is a BLOCK, and there is a model referenced, don't go searching for any extra files. I have the impression that a block can have multiple models. Supporting that risks being complicated (it probably should be handled in asyreader) and to what end... 2) if there can only be 1 model in a CELL or a BLOCK, turn AscEditor._get_subcircuit() around, and load the model if there is one, if not load the .asc.

nr 2 is probably better. And to be included in the unitests of course.

nunobrum commented 1 month ago

@nunobrum : we should probably provide some protection against that. There are other cases like this. Examples: ADAQ7767-1.asy (points to a .sub) and LTC6605-14.asy (points to a .lib with another name)

Proposals:

  1. if it is a BLOCK, and there is a model referenced, don't go searching for any extra files. I have the impression that a block can have multiple models. Supporting that risks being complicated (it probably should be handled in asyreader) and to what end...
  2. if there can only be 1 model in a CELL or a BLOCK, turn AscEditor._get_subcircuit() around, and load the model if there is one, if not load the .asc.

nr 2 is probably better. And to be included in the unitests of course.

Is there something else on the ASY that we can use ? I remember seeing some .ASY files that had a .lib statement. If this is always the case, maybe it is a better workaround.

hb020 commented 1 month ago

These are my findings, on this week's LTSpice libs:

The only differences found between CELL and BLOCK .asy files when they have Prefix X

Apart of that, there is no fundamental difference between CELL and BLOCK files when they have Prefix X

About .asy files with other Prefix types

Small errors that look like they are harmless but might throw off parsers

Conclusion:

hb020 commented 1 month ago

See branch cell-and-block-subcircuit-#94

hb020 commented 1 month ago

@J-escandon with the latest version from main (not yet available under pip), is all OK now?

J-escandon commented 1 month ago

It seems to work now