Skip to content
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

on-the-fly decompression and spi-over-jtag #47

Open
emard opened this issue Sep 3, 2020 · 40 comments
Open

on-the-fly decompression and spi-over-jtag #47

emard opened this issue Sep 3, 2020 · 40 comments
Labels
enhancement New feature or request

Comments

@emard
Copy link
Contributor

emard commented Sep 3, 2020

HI!

I suggest gzip on-the-fly decompression to upload bitstreams.
Especially it's good for spi-over-jtag bitstreams database
each one from 2MB becomes only 3.3KB with gzip -9

@trabucayre
Copy link
Owner

Hi
It's not clear for me:

  • You propose to store spiOverJtag bridge in gzip format, uncompress this file before loading in RAM ? or
  • sending the gzip by spiOverJtag, uncompressing this one in the FPGA before writing the FLASH?

@emard
Copy link
Contributor Author

emard commented Sep 4, 2020 via email

@GbGp
Copy link
Contributor

GbGp commented Nov 26, 2020

Xilinx FPGAs already supports a compressed bitstream format that can be loaded with openFPGAloader as usual.
To enable this feature it should be sufficient to just set set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] constraint. Other than saving space this can make the flashing operation slightly faster.

@emard
Copy link
Contributor Author

emard commented Nov 26, 2020 via email

@trabucayre
Copy link
Owner

I'm agree with both proposition.
A small test with xilinx compression and/or gzip shows:

size compression
2192129 without xilinx compression
236791 with xilinx compression
3390 without xilinx compression + gzip -9
15910 with xilinx compression + gzip -9

Clearly gzip applied on non compressed file is smaller, but with both the flashing time is faster + file small
The question is to determine which library to use to be compatible with linux, macOS and windows.

For unix pipe, my problem is a bit different: I use file extension to determine file type (it's diffcult or impossible to determine by content itself), with this approach it's required to find a way to select correct bitstream parser without extension information

@emard
Copy link
Contributor Author

emard commented Nov 26, 2020 via email

@trabucayre
Copy link
Owner

It's true, sometime letting deduce behaviour automatically is not a good thing.
I think adding option to provides file format it's a good idea and the only solution to allows using unix pipe.

I will let nonetheless automatic detection for backward compatibility.

If someone can tell me an gzip library compatible with linux, windows and macOS ?

@emard
Copy link
Contributor Author

emard commented Nov 28, 2020 via email

@trabucayre trabucayre added the enhancement New feature or request label Nov 28, 2020
@trabucayre
Copy link
Owner

My problem is to be sure for all 3 platforms :-)
Currently the documentation to install under windows and macOS is missing, if at least I don't break everything that would be good :-)

@emard
Copy link
Contributor Author

emard commented Nov 28, 2020 via email

@trabucayre
Copy link
Owner

Sorry for delay.
In a first time I have used solution suggested by @GbGp to reduce bitstream size (and reduce load time): the artix50t bitstream is compressed, others are left unchanged to avoid noise by updating all of them
I'm currently doing some test to refactor some classes to be able to use stdin.
For file type as argument, again it's in pipe: this way is sometime required (for xilinx when using .bin file it's not possible to deduce if it's simple raw data or a bitstream).

@emard
Copy link
Contributor Author

emard commented Dec 9, 2020 via email

@trabucayre
Copy link
Owner

xc7a100 bitstream is already available. No ?

@emard
Copy link
Contributor Author

emard commented Dec 9, 2020 via email

@trabucayre
Copy link
Owner

Sorry for the long delay.
openFPGALoader has now --file-type to force format (instead of using file extension) and pipe support.
It's now possible to use cat or gzip | openFPGALoader [options] --file-type xxxx

Thanks

@emard
Copy link
Contributor Author

emard commented Feb 24, 2021 via email

@trabucayre
Copy link
Owner

Thanks for you feedback.
Yes I've take time to improve bitbanging speedup (I'm not sure if it's possible to increase more).

I will reread this issue and the other one to see if I have lost some improvements. And need to find a universal library to uncompress file on the fly

@emard
Copy link
Contributor Author

emard commented Feb 25, 2021 via email

@trabucayre
Copy link
Owner

The speed reported by openFPGALoader is internal speed (I have tested with a logic analyzer) to consume FIFO's content, this why it's used. But it's true, for the full bitstream transfer the communication and the small internal FIFO size, will reduce the real speed.

@inkdot7
Copy link
Contributor

inkdot7 commented Nov 15, 2021

This is from #132 by @trabucayre:

My worry about spiOverJtag directory size is primarly to the download/clone step. Xilinx bitstream, with compress option enabled, have an acceptable size, but intel/altera ones must have compress option disabled, and consequently have a size more important. Most globally, due the potential number of devices this directory may become awfully heavy.

Concerning decompression at install step vs on-the-fly decompression:

  • the first is the most simple. No openFPGALoader's internal modifications to do, but requires to have access to the correct tools (gunzip/xz) for all systems (possible for windows and mac ?)

  • the second only requires to have correct library (again windows/mac ?), no modification at install step but maybe increase programming time due to decompress step (it's maybe a wrong question, maybe impact is really small compared to spi flash transactions).

With the need to have access to the tools, I think it would be more convenient to a user especially on windows/mac if it has been compiled into the code using a library, rather than openFPGALoader having to find the executable at runtime.

Another alternative might be a small (~20 line) custom C compression/decompression using the basic Lempel-Ziv strategy. This could then be included directly in the openFPGALoader sources. Here is one example:

https://github.com/andyherbert/lz1

(There is no license statement however, but I guess the author could be contacted; @andyherbert.) I also tried to do an implementation just from the description given. Such an approach seems to be able to reach a few kB for the .bit files, and 50kB - 200kB for .rbf. This is not worse than a factor of 2 or 3 compared to .gz for the .rbf files.

@emard
Copy link
Contributor Author

emard commented Nov 15, 2021 via email

@trabucayre
Copy link
Owner

It's true, The best solution, in all case is to compress bitstream in the repository to reduce size and download/clone time.
Using a second repo dedicated to binary files may be a solution but without compression clone time will be the same as current solution, and it's maybe less user friendly since it's required to fetch submodule (but I keep this option in my mind).

When I've said "an external tool to uncompress file" it's not at runtime but at install time: all bitstream are compressed in repository and instead to simply copy files, bitstream are uncompressed to /usr/share/openFPGALoader.

To resume the two options (but maybe others solutions are possible. I'm, of course, open, to all advice):

  • bitstream are extracted are install time using external tool, openFPGALoader is not modified to add uncompress support. This option have no impact to time to write bitstream
  • bitstream are uncompressed at runtime using an external, or internal, library. This option may increase a bit global runtime (really? compared to the spi Flash protocol?) to write bitstream, but everything is known since the library become a required dependency.

First one has my favor (maybe I'm wrong) because it has no impact on runtime/speed.

Of course, it's possible to select one option and finally to move to another if, finally, it's not the best.

@emard
Copy link
Contributor Author

emard commented Nov 15, 2021 via email

@inkdot7
Copy link
Contributor

inkdot7 commented Nov 15, 2021

Runtime penalty for decompression would be very small. E.g. zcat of 233 kB .gz file containing all the .bin and .rbf files (to 31 MB) takes 0.14 s on a fairly old AMD Athlon. That would be ~230 MB/s.

Programming my EP4CE15 with 511 kB takes 1.2 s, i.e. 0.42 MB/s.

@trabucayre
Copy link
Owner

Programming time depends, partially, to the probe: arty @30mhz takes 0,735s. I think having one .gz by bitstream is more easy and well VCS compliant (this avoid to update all the time one file, but just add new one).
Anyway, I think I must try both solutions (and maybe add them: one as primary solution, second as backup).
But before, I must find which library is linux/windows/mac/BSD compatible. Or as mentionned previously using an internal library but this one needs to be maintained (maybe as an early solution).

@inkdot7
Copy link
Contributor

inkdot7 commented Nov 17, 2021

I did not want to suggest to put all bitstreams in one compressed file. That was only to test the decompression speed.

@trabucayre
Copy link
Owner

Okay! Sorry to my misunderstood.
And thanks for your tests!

@emard
Copy link
Contributor Author

emard commented Nov 17, 2021 via email

@trabucayre
Copy link
Owner

Will check/test both.
Maybe @jeanthom, @kost and @umarcor are able to point some multiplatform libraries to test.
Thanks

@kost
Copy link
Contributor

kost commented Nov 19, 2021

I would say there are 3 ways:

  1. standard zlib
  2. using minimalistic single source file decompression and include it with openFPGAloder: one of my favourites is miniz: https://github.com/richgel999/miniz (make sure to use release version, not from github master/main branch)
  3. using modern library like https://github.com/zlib-ng/zlib-ng

To be honest, i would prefer option 2) since it is quite straightforward and not pain for user to use and build from the source on any platform.
Second best option is standard zlib (option 1). Using anything else on Linux/Mac/Unix systems other than libz could be problematic for end user since most of them already have that default lib. Windows have to install any lib to build anyway.
I would choose 3) only if performance is critical and project is heavily dependant on compression/decompression.

Hope it helps!

@umarcor
Copy link
Contributor

umarcor commented Nov 19, 2021

I would go with good old zlib. That is already used in several projects, such as GHDL, GTKWave, Yosys... all of which are known to work on GNU/Linux, Windows and macOS. Actually, the difference between vcd and vcdgz is the same discussion you are having here, but applied to waveforms instead of bitstreams.

@jeanthom
Copy link
Contributor

I don't have any experience with gzip libraries, but regarding packaging concerns on macOS both zlib and zlib-ng are well supported.

@trabucayre
Copy link
Owner

Thanks to all!
If zlib is the most available/multiplatform I will use it.

@trabucayre
Copy link
Owner

I have added the code to decompress gz files (works on linux, building for mingw is okay too).
Currently:

  • no bitstream are compressed (it's easy to compress manually for validation), but new bitstreams will in this format
  • it's limited to intel/altera (these bitstreams can't be internally compressed), for xilinx I don't know if it's required since these are already compressed by the tool.
  • a fallback is present: if .gz file is not found openFPGALoader will search for same file withouth .gz extension

macOS support has to be updated accordingly (currently hid and zlib aren't supported)

Thanks all!

@emard
Copy link
Contributor Author

emard commented Nov 25, 2021 via email

@trabucayre
Copy link
Owner

In fact it's not really limited to spiOverJtag with altera:

openFPGALoader -b ulx3s bitstream.bit.gz --file-type bit

do the job.
Have to modify the file type detection to check if extension is gzip or gz and to take into account second extension

@emard
Copy link
Contributor Author

emard commented Nov 25, 2021 via email

@trabucayre
Copy link
Owner

it's fixed on master branch. Now gz extension is detected, real type too.
I think I need to simplify a bit. This detection is done twice: in device.cpp and in configBitstreamParser.

@emard
Copy link
Contributor Author

emard commented Nov 26, 2021 via email

@trabucayre
Copy link
Owner

Great to know that!
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

7 participants