1 //----------------------------------------------------------------------------- 
   2 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   3 // at your option, any later version. See the LICENSE.txt file for the text of 
   5 //----------------------------------------------------------------------------- 
   6 // Compression tool for FPGA config files. Compress several *.bit files at 
   7 // compile time. Decompression is done at run time (see fpgaloader.c). 
   8 // This uses the zlib library tuned to this specific case. The small file sizes 
   9 // allow to use "insane" parameters for optimum compression ratio. 
  10 //----------------------------------------------------------------------------- 
  19 #define MAX(a,b) ((a)>(b)?(a):(b)) 
  22 #define COMPRESS_LEVEL           9  // use best possible compression 
  23 #define COMPRESS_WINDOW_BITS    15  // default = max = 15 for a window of 2^15 = 32KBytes 
  24 #define COMPRESS_MEM_LEVEL       9  // determines the amount of memory allocated during compression. Default = 8. 
  25 /* COMPRESS_STRATEGY can be  
  26         Z_DEFAULT_STRATEGY (the default),  
  27         Z_FILTERED (more huffmann, less string matching), 
  28         Z_HUFFMAN_ONLY (huffman only, no string matching) 
  29         Z_RLE (distances limited to one) 
  30         Z_FIXED (prevents the use of dynamic Huffman codes) 
  33 #define COMPRESS_STRATEGY       Z_DEFAULT_STRATEGY 
  34 // zlib tuning parameters: 
  35 #define COMPRESS_GOOD_LENGTH           258 
  36 #define COMPRESS_MAX_LAZY              258 
  37 #define COMPRESS_MAX_NICE_LENGTH       258 
  38 #define COMPRESS_MAX_CHAIN            8192 
  40 #define FPGA_INTERLEAVE_SIZE           288  // (the FPGA's internal config frame size is 288 bits. Interleaving with 288 bytes should give best compression) 
  41 #define FPGA_CONFIG_SIZE            42336L  // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE 
  42 #define HARDNESTED_TABLE_SIZE           (sizeof(uint32_t) * ((1L<<19)+1)) 
  44 static void usage(void) 
  46         fprintf(stdout
, "Usage: fpga_compress <infile1> <infile2> ... <infile_n> <outfile>\n"); 
  47         fprintf(stdout
, "          Combine n FPGA bitstream files and compress them into one.\n\n"); 
  48         fprintf(stdout
, "       fpga_compress -d <infile> <outfile>"); 
  49         fprintf(stdout
, "          Decompress <infile>. Write result to <outfile>"); 
  50         fprintf(stdout
, "       fpga_compress -t <infile> <outfile>"); 
  51         fprintf(stdout
, "          Compress hardnested table <infile>. Write result to <outfile>"); 
  55 static voidpf 
fpga_deflate_malloc(voidpf opaque
, uInt items
, uInt size
) 
  57         return malloc(items
*size
); 
  61 static void fpga_deflate_free(voidpf opaque
, voidpf address
) 
  67 static bool all_feof(FILE *infile
[], uint8_t num_infiles
) 
  69         for (uint16_t i 
= 0; i 
< num_infiles
; i
++) { 
  70                 if (!feof(infile
[i
])) { 
  79 int zlib_compress(FILE *infile
[], uint8_t num_infiles
, FILE *outfile
, bool hardnested_mode
) 
  85         z_stream compressed_fpga_stream
; 
  87         if (hardnested_mode
) { 
  88                 fpga_config 
= malloc(num_infiles 
* HARDNESTED_TABLE_SIZE
); 
  90                 fpga_config 
= malloc(num_infiles 
* FPGA_CONFIG_SIZE
); 
  92         // read the input files. Interleave them into fpga_config[] 
  96                 if (i 
>= num_infiles 
* (hardnested_mode
?HARDNESTED_TABLE_SIZE
:FPGA_CONFIG_SIZE
)) { 
  97                         if (hardnested_mode
) { 
  98                                 fprintf(stderr
, "Input file too big (> %lu bytes). This is probably not a hardnested bitflip state table.\n", HARDNESTED_TABLE_SIZE
); 
 100                                 fprintf(stderr
, "Input files too big (total > %lu bytes). These are probably not PM3 FPGA config files.\n", num_infiles
*FPGA_CONFIG_SIZE
); 
 102                         for(uint16_t j 
= 0; j 
< num_infiles
; j
++) { 
 106                         return(EXIT_FAILURE
); 
 109                 for(uint16_t j 
= 0; j 
< num_infiles
; j
++) { 
 110                         for(uint16_t k 
= 0; k 
< FPGA_INTERLEAVE_SIZE
; k
++) { 
 111                                 c 
= fgetc(infile
[j
]); 
 112                                 if (!feof(infile
[j
])) { 
 113                                         fpga_config
[i
++] = c
; 
 114                                 } else if (num_infiles 
> 1) { 
 115                                         fpga_config
[i
++] = '\0'; 
 120         } while (!all_feof(infile
, num_infiles
)); 
 122         // initialize zlib structures 
 123         compressed_fpga_stream
.next_in 
= fpga_config
; 
 124         compressed_fpga_stream
.avail_in 
= i
; 
 125         compressed_fpga_stream
.zalloc 
= fpga_deflate_malloc
; 
 126         compressed_fpga_stream
.zfree 
= fpga_deflate_free
; 
 127         compressed_fpga_stream
.opaque 
= Z_NULL
; 
 128         ret 
= deflateInit2(&compressed_fpga_stream
,  
 131                                                 COMPRESS_WINDOW_BITS
, 
 135         // estimate the size of the compressed output 
 136         uint32_t outsize_max 
= deflateBound(&compressed_fpga_stream
, compressed_fpga_stream
.avail_in
); 
 137         uint8_t *outbuf 
= malloc(outsize_max
); 
 138         compressed_fpga_stream
.next_out 
= outbuf
; 
 139         compressed_fpga_stream
.avail_out 
= outsize_max
; 
 142                 ret 
= deflateTune(&compressed_fpga_stream
, 
 143                                                         COMPRESS_GOOD_LENGTH
, 
 145                                                         COMPRESS_MAX_NICE_LENGTH
, 
 150                 ret 
= deflate(&compressed_fpga_stream
, Z_FINISH
); 
 153         fprintf(stdout
, "compressed %u input bytes to %lu output bytes\n", i
, compressed_fpga_stream
.total_out
); 
 155         if (ret 
!= Z_STREAM_END
) { 
 156                 fprintf(stderr
, "Error in deflate(): %i %s\n", ret
, compressed_fpga_stream
.msg
); 
 158                 deflateEnd(&compressed_fpga_stream
); 
 159                 for(uint16_t j 
= 0; j 
< num_infiles
; j
++) { 
 165                 return(EXIT_FAILURE
); 
 168         for (i 
= 0; i 
< compressed_fpga_stream
.total_out
; i
++) { 
 169                 fputc(outbuf
[i
], outfile
); 
 173         deflateEnd(&compressed_fpga_stream
); 
 174         for(uint16_t j 
= 0; j 
< num_infiles
; j
++) { 
 181         return(EXIT_SUCCESS
); 
 186 int zlib_decompress(FILE *infile
, FILE *outfile
) 
 188         #define DECOMPRESS_BUF_SIZE 1024 
 189         uint8_t outbuf
[DECOMPRESS_BUF_SIZE
]; 
 190         uint8_t inbuf
[DECOMPRESS_BUF_SIZE
]; 
 193         z_stream compressed_fpga_stream
; 
 195         // initialize zlib structures 
 196         compressed_fpga_stream
.next_in 
= inbuf
; 
 197         compressed_fpga_stream
.avail_in 
= 0; 
 198         compressed_fpga_stream
.next_out 
= outbuf
; 
 199         compressed_fpga_stream
.avail_out 
= DECOMPRESS_BUF_SIZE
; 
 200         compressed_fpga_stream
.zalloc 
= fpga_deflate_malloc
; 
 201         compressed_fpga_stream
.zfree 
= fpga_deflate_free
; 
 202         compressed_fpga_stream
.opaque 
= Z_NULL
; 
 204         ret 
= inflateInit2(&compressed_fpga_stream
, 0); 
 207                 if (compressed_fpga_stream
.avail_in 
== 0) { 
 208                         compressed_fpga_stream
.next_in 
= inbuf
; 
 211                                 int32_t c 
= fgetc(infile
); 
 213                                         inbuf
[i
++] = c 
& 0xFF; 
 214                                         compressed_fpga_stream
.avail_in
++; 
 218                         } while (i 
< DECOMPRESS_BUF_SIZE
); 
 221                 ret 
= inflate(&compressed_fpga_stream
, Z_SYNC_FLUSH
); 
 223                 if (ret 
!= Z_OK 
&& ret 
!= Z_STREAM_END
) { 
 227                 if (compressed_fpga_stream
.avail_out 
== 0) { 
 228                         for (uint16_t i 
= 0; i 
< DECOMPRESS_BUF_SIZE
; i
++) { 
 229                                 fputc(outbuf
[i
], outfile
); 
 231                         compressed_fpga_stream
.avail_out 
= DECOMPRESS_BUF_SIZE
; 
 232                         compressed_fpga_stream
.next_out 
= outbuf
; 
 234         } while (ret 
== Z_OK
); 
 236         if (ret 
== Z_STREAM_END
) {  // reached end of input 
 238                 while (compressed_fpga_stream
.avail_out 
< DECOMPRESS_BUF_SIZE
) { 
 239                         fputc(outbuf
[i
++], outfile
); 
 240                         compressed_fpga_stream
.avail_out
++; 
 244                 return(EXIT_SUCCESS
); 
 246                 fprintf(stderr
, "Error. Inflate() returned error %i, %s", ret
, compressed_fpga_stream
.msg
); 
 249                 return(EXIT_FAILURE
); 
 255 int main(int argc
, char **argv
) 
 260         if (argc 
== 1 || argc 
== 2) { 
 262                 return(EXIT_FAILURE
); 
 265         if (!strcmp(argv
[1], "-d")) { // Decompress 
 267                 infiles 
= calloc(1, sizeof(FILE*)); 
 270                         return(EXIT_FAILURE
); 
 272                 infiles
[0] = fopen(argv
[2], "rb"); 
 273                 if (infiles
[0] == NULL
) { 
 274                         fprintf(stderr
, "Error. Cannot open input file %s", argv
[2]); 
 275                         return(EXIT_FAILURE
); 
 277                 outfile 
= fopen(argv
[3], "wb"); 
 278                 if (outfile 
== NULL
) { 
 279                         fprintf(stderr
, "Error. Cannot open output file %s", argv
[3]); 
 280                         return(EXIT_FAILURE
); 
 282                 return zlib_decompress(infiles
[0], outfile
); 
 286                 bool hardnested_mode 
= false; 
 287                 int num_input_files 
= 0; 
 288                 if (!strcmp(argv
[1], "-t")) { // hardnested table 
 291                                 return(EXIT_FAILURE
); 
 293                         hardnested_mode 
= true; 
 296                         num_input_files 
= argc
-2; 
 298                 infiles 
= calloc(num_input_files
, sizeof(FILE*)); 
 299                 for (uint16_t i 
= 0; i 
< num_input_files
; i
++) {  
 300                         infiles
[i
] = fopen(argv
[i
+hardnested_mode
?2:1], "rb"); 
 301                         if (infiles
[i
] == NULL
) { 
 302                                 fprintf(stderr
, "Error. Cannot open input file %s", argv
[i
+hardnested_mode
?2:1]); 
 303                                 return(EXIT_FAILURE
); 
 306                 outfile 
= fopen(argv
[argc
-1], "wb"); 
 307                 if (outfile 
== NULL
) { 
 308                         fprintf(stderr
, "Error. Cannot open output file %s", argv
[argc
-1]); 
 309                         return(EXIT_FAILURE
); 
 311                 return zlib_compress(infiles
, num_input_files
, outfile
, hardnested_mode
);