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) 
  32 #define COMPRESS_STRATEGY               Z_DEFAULT_STRATEGY 
  33 // zlib tuning parameters: 
  34 #define COMPRESS_GOOD_LENGTH            258 
  35 #define COMPRESS_MAX_LAZY                       258      
  36 #define COMPRESS_MAX_NICE_LENGTH        258 
  37 #define COMPRESS_MAX_CHAIN                      8192 
  39 #define FPGA_INTERLEAVE_SIZE    288     // (the FPGA's internal config frame size is 288 bits. Interleaving with 288 bytes should give best compression) 
  40 #define FPGA_CONFIG_SIZE                42336   // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE 
  42 static void usage(void) 
  44         fprintf(stderr
, "Usage: fpga_compress <infile1> <infile2> ... <infile_n> <outfile>\n"); 
  45         fprintf(stderr
, "          Combine n FPGA bitstream files and compress them into one.\n\n"); 
  46         fprintf(stderr
, "       fpga_compress -d <infile> <outfile>"); 
  47         fprintf(stderr
, "          Decompress <infile>. Write result to <outfile>"); 
  51 static voidpf 
fpga_deflate_malloc(voidpf opaque
, uInt items
, uInt size
) 
  53         return malloc(items
*size
); 
  57 static void fpga_deflate_free(voidpf opaque
, voidpf address
) 
  63 static bool all_feof(FILE *infile
[], uint8_t num_infiles
) 
  65         for (uint16_t i 
= 0; i 
< num_infiles
; i
++) { 
  66                 if (!feof(infile
[i
])) { 
  75 int zlib_compress(FILE *infile
[], uint8_t num_infiles
, FILE *outfile
) 
  81         z_stream compressed_fpga_stream
; 
  83         fpga_config 
= malloc(num_infiles 
* FPGA_CONFIG_SIZE
); 
  85         // read the input files. Interleave them into fpga_config[] 
  89                 if (i 
>= num_infiles 
* FPGA_CONFIG_SIZE
) { 
  90                         fprintf(stderr
, "Input files too big (total > %lu bytes). These are probably not PM3 FPGA config files.\n", num_infiles
*FPGA_CONFIG_SIZE
); 
  91                         for(uint16_t j 
= 0; j 
< num_infiles
; j
++) { 
  98                 for(uint16_t j 
= 0; j 
< num_infiles
; j
++) { 
  99                         for(uint16_t k 
= 0; k 
< FPGA_INTERLEAVE_SIZE
; k
++) { 
 100                                 c 
= fgetc(infile
[j
]); 
 101                                 if (!feof(infile
[j
])) { 
 102                                         fpga_config
[i
++] = c
; 
 103                                 } else if (num_infiles 
> 1) { 
 104                                         fpga_config
[i
++] = '\0'; 
 109         } while (!all_feof(infile
, num_infiles
)); 
 111         // initialize zlib structures 
 112         compressed_fpga_stream
.next_in 
= fpga_config
; 
 113         compressed_fpga_stream
.avail_in 
= i
; 
 114         compressed_fpga_stream
.zalloc 
= fpga_deflate_malloc
; 
 115         compressed_fpga_stream
.zfree 
= fpga_deflate_free
; 
 116         compressed_fpga_stream
.opaque 
= Z_NULL
; 
 117         ret 
= deflateInit2(&compressed_fpga_stream
,  
 120                                                 COMPRESS_WINDOW_BITS
, 
 124         // estimate the size of the compressed output 
 125         unsigned int outsize_max 
= deflateBound(&compressed_fpga_stream
, compressed_fpga_stream
.avail_in
); 
 126         uint8_t *outbuf 
= malloc(outsize_max
); 
 127         compressed_fpga_stream
.next_out 
= outbuf
; 
 128         compressed_fpga_stream
.avail_out 
= outsize_max
; 
 131                 ret 
= deflateTune(&compressed_fpga_stream
, 
 132                                                         COMPRESS_GOOD_LENGTH
, 
 134                                                         COMPRESS_MAX_NICE_LENGTH
, 
 139                 ret 
= deflate(&compressed_fpga_stream
, Z_FINISH
); 
 142         fprintf(stderr
, "compressed %lu input bytes to %lu output bytes\n", i
, compressed_fpga_stream
.total_out
); 
 144         if (ret 
!= Z_STREAM_END
) { 
 145                 fprintf(stderr
, "Error in deflate(): %d %s\n", ret
, compressed_fpga_stream
.msg
); 
 147                 deflateEnd(&compressed_fpga_stream
); 
 148                 for(uint16_t j 
= 0; j 
< num_infiles
; j
++) { 
 154                 return(EXIT_FAILURE
); 
 157         for (i 
= 0; i 
< compressed_fpga_stream
.total_out
; i
++) { 
 158                 fputc(outbuf
[i
], outfile
); 
 162         deflateEnd(&compressed_fpga_stream
); 
 163         for(uint16_t j 
= 0; j 
< num_infiles
; j
++) { 
 170         return(EXIT_SUCCESS
); 
 175 int zlib_decompress(FILE *infile
, FILE *outfile
) 
 177         #define DECOMPRESS_BUF_SIZE 1024 
 178         uint8_t outbuf
[DECOMPRESS_BUF_SIZE
]; 
 179         uint8_t inbuf
[DECOMPRESS_BUF_SIZE
]; 
 182         z_stream compressed_fpga_stream
; 
 184         // initialize zlib structures 
 185         compressed_fpga_stream
.next_in 
= inbuf
; 
 186         compressed_fpga_stream
.avail_in 
= 0; 
 187         compressed_fpga_stream
.next_out 
= outbuf
; 
 188         compressed_fpga_stream
.avail_out 
= DECOMPRESS_BUF_SIZE
; 
 189         compressed_fpga_stream
.zalloc 
= fpga_deflate_malloc
; 
 190         compressed_fpga_stream
.zfree 
= fpga_deflate_free
; 
 191         compressed_fpga_stream
.opaque 
= Z_NULL
; 
 193         ret 
= inflateInit2(&compressed_fpga_stream
, 0); 
 196                 if (compressed_fpga_stream
.avail_in 
== 0) { 
 197                         compressed_fpga_stream
.next_in 
= inbuf
; 
 200                                 int c 
= fgetc(infile
); 
 202                                         inbuf
[i
++] = c 
& 0xFF; 
 203                                         compressed_fpga_stream
.avail_in
++; 
 207                         } while (i 
< DECOMPRESS_BUF_SIZE
); 
 210                 ret 
= inflate(&compressed_fpga_stream
, Z_SYNC_FLUSH
); 
 212                 if (ret 
!= Z_OK 
&& ret 
!= Z_STREAM_END
) { 
 216                 if (compressed_fpga_stream
.avail_out 
== 0) { 
 217                         for (uint16_t i 
= 0; i 
< DECOMPRESS_BUF_SIZE
; i
++) { 
 218                                 fputc(outbuf
[i
], outfile
); 
 220                         compressed_fpga_stream
.avail_out 
= DECOMPRESS_BUF_SIZE
; 
 221                         compressed_fpga_stream
.next_out 
= outbuf
; 
 223         } while (ret 
== Z_OK
); 
 225         if (ret 
== Z_STREAM_END
) {  // reached end of input 
 227                 while (compressed_fpga_stream
.avail_out 
< DECOMPRESS_BUF_SIZE
) { 
 228                         fputc(outbuf
[i
++], outfile
); 
 229                         compressed_fpga_stream
.avail_out
++; 
 233                 return(EXIT_SUCCESS
); 
 235                 fprintf(stderr
, "Error. Inflate() returned error %d, %s", ret
, compressed_fpga_stream
.msg
); 
 238                 return(EXIT_FAILURE
); 
 244 int main(int argc
, char **argv
) 
 249         if (argc 
== 1 || argc 
== 2) { 
 251                 return(EXIT_FAILURE
); 
 254         if (!strcmp(argv
[1], "-d")) {                   // Decompress 
 255                 infiles 
= calloc(1, sizeof(FILE*)); 
 258                         return(EXIT_FAILURE
); 
 260                 infiles
[0] = fopen(argv
[2], "rb"); 
 261                 if (infiles
[0] == NULL
) { 
 262                         fprintf(stderr
, "Error. Cannot open input file %s", argv
[2]); 
 263                         return(EXIT_FAILURE
); 
 265                 outfile 
= fopen(argv
[3], "wb"); 
 266                 if (outfile 
== NULL
) { 
 267                         fprintf(stderr
, "Error. Cannot open output file %s", argv
[3]); 
 268                         return(EXIT_FAILURE
); 
 270                 return zlib_decompress(infiles
[0], outfile
); 
 274                 infiles 
= calloc(argc
-2, sizeof(FILE*)); 
 275                 for (uint16_t i 
= 0; i 
< argc
-2; i
++) {  
 276                         infiles
[i
] = fopen(argv
[i
+1], "rb"); 
 277                         if (infiles
[i
] == NULL
) { 
 278                                 fprintf(stderr
, "Error. Cannot open input file %s", argv
[i
+1]); 
 279                                 return(EXIT_FAILURE
); 
 282                 outfile 
= fopen(argv
[argc
-1], "wb"); 
 283                 if (outfile 
== NULL
) { 
 284                         fprintf(stderr
, "Error. Cannot open output file %s", argv
[argc
-1]); 
 285                         return(EXIT_FAILURE
); 
 287                 return zlib_compress(infiles
, argc
-2, outfile
);