Coverage Report

Created: 2025-06-15 00:57

/src/cmp_tool/lib/rdcu_compress/cmp_rdcu_cfg.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file   cmp_rdcu_cfg.c
3
 * @author Dominik Loidolt (dominik.loidolt@univie.ac.at)
4
 * @date   2020
5
 *
6
 * @copyright GPLv2
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms and conditions of the GNU General Public License,
9
 * version 2, as published by the Free Software Foundation.
10
 *
11
 * This program is distributed in the hope it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14
 * more details.
15
 *
16
 * @brief hardware compressor configuration library
17
 * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
18
 */
19
20
21
#include <stdint.h>
22
#include <string.h>
23
24
#include "../common/cmp_debug.h"
25
#include "../common/cmp_support.h"
26
#include "../common/leon_inttypes.h"
27
#include "../common/compiler.h"
28
#include "../common/cmp_cal_up_model.h"
29
#include "rdcu_cmd.h"
30
#include "cmp_rdcu_cfg.h"
31
32
33
/**
34
 * @brief check if the compression mode, model value and the lossy rounding
35
 *  parameters are invalid for an RDCU compression
36
 *
37
 * @param rcfg  pointer to a RDCU compression configuration containing the
38
 *  compression mode, model value and the rounding parameters
39
 *
40
 * @returns 0 if the compression mode, model value and the lossy rounding
41
 *  parameters are valid for an RDCU compression, non-zero if parameters are
42
 *  invalid
43
 */
44
45
static int rdcu_cfg_gen_pars_are_invalid(const struct rdcu_cfg *rcfg)
46
18
{
47
18
  int rcfg_invalid = 0;
48
49
18
  if (!cmp_mode_is_supported(rcfg->cmp_mode)) {
50
0
    debug_print("Error: selected cmp_mode: %i is not supported for a RDCU compression.", rcfg->cmp_mode);
51
0
    rcfg_invalid++;
52
0
  }
53
54
18
  if (rcfg->model_value > MAX_MODEL_VALUE) {
55
0
    debug_print("Error: selected model_value: %" PRIu32 " is invalid. The largest supported value is: %u.",
56
0
          rcfg->model_value, MAX_MODEL_VALUE);
57
0
    rcfg_invalid++;
58
0
  }
59
60
18
  if (rcfg->round > MAX_RDCU_ROUND) {
61
0
    debug_print("Error: selected lossy parameter: %" PRIu32 " is not supported for a RDCU compression. The largest supported value is: %" PRIu32 ".",
62
0
          rcfg->round, MAX_RDCU_ROUND);
63
0
    rcfg_invalid++;
64
0
  }
65
66
#ifdef SKIP_CMP_PAR_CHECK
67
  return 0;
68
#endif
69
18
  return rcfg_invalid;
70
18
}
71
72
73
/**
74
 * @brief create an RDCU compression configuration
75
 *
76
 * @param rcfg    pointer to an RDCU compression configuration to be created
77
 * @param cmp_mode  compression mode
78
 * @param model_value model weighting parameter (only needed for model compression mode)
79
 * @param round   lossy rounding parameter (use CMP_LOSSLESS for lossless compression)
80
 *
81
 * @returns 0 if parameters are valid, non-zero if parameters are invalid
82
 */
83
84
int rdcu_cfg_create(struct rdcu_cfg *rcfg, enum cmp_mode cmp_mode,
85
        uint32_t model_value, uint32_t round)
86
18
{
87
18
  if (!rcfg)
88
0
    return 1;
89
90
18
  memset(rcfg, 0, sizeof(*rcfg));
91
92
18
  rcfg->cmp_mode = cmp_mode;
93
18
  rcfg->model_value = model_value;
94
18
  rcfg->round = round;
95
96
18
  return rdcu_cfg_gen_pars_are_invalid(rcfg);
97
18
}
98
99
100
/**
101
 * @brief check if a buffer is outside the RDCU SRAM
102
 *
103
 * @param addr  start address of the buffer
104
 * @param size  length of the buffer in bytes
105
 *
106
 * @returns 0 if the buffer is inside the RDCU SRAM, 1 when the buffer is outside
107
 */
108
109
static int outside_sram_range(uint32_t addr, uint32_t size)
110
68
{
111
68
  if (addr + size > RDCU_SRAM_START + RDCU_SRAM_SIZE)
112
0
    return 1;
113
114
68
  if (addr > RDCU_SRAM_END)
115
0
    return 1;
116
117
68
  if (size > RDCU_SRAM_SIZE)
118
0
    return 1;
119
120
68
  return 0;
121
68
}
122
123
124
/**
125
 * @brief check if two buffers are overlapping
126
 * @note implement according to https://stackoverflow.com/a/325964
127
 *
128
 * @param start_a start address of the 1st buffer
129
 * @param end_a   end address of the 1st buffer
130
 * @param start_b start address of the 2nd buffer
131
 * @param end_b   end address of the 2nd buffer
132
 *
133
 * @returns 0 if buffers are not overlapping, otherwise buffers are
134
 *  overlapping
135
 */
136
137
static int buffers_overlap(uint32_t start_a, uint32_t end_a, uint32_t start_b,
138
         uint32_t end_b)
139
98
{
140
98
  if (start_a < end_b && end_a > start_b)
141
0
    return 1;
142
98
  else
143
98
    return 0;
144
98
}
145
146
147
/**
148
 * @brief check if RDCU buffer settings are invalid
149
 *
150
 * @param rcfg  a pointer to a RDCU compression configuration
151
 *
152
 * @returns 0 if the buffer configuration is valid, otherwise the configuration
153
 *  is invalid
154
 */
155
156
static int rdcu_cfg_buffers_is_invalid(const struct rdcu_cfg *rcfg)
157
18
{
158
18
  int rcfg_invalid = 0;
159
160
18
  if (rcfg->cmp_mode == CMP_MODE_RAW) {
161
0
    if (rcfg->buffer_length < rcfg->samples) {
162
0
      debug_print("Error: rdcu_buffer_length is smaller than the samples parameter. There is not enough space to copy the data in RAW mode.");
163
0
      rcfg_invalid++;
164
0
    }
165
0
  }
166
167
18
  if (rcfg->rdcu_data_adr & 0x3) {
168
0
    debug_print("Error: The RDCU data to compress start address is not 4-Byte aligned.");
169
0
    rcfg_invalid++;
170
0
  }
171
172
18
  if (rcfg->rdcu_buffer_adr & 0x3) {
173
0
    debug_print("Error: The RDCU compressed data start address is not 4-Byte aligned.");
174
0
    rcfg_invalid++;
175
0
  }
176
177
18
  if (outside_sram_range(rcfg->rdcu_data_adr, rcfg->samples * IMA_SAM2BYT)) {
178
0
    debug_print("Error: The RDCU data to compress buffer is outside the RDCU SRAM address space.");
179
0
    rcfg_invalid++;
180
0
  }
181
182
18
  if (outside_sram_range(rcfg->rdcu_buffer_adr, rcfg->buffer_length * IMA_SAM2BYT)) {
183
0
    debug_print("Error: The RDCU compressed data buffer is outside the RDCU SRAM address space.");
184
0
    rcfg_invalid++;
185
0
  }
186
187
18
  if (buffers_overlap(rcfg->rdcu_data_adr,
188
18
          rcfg->rdcu_data_adr + rcfg->samples * IMA_SAM2BYT,
189
18
          rcfg->rdcu_buffer_adr,
190
18
          rcfg->rdcu_buffer_adr + rcfg->buffer_length * IMA_SAM2BYT)) {
191
0
    debug_print("Error: The RDCU data to compress buffer and the RDCU compressed data buffer are overlapping.");
192
0
    rcfg_invalid++;
193
0
  }
194
195
18
  if (model_mode_is_used(rcfg->cmp_mode)) {
196
16
    if (rcfg->model_buf && rcfg->model_buf == rcfg->input_buf) {
197
0
      debug_print("Error: The model buffer (model_buf) and the data to be compressed (input_buf) are equal.");
198
0
      rcfg_invalid++;
199
0
    }
200
201
16
    if (rcfg->rdcu_model_adr & 0x3) {
202
0
      debug_print("Error: The RDCU model start address is not 4-Byte aligned.");
203
0
      rcfg_invalid++;
204
0
    }
205
206
16
    if (outside_sram_range(rcfg->rdcu_model_adr, rcfg->samples * IMA_SAM2BYT)) {
207
0
      debug_print("Error: The RDCU model buffer is outside the RDCU SRAM address space.");
208
0
      rcfg_invalid++;
209
0
    }
210
211
16
    if (buffers_overlap(
212
16
          rcfg->rdcu_model_adr,
213
16
          rcfg->rdcu_model_adr + rcfg->samples * IMA_SAM2BYT,
214
16
          rcfg->rdcu_data_adr,
215
16
          rcfg->rdcu_data_adr + rcfg->samples * IMA_SAM2BYT)) {
216
0
      debug_print("Error: The model buffer and the data to compress buffer are overlapping.");
217
0
      rcfg_invalid++;
218
0
    }
219
220
16
    if (buffers_overlap(
221
16
      rcfg->rdcu_model_adr,
222
16
      rcfg->rdcu_model_adr + rcfg->samples * IMA_SAM2BYT,
223
16
      rcfg->rdcu_buffer_adr,
224
16
      rcfg->rdcu_buffer_adr + rcfg->buffer_length * IMA_SAM2BYT)
225
16
        ) {
226
0
      debug_print("Error: The model buffer and the compressed data buffer are overlapping.");
227
0
      rcfg_invalid++;
228
0
    }
229
230
16
    if (rcfg->rdcu_model_adr != rcfg->rdcu_new_model_adr) {
231
16
      if (rcfg->rdcu_new_model_adr & 0x3) {
232
0
        debug_print("Error: The RDCU updated model start address (rdcu_new_model_adr) is not 4-Byte aligned.");
233
0
        rcfg_invalid++;
234
0
      }
235
236
16
      if (outside_sram_range(rcfg->rdcu_new_model_adr,
237
16
             rcfg->samples * IMA_SAM2BYT)) {
238
0
        debug_print("Error: The RDCU updated model buffer is outside the RDCU SRAM address space.");
239
0
        rcfg_invalid++;
240
0
      }
241
242
16
      if (buffers_overlap(
243
16
        rcfg->rdcu_new_model_adr,
244
16
        rcfg->rdcu_new_model_adr + rcfg->samples * IMA_SAM2BYT,
245
16
        rcfg->rdcu_data_adr,
246
16
        rcfg->rdcu_data_adr + rcfg->samples * IMA_SAM2BYT)
247
16
          ) {
248
0
        debug_print("Error: The updated model buffer and the data to compress buffer are overlapping.");
249
0
        rcfg_invalid++;
250
0
      }
251
252
16
      if (buffers_overlap(
253
16
        rcfg->rdcu_new_model_adr,
254
16
        rcfg->rdcu_new_model_adr + rcfg->samples * IMA_SAM2BYT,
255
16
        rcfg->rdcu_buffer_adr,
256
16
        rcfg->rdcu_buffer_adr + rcfg->buffer_length * IMA_SAM2BYT)
257
16
          ) {
258
0
        debug_print("Error: The updated model buffer and the compressed data buffer are overlapping.");
259
0
        rcfg_invalid++;
260
0
      }
261
16
      if (buffers_overlap(
262
16
        rcfg->rdcu_new_model_adr,
263
16
        rcfg->rdcu_new_model_adr + rcfg->samples * IMA_SAM2BYT,
264
16
        rcfg->rdcu_model_adr,
265
16
        rcfg->rdcu_model_adr + rcfg->samples * IMA_SAM2BYT)
266
16
          ) {
267
0
        debug_print("Error: The updated model buffer and the model buffer are overlapping.");
268
0
        rcfg_invalid++;
269
0
      }
270
16
    }
271
16
  }
272
273
#ifdef SKIP_CMP_PAR_CHECK
274
  return 0;
275
#endif
276
18
  return rcfg_invalid;
277
18
}
278
279
280
/**
281
 * @brief setup of the different data buffers for an RDCU compression
282
 *
283
 * @param rcfg      pointer to a RDCU compression configuration
284
 *        (created with the rdcu_cfg_create() function)
285
 * @param data_to_compress  pointer to the data to be compressed (if NULL no
286
 *        data transfer to the RDCU)
287
 * @param data_samples    length of the data to be compressed (plus the
288
 *        collection header) measured in 16-bit data samples
289
 * @param model_of_data   pointer to the model data buffer (only needed for
290
 *        model compression mode, if NULL no model data is
291
 *        transferred to the RDCU)
292
 * @param rdcu_data_adr   RDCU SRAM data to compress start address
293
 * @param rdcu_model_adr  RDCU SRAM model start address (only needed for
294
 *        model compression mode)
295
 * @param rdcu_new_model_adr  RDCU SRAM new/updated model start address (can be
296
 *        the same as rdcu_model_adr for in-place model update)
297
 * @param rdcu_buffer_adr RDCU SRAM compressed data start address
298
 * @param rdcu_buffer_lenght  length of the RDCU compressed data SRAM buffer
299
 *        measured in 16-bit units (same as data_samples)
300
 *
301
 * @returns 0 if parameters are valid, non-zero if parameters are invalid
302
 */
303
304
int rdcu_cfg_buffers(struct rdcu_cfg *rcfg, uint16_t *data_to_compress,
305
         uint32_t data_samples, uint16_t *model_of_data,
306
         uint32_t rdcu_data_adr, uint32_t rdcu_model_adr,
307
         uint32_t rdcu_new_model_adr, uint32_t rdcu_buffer_adr,
308
         uint32_t rdcu_buffer_lenght)
309
18
{
310
18
  if (!rcfg) {
311
0
    debug_print("Error: pointer to the compression configuration structure is NULL.");
312
0
    return -1;
313
0
  }
314
315
18
  rcfg->input_buf = data_to_compress;
316
18
  rcfg->samples = data_samples;
317
18
  rcfg->model_buf = model_of_data;
318
18
  rcfg->rdcu_data_adr = rdcu_data_adr;
319
18
  rcfg->rdcu_model_adr = rdcu_model_adr;
320
18
  rcfg->rdcu_new_model_adr = rdcu_new_model_adr;
321
18
  rcfg->rdcu_buffer_adr = rdcu_buffer_adr;
322
18
  rcfg->buffer_length = rdcu_buffer_lenght;
323
324
18
  return rdcu_cfg_buffers_is_invalid(rcfg);
325
18
}
326
327
328
/**
329
 * @brief check if the combination of the Golomb and spill parameters is invalid
330
 *
331
 * @param golomb_par  Golomb parameter
332
 * @param spill   spillover threshold parameter
333
 * @param par_name  string describing the use of the compression par. for
334
 *      debug messages (can be NULL)
335
 *
336
 * @returns 0 if the parameter combination is valid, otherwise the combination is invalid
337
 */
338
339
static int rdcu_cfg_golomb_spill_are_invalid(uint32_t golomb_par, uint32_t spill,
340
           const char *par_name MAYBE_UNUSED)
341
54
{
342
54
  int rcfg_invalid = 0;
343
344
54
  if (golomb_par < MIN_IMA_GOLOMB_PAR || golomb_par > MAX_IMA_GOLOMB_PAR) {
345
0
    debug_print("Error: The selected %s compression parameter: %" PRIu32 " is not supported in the selected compression mode. The compression parameter has to be between [%" PRIu32 ", %" PRIu32 "] in this mode.",
346
0
          par_name, golomb_par, MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR);
347
0
    rcfg_invalid++;
348
0
  }
349
54
  if (spill < MIN_IMA_SPILL) {
350
0
    debug_print("Error: The selected %s spillover threshold value: %" PRIu32 " is too small. The smallest possible spillover value is: %" PRIu32 ".",
351
0
          par_name, spill, MIN_IMA_SPILL);
352
0
    rcfg_invalid++;
353
0
  }
354
54
  if (spill > cmp_ima_max_spill(golomb_par)) {
355
0
    debug_print("Error: The selected %s spillover threshold value: %" PRIu32 " is too large for the selected %s compression parameter: %" PRIu32 ". The largest possible spillover value in the selected compression mode is: %" PRIu32 ".",
356
0
          par_name, spill, par_name, golomb_par, cmp_ima_max_spill(golomb_par));
357
0
    rcfg_invalid++;
358
0
  }
359
360
361
#ifdef SKIP_CMP_PAR_CHECK
362
  return 0;
363
#endif
364
54
  return rcfg_invalid;
365
54
}
366
367
368
/**
369
 * @brief check if the all Golomb and spill parameters pairs are invalid
370
 *
371
 * @param rcfg  pointer to a RDCU compressor configuration
372
 *
373
 * @returns 0 if the parameters are valid, otherwise invalid
374
 */
375
376
static int rdcu_cfg_imagette_is_invalid(const struct rdcu_cfg *rcfg)
377
18
{
378
18
  int rcfg_invalid = 0;
379
380
18
  rcfg_invalid += rdcu_cfg_golomb_spill_are_invalid(rcfg->golomb_par, rcfg->spill,
381
18
               "imagette");
382
18
  rcfg_invalid += rdcu_cfg_golomb_spill_are_invalid(rcfg->ap1_golomb_par, rcfg->ap1_spill,
383
18
               "adaptive 1 imagette");
384
18
  rcfg_invalid += rdcu_cfg_golomb_spill_are_invalid(rcfg->ap2_golomb_par, rcfg->ap2_spill,
385
18
               "adaptive 2 imagette");
386
387
18
  return rcfg_invalid;
388
18
}
389
390
391
/**
392
 * @brief set up the configuration parameters for an RDCU imagette compression
393
 *
394
 * @param rcfg      pointer to a RDCU compression configuration
395
 *        (created with the rdcu_cfg_create() function)
396
 * @param golomb_par    imagette compression parameter
397
 * @param spillover_par   imagette spillover threshold parameter
398
 * @param ap1_golomb_par  adaptive 1 imagette compression parameter
399
 * @param ap1_spillover_par adaptive 1 imagette spillover threshold parameter
400
 * @param ap2_golomb_par  adaptive 2 imagette compression parameter
401
 * @param ap2_spillover_par adaptive 2 imagette spillover threshold parameter
402
 *
403
 * @returns 0 if parameters are valid, non-zero if parameters are invalid
404
 */
405
406
int rdcu_cfg_imagette(struct rdcu_cfg *rcfg,
407
          uint32_t golomb_par, uint32_t spillover_par,
408
          uint32_t ap1_golomb_par, uint32_t ap1_spillover_par,
409
          uint32_t ap2_golomb_par, uint32_t ap2_spillover_par)
410
18
{
411
18
  if (!rcfg) {
412
0
    debug_print("Error: pointer to the compression configuration structure is NULL.");
413
0
    return -1;
414
0
  }
415
416
18
  rcfg->golomb_par = golomb_par;
417
18
  rcfg->spill = spillover_par;
418
18
  rcfg->ap1_golomb_par = ap1_golomb_par;
419
18
  rcfg->ap1_spill = ap1_spillover_par;
420
18
  rcfg->ap2_golomb_par = ap2_golomb_par;
421
18
  rcfg->ap2_spill = ap2_spillover_par;
422
423
18
  return rdcu_cfg_imagette_is_invalid(rcfg);
424
18
}
425
426
427
/**
428
 * @brief set up the default configuration parameters for an RDCU imagette
429
 *  compression based on the set compression mode
430
 *
431
 * @param rcfg  pointer to a RDCU compression configuration (created with the
432
 *    rdcu_cfg_create() function)
433
 *
434
 * @returns 0 if parameters are valid, non-zero if parameters are invalid
435
 */
436
437
int rdcu_cfg_imagette_default(struct rdcu_cfg *rcfg)
438
18
{
439
440
18
  if (!rcfg) {
441
0
    debug_print("Error: pointer to the compression configuration structure is NULL.");
442
0
    return -1;
443
0
  }
444
445
18
  if (model_mode_is_used(rcfg->cmp_mode)) {
446
16
    return rdcu_cfg_imagette(rcfg, CMP_DEF_IMA_MODEL_GOLOMB_PAR,
447
16
           CMP_DEF_IMA_MODEL_SPILL_PAR,
448
16
           CMP_DEF_IMA_MODEL_AP1_GOLOMB_PAR,
449
16
           CMP_DEF_IMA_MODEL_AP1_SPILL_PAR,
450
16
           CMP_DEF_IMA_MODEL_AP2_GOLOMB_PAR,
451
16
           CMP_DEF_IMA_MODEL_AP2_SPILL_PAR);
452
16
  } else {
453
2
    return rdcu_cfg_imagette(rcfg, CMP_DEF_IMA_DIFF_GOLOMB_PAR,
454
2
           CMP_DEF_IMA_DIFF_SPILL_PAR,
455
2
           CMP_DEF_IMA_DIFF_AP1_GOLOMB_PAR,
456
2
           CMP_DEF_IMA_DIFF_AP1_SPILL_PAR,
457
2
           CMP_DEF_IMA_DIFF_AP2_GOLOMB_PAR,
458
2
           CMP_DEF_IMA_DIFF_AP2_SPILL_PAR);
459
2
  }
460
18
}
461
462
463
/**
464
 * @brief check if the compressor configuration is invalid for an RDCU compression,
465
 *  see the user manual for more information (PLATO-UVIE-PL-UM-0001).
466
 *
467
 * @param rcfg  pointer to a RDCU compression configuration contains all
468
 *    parameters required for compression
469
 *
470
 * @returns 0 if parameters are valid, non-zero if parameters are invalid
471
 */
472
473
int rdcu_cmp_cfg_is_invalid(const struct rdcu_cfg *rcfg)
474
0
{
475
0
  int rcfg_invalid = 0;
476
477
0
  if (!rcfg) {
478
0
    debug_print("Error: pointer to the compression configuration structure is NULL.");
479
0
    return -1;
480
0
  }
481
482
0
  if (!rcfg->input_buf)
483
0
    debug_print("Warning: The data to compress buffer is set to NULL. No data will be transferred to the rdcu_data_adr in the RDCU SRAM.");
484
485
0
  if (model_mode_is_used(rcfg->cmp_mode)) {
486
0
    if (!rcfg->model_buf)
487
0
      debug_print("Warning: The model buffer is set to NULL. No model data will be transferred to the rdcu_model_adr in the RDCU SRAM.");
488
0
  }
489
490
0
  if (rcfg->samples == 0)
491
0
    debug_print("Warning: The samples parameter is set to 0. No data will be compressed.");
492
493
0
  if (rcfg->icu_new_model_buf)
494
0
    debug_print("Warning: ICU updated model buffer is set. This buffer is not used for an RDCU compression.");
495
496
0
  if (rcfg->icu_output_buf)
497
0
    debug_print("Warning: ICU compressed data buffer is set. This buffer is not used for an RDCU compression.");
498
499
0
  if (rcfg->buffer_length == 0) {
500
0
    debug_print("Error: The buffer_length is set to 0. There is no place to store the compressed data.");
501
0
    rcfg_invalid++;
502
0
  }
503
504
0
  rcfg_invalid += rdcu_cfg_gen_pars_are_invalid(rcfg);
505
0
  rcfg_invalid += rdcu_cfg_buffers_is_invalid(rcfg);
506
0
  rcfg_invalid += rdcu_cfg_imagette_is_invalid(rcfg);
507
508
0
  return rcfg_invalid;
509
0
}