blob: 0e2503657d509bca142b139569f3119cf2242b92 [file] [log] [blame]
Tim Hall79d07d22020-04-27 18:20:16 +01001/*
Rickard Bolin899500d2023-02-10 11:55:41 +00002 * SPDX-FileCopyrightText: Copyright 2020, 2022 Arm Limited and/or its affiliates <open-source-office@arm.com>
Tim Hall79d07d22020-04-27 18:20:16 +01003 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <stdint.h>
22#include <stdbool.h>
23#include <string.h>
24#include <assert.h>
25#include <math.h>
26#include <getopt.h>
27#include <stdarg.h>
28#include "mlw_encode.h"
29#include "mlw_decode.h"
30
Fredrik Svedbergdb947e42022-11-22 15:47:24 +010031#define UNCHECKED(call) (void)call
32
Tim Hall79d07d22020-04-27 18:20:16 +010033static void fatal_error(const char *format, ...) {
34 va_list ap;
35 va_start (ap, format);
36 vfprintf(stderr, format, ap);
37 va_end(ap);
38 exit(1);
39}
40
41static void print_usage(void) {
42 printf("Usage:\n");
43 printf(" Encode: ./mlw_codec [<options>] [-o <outfile.mlw>] infiles.bin\n");
44 printf(" Decode: ./mlw_codec [<options>] -d [-o <outfile.bin>] infiles.mlw\n");
45 printf("\n");
46 printf("Options:\n");
47 printf(" -w The uncompressed weight file is an int16_t (word) stream.\n");
48 printf(" This is to support 9bit signed weights. Little endian is assuemd.\n");
49 printf(" The default format is int8_t (byte) stream (if -w is not specified)\n");
50 printf("\n");
51}
52
53// Read file into allocated buffer. Return length in bytes.
Fredrik Svedbergdb947e42022-11-22 15:47:24 +010054static size_t read_file( FILE *f, uint8_t **buf) {
55 size_t rsize = 0;
56 UNCHECKED(fseek(f, 0, SEEK_END));
57 long size = ftell(f);
58 size = size < 0 ? 0 : size;
59 UNCHECKED(fseek(f, 0, SEEK_SET));
Tim Hall79d07d22020-04-27 18:20:16 +010060 *buf = malloc(size);
Fredrik Svedbergdb947e42022-11-22 15:47:24 +010061 if (*buf)
62 {
63 rsize = fread(*buf, 1, size, f);
64 assert(rsize==size);
65 }
66 UNCHECKED(fclose(f));
67 return rsize;
Tim Hall79d07d22020-04-27 18:20:16 +010068}
69
70
71#define MAX_INFILES 1000
72
73int main(int argc, char *argv[])
74{
75 int c, decode=0, inbuf_size, outbuf_size;
76 char *infile_name[MAX_INFILES], *outfile_name=0;
77 uint8_t *inbuf=0, *outbuf=0;
78 FILE *infile, *outfile=0;
79 int verbose=0, infile_idx=0;
80 int int16_format=0;
81
82 if (argc==1) {
83 print_usage();
84 exit(1);
85 }
86
87 // Parse command line options
88 while( optind < argc) {
89 // Parse options
90 while ((c = getopt (argc, argv, "di:o:v:w?")) != -1) {
91 switch (c) {
92 case 'd':
93 decode=1;
94 break;
95 case 'i':
96 assert(infile_idx<MAX_INFILES);
97 infile_name[infile_idx++]=optarg;
98 break;
99 case 'o':
100 outfile_name=optarg;
101 break;
102 case 'v':
103 verbose=atoi(optarg);
104 break;
105 case 'w':
106 int16_format=1;
107 break;
108 case '?':
109 print_usage();
110 exit(0);
111 }
112 }
113
114 if (optind<argc) {
115 assert(infile_idx<MAX_INFILES);
116 infile_name[infile_idx++]=argv[optind];
117 optind++;
118
119 }
120 }
121
122 if (outfile_name) {
123 outfile=fopen(outfile_name, "wb");
124 if (!outfile)
125 fatal_error("ERROR: cannot open outfile %s\n", outfile_name);
126 }
127
128 // Loop over input files
129 int nbr_of_infiles=infile_idx;
130 for(infile_idx=0; infile_idx<nbr_of_infiles; infile_idx++) {
131 infile=fopen(infile_name[infile_idx], "rb");
132 if (!infile)
133 fatal_error("ERROR: cannot open infile %s\n", infile_name[infile_idx]);
134
135 // Read infile to buffer
136 inbuf_size = read_file(infile, &inbuf);
137
138 if (!decode) {
139 // Encode
Michael McGeaghd5cf7652020-12-03 13:53:56 +0000140 int i, n = int16_format ? inbuf_size/(int)sizeof(int16_t) : inbuf_size;
Tim Hall79d07d22020-04-27 18:20:16 +0100141 int16_t *weights = malloc( n * sizeof(int16_t) );
142 for(i=0; i<n; i++) {
143 weights[i] = int16_format ? ((int16_t*)inbuf)[i] : ((int8_t*)inbuf)[i];
144 }
145 outbuf_size = mlw_encode( weights, n, &outbuf, verbose);
146 free(weights);
147 printf("Input size %d output size %d bpw %4.2f\n", n, outbuf_size, outbuf_size*8.0/n);
148 } else {
149 // Decode
150 int i, n;
151 int16_t *weights;
152 n = mlw_decode( inbuf, inbuf_size, &weights, verbose);
Michael McGeaghd5cf7652020-12-03 13:53:56 +0000153 outbuf_size = int16_format ? n*(int)sizeof(int16_t) : n;
Tim Hall79d07d22020-04-27 18:20:16 +0100154 outbuf = malloc( outbuf_size );
155 assert(outbuf);
156 for(i=0; i<n; i++) {
157 if (int16_format)
158 ((int16_t*)outbuf)[i] = weights[i];
159 else
160 outbuf[i] = weights[i];
161 }
162 free(weights);
Fredrik Svedbergdb947e42022-11-22 15:47:24 +0100163 printf("Input size %d output size %d bpw %4.2f\n", inbuf_size, n, n ? inbuf_size*8.0/n : 0);
Tim Hall79d07d22020-04-27 18:20:16 +0100164
165 }
166
167 if (outfile) {
Fredrik Svedbergdb947e42022-11-22 15:47:24 +0100168 UNCHECKED(fwrite(outbuf, 1, outbuf_size, outfile));
Tim Hall79d07d22020-04-27 18:20:16 +0100169 }
170
171 if (inbuf)
172 free(inbuf);
173 if (outbuf)
174 free(outbuf);
175 }
176
177 if (outfile) {
Fredrik Svedbergdb947e42022-11-22 15:47:24 +0100178 UNCHECKED(fclose(outfile));
Tim Hall79d07d22020-04-27 18:20:16 +0100179 }
180
181 return 0;
182}