Coverage Report

Created: 2025-06-15 00:57

/src/cmp_tool/lib/rdcu_compress/cmp_rdcu.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file   cmp_rdcu.c
3
 * @author Dominik Loidolt (dominik.loidolt@univie.ac.at)
4
 * @date   2019
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 control library
17
 * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
18
 *
19
 * To compress data, first create a compression configuration with the
20
 * rdcu_cfg_create() function.
21
 * Then set the different data buffers with the data to compressed, the model
22
 * data and the RDCU SRAM addresses with the rdcu_cfg_buffers() function.
23
 * Then set the imagette compression parameters with the rdcu_cfg_imagette()
24
 * function.
25
 * Finally, you can compress the data with the RDCU using the
26
 * rdcu_compress_data() function.
27
 */
28
29
30
#include <stddef.h>
31
#include <stdint.h>
32
33
#include "../common/cmp_debug.h"
34
#include "../common/cmp_support.h"
35
#include "cmp_rdcu_testing.h"
36
#include "cmp_rdcu_cfg.h"
37
#include "rdcu_ctrl.h"
38
#include "rdcu_rmap.h"
39
#include "../cmp_rdcu.h"
40
41
42
0
#define RDCU_INTR_SIG_ENA 1 /* RDCU interrupt signal enabled */
43
0
#define RDCU_INTR_SIG_DIS 0 /* RDCU interrupt signal disable */
44
#define RDCU_INTR_SIG_DEFAULT RDCU_INTR_SIG_ENA /* default start value for RDCU interrupt signal */
45
46
47
/* RDCU interrupt signal status */
48
static int interrupt_signal_enabled = RDCU_INTR_SIG_DEFAULT;
49
50
51
/**
52
 * @brief save repeating 3 lines of code...
53
 *
54
 * @note This function depends on the SpW implementation and must be adjusted to it.
55
 *
56
 * @note prints abort message if pending status is non-zero after 10 retries
57
 */
58
59
static void rdcu_syncing(void)
60
0
{
61
#if 0
62
  not needed for packed generation
63
64
  int cnt = 0;
65
66
  debug_print("syncing...");
67
  while (rdcu_rmap_sync_status()) {
68
    debug_print("pending: %d", rdcu_rmap_sync_status());
69
70
    if (cnt++ > 10) {
71
      debug_print("aborting; de-");
72
      break;
73
    }
74
75
  }
76
  debug_print("synced");
77
#endif
78
0
}
79
80
81
/**
82
 * @brief interrupt a data compression
83
 *
84
 * @returns 0 on success, error otherwise
85
 */
86
87
int rdcu_interrupt_compression(void)
88
0
{
89
  /* interrupt a compression */
90
0
  rdcu_set_data_compr_interrupt();
91
0
  if (rdcu_sync_compr_ctrl())
92
0
    return -1;
93
0
  rdcu_syncing();
94
95
  /* clear local bit immediately, this is a write-only register.
96
   * we would not want to restart compression by accidentally calling
97
   * rdcu_sync_compr_ctrl() again
98
   */
99
0
  rdcu_clear_data_compr_interrupt();
100
101
0
  return 0;
102
0
}
103
104
105
/**
106
 * @brief set up RDCU compression register
107
 *
108
 * @param rcfg  pointer to a compression configuration contains all parameters
109
 *  required for a RDCU compression
110
 *
111
 * @returns 0 on success, error otherwise
112
 */
113
114
static int rdcu_set_compression_register(const struct rdcu_cfg *rcfg)
115
0
{
116
0
  if (rdcu_cmp_cfg_is_invalid(rcfg))
117
0
    return -1;
118
0
#if 1
119
  /*
120
   * There is a bug in the RDCU HW data compressor, when a non-raw mode
121
   * compression is performed after a raw mode compression, the compressor
122
   * gets stuck due to a deadlock condition. Performing a compression
123
   * interrupt after a raw mode compression work around this bug.
124
   */
125
0
  if (rdcu_sync_used_param1())
126
0
    return -1;
127
0
  rdcu_syncing();
128
0
  if (rdcu_get_compression_mode() == CMP_MODE_RAW)
129
0
    rdcu_interrupt_compression();
130
0
#endif
131
132
133
  /* first, set compression parameters in local mirror registers */
134
0
  if (rdcu_set_compression_mode(rcfg->cmp_mode))
135
0
    return -1;
136
0
  if (rdcu_set_golomb_param(rcfg->golomb_par))
137
0
    return -1;
138
0
  if (rdcu_set_spillover_threshold(rcfg->spill))
139
0
    return -1;
140
0
  if (rdcu_set_weighting_param(rcfg->model_value))
141
0
    return -1;
142
0
  if (rdcu_set_noise_bits_rounded(rcfg->round))
143
0
    return -1;
144
145
0
  if (rdcu_set_adaptive_1_golomb_param(rcfg->ap1_golomb_par))
146
0
    return -1;
147
0
  if (rdcu_set_adaptive_1_spillover_threshold(rcfg->ap1_spill))
148
0
    return -1;
149
150
0
  if (rdcu_set_adaptive_2_golomb_param(rcfg->ap2_golomb_par))
151
0
    return -1;
152
0
  if (rdcu_set_adaptive_2_spillover_threshold(rcfg->ap2_spill))
153
0
    return -1;
154
155
0
  if (rdcu_set_data_start_addr(rcfg->rdcu_data_adr))
156
0
    return -1;
157
0
  if (rdcu_set_model_start_addr(rcfg->rdcu_model_adr))
158
0
    return -1;
159
0
  if (rdcu_set_num_samples(rcfg->samples))
160
0
    return -1;
161
0
  if (rdcu_set_new_model_start_addr(rcfg->rdcu_new_model_adr))
162
0
    return -1;
163
164
0
  if (rdcu_set_compr_data_buf_start_addr(rcfg->rdcu_buffer_adr))
165
0
    return -1;
166
0
  if (rdcu_set_compr_data_buf_len(rcfg->buffer_length))
167
0
    return -1;
168
169
  /* now sync the configuration registers to the RDCU... */
170
0
  if (rdcu_sync_compressor_param1())
171
0
    return -1;
172
0
  if (rdcu_sync_compressor_param2())
173
0
    return -1;
174
0
  if (rdcu_sync_adaptive_param1())
175
0
    return -1;
176
0
  if (rdcu_sync_adaptive_param2())
177
0
    return -1;
178
0
  if (rdcu_sync_data_start_addr())
179
0
    return -1;
180
0
  if (rdcu_sync_model_start_addr())
181
0
    return -1;
182
0
  if (rdcu_sync_num_samples())
183
0
    return -1;
184
0
  if (rdcu_sync_new_model_start_addr())
185
0
    return -1;
186
0
  if (rdcu_sync_compr_data_buf_start_addr())
187
0
    return -1;
188
0
  if (rdcu_sync_compr_data_buf_len())
189
0
    return -1;
190
191
  /* wait for it */
192
0
  rdcu_syncing();
193
194
0
  return 0;
195
0
}
196
197
198
/**
199
 * @brief start the RDCU data compressor
200
 *
201
 * @returns 0 on success, error otherwise
202
 */
203
204
int rdcu_start_compression(void)
205
0
{
206
0
  if (interrupt_signal_enabled) {
207
    /* enable the interrupt signal to the ICU */
208
0
    rdcu_set_rdcu_interrupt();
209
0
  } else {
210
    /* disable the interrupt signal to the ICU */
211
0
    rdcu_clear_rdcu_interrupt();
212
0
  }
213
214
  /* start the compression */
215
0
  rdcu_set_data_compr_start();
216
0
  if (rdcu_sync_compr_ctrl())
217
0
    return -1;
218
0
  rdcu_syncing();
219
220
  /* clear local bit immediately, this is a write-only register.
221
   * we would not want to restart compression by accidentally calling
222
   * rdcu_sync_compr_ctrl() again
223
   */
224
0
  rdcu_clear_data_compr_start();
225
226
0
  return 0;
227
0
}
228
229
230
/**
231
 * @brief set up RDCU SRAM for compression
232
 *
233
 * @param rcfg  pointer to a RDCU compression configuration
234
 *
235
 * @returns 0 on success, error otherwise
236
 */
237
238
static int rdcu_transfer_sram(const struct rdcu_cfg *rcfg)
239
0
{
240
0
  if (rcfg->input_buf != NULL) {
241
    /* round up needed size must be a multiple of 4 bytes */
242
0
    uint32_t size = (rcfg->samples * 2 + 3) & ~3U;
243
    /* now set the data in the local mirror... */
244
0
    if (rdcu_write_sram_16(rcfg->input_buf, rcfg->rdcu_data_adr, rcfg->samples * 2) < 0) {
245
0
      debug_print("Error: The data to be compressed cannot be transferred to the SRAM of the RDCU.");
246
0
      return -1;
247
0
    }
248
0
    if (rdcu_sync_mirror_to_sram(rcfg->rdcu_data_adr, size, rdcu_get_data_mtu())) {
249
0
      debug_print("Error: The data to be compressed cannot be transferred to the SRAM of the RDCU.");
250
0
      return -1;
251
0
    }
252
0
  }
253
  /*...and the model when needed */
254
0
  if (rcfg->model_buf != NULL) {
255
    /* set model only when model mode is used */
256
0
    if (model_mode_is_used(rcfg->cmp_mode)) {
257
      /* round up needed size must be a multiple of 4 bytes */
258
0
      uint32_t size = (rcfg->samples * 2 + 3) & ~3U;
259
      /* set the model in the local mirror... */
260
0
      if (rdcu_write_sram_16(rcfg->model_buf, rcfg->rdcu_model_adr, rcfg->samples * 2) < 0) {
261
0
        debug_print("Error: The model buffer cannot be transferred to the SRAM of the RDCU.");
262
0
        return -1;
263
0
      }
264
0
      if (rdcu_sync_mirror_to_sram(rcfg->rdcu_model_adr, size, rdcu_get_data_mtu())) {
265
0
        debug_print("Error: The model buffer cannot be transferred to the SRAM of the RDCU.");
266
0
        return -1;
267
0
      }
268
0
    }
269
0
  }
270
271
  /* ...and wait for completion */
272
0
  rdcu_syncing();
273
274
0
  return 0;
275
0
}
276
277
278
/**
279
 * @brief compressing data with the help of the RDCU hardware compressor
280
 *
281
 * @param rcfg  RDCU configuration contains all parameters required for compression
282
 *
283
 * @note Before the rdcu_compress function can be used, an initialisation of
284
 *  the RMAP library is required. This is achieved with the functions
285
 *  rdcu_ctrl_init() and rdcu_rmap_init().
286
 * @note The validity of the rcfg structure is checked before the compression is
287
 *   started.
288
 *
289
 * @returns 0 on success, error otherwise
290
 */
291
292
int rdcu_compress_data(const struct rdcu_cfg *rcfg)
293
0
{
294
0
  if (rdcu_set_compression_register(rcfg))
295
0
    return -1;
296
297
0
  if (rdcu_transfer_sram(rcfg))
298
0
    return -1;
299
300
0
  if (rdcu_start_compression())
301
0
    return -1;
302
303
0
  return 0;
304
0
}
305
306
307
/**
308
 * @brief read out the status register of the RDCU compressor
309
 *
310
 * @param status  compressor status contains the stats of the HW compressor
311
 *
312
 * @note access to the status registers is also possible during compression
313
 *
314
 * @returns 0 on success, error otherwise
315
 */
316
317
int rdcu_read_cmp_status(struct cmp_status *status)
318
0
{
319
320
0
  if (rdcu_sync_compr_status())
321
0
    return -1;
322
0
  rdcu_syncing();
323
324
0
  if (status) {
325
0
    status->data_valid = (uint8_t)rdcu_get_compr_status_valid();
326
0
    status->cmp_ready = (uint8_t)rdcu_get_data_compr_ready();
327
0
    status->cmp_interrupted = (uint8_t)rdcu_get_data_compr_interrupted();
328
0
    status->cmp_active = (uint8_t)rdcu_get_data_compr_active();
329
0
    status->rdcu_interrupt_en = (uint8_t)rdcu_get_rdcu_interrupt_enabled();
330
0
  }
331
0
  return 0;
332
0
}
333
334
335
/**
336
 * @brief read out the metadata of an RDCU compression
337
 *
338
 * @param info  compression information contains the metadata of a compression
339
 *
340
 * @note the compression information registers cannot be accessed during a
341
 *   compression
342
 *
343
 * @returns 0 on success, error otherwise
344
 */
345
346
int rdcu_read_cmp_info(struct cmp_info *info)
347
0
{
348
  /* read out the compressor information register*/
349
0
  if (rdcu_sync_used_param1())
350
0
    return -1;
351
0
  if (rdcu_sync_used_param2())
352
0
    return -1;
353
0
  if (rdcu_sync_compr_data_start_addr())
354
0
    return -1;
355
0
  if (rdcu_sync_compr_data_size())
356
0
    return -1;
357
0
  if (rdcu_sync_compr_data_adaptive_1_size())
358
0
    return -1;
359
0
  if (rdcu_sync_compr_data_adaptive_2_size())
360
0
    return -1;
361
0
  if (rdcu_sync_compr_error())
362
0
    return -1;
363
0
  if (rdcu_sync_new_model_addr_used())
364
0
    return -1;
365
0
  if (rdcu_sync_samples_used())
366
0
    return -1;
367
368
0
  rdcu_syncing();
369
370
0
  if (info) {
371
    /* put the data in the cmp_info structure */
372
0
    info->cmp_mode_used = rdcu_get_compression_mode();
373
0
    info->golomb_par_used = rdcu_get_golomb_param();
374
0
    info->spill_used = rdcu_get_spillover_threshold();
375
0
    info->model_value_used = (uint8_t)rdcu_get_weighting_param();
376
0
    info->round_used = (uint8_t)rdcu_get_noise_bits_rounded();
377
0
    info->rdcu_new_model_adr_used = rdcu_get_new_model_addr_used();
378
0
    info->samples_used = rdcu_get_samples_used();
379
0
    info->rdcu_cmp_adr_used = rdcu_get_compr_data_start_addr();
380
0
    info->cmp_size = rdcu_get_compr_data_size_bit();
381
0
    info->ap1_cmp_size = rdcu_get_compr_data_adaptive_1_size_bit();
382
0
    info->ap2_cmp_size = rdcu_get_compr_data_adaptive_2_size_bit();
383
0
    info->cmp_err = rdcu_get_compr_error();
384
#ifdef FPGA_VERSION_0_7
385
    /* There is a bug up to RDCU FPGA version 0.7 where the
386
     * compressed size is not updated accordingly in RAW mode.
387
     */
388
    if (info->cmp_mode_used == CMP_MODE_RAW) {
389
      info->cmp_size = info->samples_used * IMA_SAM2BYT * 8;
390
      info->ap1_cmp_size = info->cmp_size;
391
      info->ap2_cmp_size = info->cmp_size;
392
    }
393
#endif
394
0
#if 1
395
    /* There is a bug in RDCU FPGA version 1.1 where the compressed
396
     * size is not updated accordingly in RAW mode when the samples
397
     * parameter is smaller than 3.
398
     */
399
0
    if (info->cmp_mode_used == CMP_MODE_RAW && info->samples_used < 3) {
400
0
      info->cmp_size = info->samples_used * IMA_SAM2BYT * 8;
401
0
      info->ap1_cmp_size = info->cmp_size;
402
0
      info->ap2_cmp_size = info->cmp_size;
403
0
    }
404
0
#endif
405
0
  }
406
0
  return 0;
407
0
}
408
409
410
/**
411
 * @brief calculate the need bytes to hold a bitstream
412
 * @note we round up the result to multiples of 4 bytes
413
 *
414
 * @param cmp_size_bit  compressed data size, measured in bits
415
 *
416
 * @returns the size in bytes to store the hole bitstream
417
 */
418
419
static unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit)
420
0
{
421
0
  return (cmp_bit_to_byte(cmp_size_bit) + 3) & ~0x3UL;
422
0
}
423
424
425
/**
426
 * @brief read the compressed bitstream from the RDCU SRAM
427
 *
428
 * @param info      compression information contains the metadata of a compression
429
 * @param compressed_data the buffer to store the bitstream (if NULL, the
430
 *        required size is returned)
431
 *
432
 * @returns the number of bytes read, < 0 on error
433
 */
434
435
int rdcu_read_cmp_bitstream(const struct cmp_info *info, void *compressed_data)
436
0
{
437
0
  uint32_t s;
438
439
0
  if (info == NULL)
440
0
    return -1;
441
442
  /* calculate the need bytes for the bitstream */
443
0
  s = cmp_bit_to_4byte(info->cmp_size);
444
445
0
  if (compressed_data == NULL)
446
0
    return (int)s;
447
448
0
  if (rdcu_sync_sram_to_mirror(info->rdcu_cmp_adr_used, s,
449
0
             rdcu_get_data_mtu()))
450
0
    return -1;
451
452
  /* wait for it */
453
0
  rdcu_syncing();
454
455
0
  return rdcu_read_sram(compressed_data, info->rdcu_cmp_adr_used, s);
456
0
}
457
458
459
/**
460
 * @brief read the updated model from the RDCU SRAM
461
 *
462
 * @param info    compression information contains the metadata of a compression
463
 *
464
 * @param updated_model the buffer to store the updated model (if NULL, the required size
465
 *      is returned)
466
 *
467
 * @returns the number of bytes read, < 0 on error
468
 */
469
470
int rdcu_read_model(const struct cmp_info *info, void *updated_model)
471
0
{
472
0
  uint32_t s;
473
474
0
  if (info == NULL)
475
0
    return -1;
476
477
  /* calculate the need bytes for the model */
478
0
  s = info->samples_used * IMA_SAM2BYT;
479
480
0
  if (updated_model == NULL)
481
0
    return (int)s;
482
483
0
  if (rdcu_sync_sram_to_mirror(info->rdcu_new_model_adr_used, (s+3) & ~3U,
484
0
             rdcu_get_data_mtu()))
485
0
    return -1;
486
487
  /* wait for it */
488
0
  rdcu_syncing();
489
490
0
  return rdcu_read_sram(updated_model, info->rdcu_new_model_adr_used, s);
491
0
}
492
493
494
/**
495
 * @brief enable the RDCU to signal a finished compression with an interrupt signal
496
 */
497
498
void rdcu_enable_interrput_signal(void)
499
0
{
500
0
  interrupt_signal_enabled = RDCU_INTR_SIG_ENA;
501
0
}
502
503
504
/**
505
 * @brief deactivated the RDCU interrupt signal
506
 */
507
508
void rdcu_disable_interrput_signal(void)
509
0
{
510
0
  interrupt_signal_enabled = RDCU_INTR_SIG_DIS;
511
0
}
512
513
514
/**
515
 * @brief inject a SRAM edac multi bit error into the RDCU SRAM
516
 *
517
 * @param rcfg  configuration to inject error
518
 * @param addr  SRAM address to inject edac error
519
 */
520
521
int rdcu_inject_edac_error(const struct rdcu_cfg *rcfg, uint32_t addr)
522
0
{
523
0
  uint32_t sub_chip_die_addr;
524
0
  uint8_t buf[4] = {0};
525
526
0
  if (rdcu_set_compression_register(rcfg))
527
0
    return -1;
528
529
0
  if (rdcu_transfer_sram(rcfg))
530
0
    return -1;
531
532
  /* disable edac */
533
0
  for (sub_chip_die_addr = 1; sub_chip_die_addr <= 4; sub_chip_die_addr++) {
534
0
    rdcu_edac_set_sub_chip_die_addr(sub_chip_die_addr);
535
0
    rdcu_edac_set_ctrl_reg_write_op();
536
0
    rdcu_edac_set_bypass();
537
0
    if (rdcu_sync_sram_edac_ctrl()) {
538
0
      debug_print("Error: rdcu_sync_sram_edac_ctrl");
539
0
      return -1;
540
0
    }
541
0
    rdcu_syncing();
542
    /* verify bypass aktiv */
543
0
    rdcu_edac_set_ctrl_reg_read_op();
544
0
    if (rdcu_sync_sram_edac_ctrl()) {
545
0
      debug_print("Error: rdcu_sync_sram_edac_ctrl");
546
0
      return -1;
547
0
    }
548
0
    rdcu_syncing();
549
0
    if (rdcu_sync_sram_edac_status()) {
550
0
      debug_print("Error: rdcu_sync_sram_edac_status");
551
0
      return -1;
552
0
    }
553
0
    rdcu_syncing();
554
0
    if (rdcu_edac_get_sub_chip_die_addr() != sub_chip_die_addr) {
555
0
      debug_print("Error: sub_chip_die_addr unexpected!");
556
0
      return -1;
557
0
    }
558
0
#if 1
559
    /* It looks like there is a bug when displaying the bypass status of the 2. and 4. SRAM chip. */
560
0
    if (2 != sub_chip_die_addr && 4 != sub_chip_die_addr)
561
0
#endif
562
0
      if (rdcu_edac_get_bypass_status() == 0) {
563
0
        debug_print("Error: bypass status unexpected!");
564
0
        return -1;
565
0
      }
566
0
  }
567
568
  /* inject multi bit error */
569
0
  if (rdcu_sync_sram_to_mirror(addr, sizeof(buf), rdcu_get_data_mtu()))
570
0
    return -1;
571
0
  rdcu_syncing();
572
0
  if (rdcu_read_sram(buf, addr, sizeof(buf)) < 0)
573
0
    return -1;
574
575
0
  buf[0] ^= 1 << 0;
576
0
  buf[1] ^= 1 << 1;
577
0
  buf[2] ^= 1 << 2;
578
0
  buf[3] ^= 1 << 3;
579
580
0
  if (rdcu_write_sram(buf, addr, sizeof(buf)) < 0)
581
0
    return -1;
582
0
  if (rdcu_sync_mirror_to_sram(addr, sizeof(buf), rdcu_get_data_mtu())) {
583
0
    debug_print("Error: The data to be compressed cannot be transferred to the SRAM of the RDCU.");
584
0
    return -1;
585
0
  }
586
0
  rdcu_syncing();
587
588
589
  /* enable edac again */
590
0
  for (sub_chip_die_addr = 1; sub_chip_die_addr <= 4; sub_chip_die_addr++) {
591
0
    if (rdcu_edac_set_sub_chip_die_addr(sub_chip_die_addr))
592
0
      return -1;
593
0
    rdcu_edac_set_ctrl_reg_write_op();
594
0
    rdcu_edac_clear_bypass();
595
0
    if (rdcu_sync_sram_edac_ctrl()) {
596
0
      debug_print("Error: rdcu_sync_sram_edac_ctrl");
597
0
      return -1;
598
0
    }
599
0
    rdcu_syncing();
600
    /* verify bypass disable */
601
0
    rdcu_edac_set_ctrl_reg_read_op();
602
0
    if (rdcu_sync_sram_edac_ctrl()) {
603
0
      debug_print("Error: rdcu_sync_sram_edac_ctrl");
604
0
      return -1;
605
0
    }
606
0
    rdcu_syncing();
607
0
    if (rdcu_sync_sram_edac_status()) {
608
0
      debug_print("Error: rdcu_sync_sram_edac_status");
609
0
      return -1;
610
0
    }
611
0
    rdcu_syncing();
612
0
    if (rdcu_edac_get_sub_chip_die_addr() != sub_chip_die_addr) {
613
0
      debug_print("Error: sub_chip_die_addr unexpected!");
614
0
      return -1;
615
0
    }
616
0
    if (rdcu_edac_get_bypass_status() == 1) {
617
0
      debug_print("Error: bypass status unexpected!");
618
0
      return -1;
619
0
    }
620
0
  }
621
0
  return 0;
622
0
}
623
624
625
/**
626
 * @brief compressing data with the help of the RDCU hardware compressor; read
627
 *  data from the last compression before starting compression
628
 *
629
 * @param rcfg       configuration contains all parameters required for compression
630
 * @param last_info  compression information of last compression run
631
 *
632
 * @note when using the 1d-differencing mode or the raw mode (cmp_mode = 0,2,4),
633
 *      the model parameters (model_value, model_buf, rdcu_model_adr) are ignored
634
 * @note the overlapping of the different rdcu buffers is not checked
635
 * @note the validity of the rcfg structure is checked before the compression is
636
 *   started
637
 *
638
 * @returns 0 on success, error otherwise
639
 */
640
641
int rdcu_compress_data_parallel(const struct rdcu_cfg *rcfg,
642
        const struct cmp_info *last_info)
643
0
{
644
0
  uint32_t samples_4byte;
645
646
0
  if (!rcfg)
647
0
    return -1;
648
649
0
  if (!last_info)
650
0
    return rdcu_compress_data(rcfg);
651
652
0
  if (last_info->cmp_err)
653
0
    return -1;
654
655
0
  rdcu_set_compression_register(rcfg);
656
657
  /* round up needed size must be a multiple of 4 bytes */
658
0
  samples_4byte = (rcfg->samples * IMA_SAM2BYT + 3) & ~3U;
659
660
0
  if (rcfg->input_buf != NULL) {
661
0
    uint32_t cmp_size_4byte;
662
663
    /* now set the data in the local mirror... */
664
0
    if (rdcu_write_sram_16(rcfg->input_buf, rcfg->rdcu_data_adr,
665
0
               rcfg->samples * IMA_SAM2BYT) < 0)
666
0
      return -1;
667
668
    /* calculate the need bytes for the bitstream */
669
0
    cmp_size_4byte = cmp_bit_to_4byte(last_info->cmp_size);
670
671
    /* parallel read compressed data and write input data from sram to mirror */
672
0
    if (rdcu_sync_sram_mirror_parallel(last_info->rdcu_cmp_adr_used,
673
0
        cmp_size_4byte, rcfg->rdcu_data_adr, samples_4byte,
674
0
        rdcu_get_data_mtu()))
675
0
      return -1;
676
    /* wait for it */
677
0
    rdcu_syncing();
678
0
    if (rcfg->icu_output_buf) {
679
0
      if (rdcu_read_sram(rcfg->icu_output_buf,
680
0
             last_info->rdcu_cmp_adr_used,
681
0
             cmp_size_4byte))
682
0
        return -1;
683
0
    }
684
0
  } else {
685
0
    debug_print("Warning: input_buf = NULL; input_buf is not written to the sram and compressed data is not read from the SRAM.");
686
0
  }
687
688
  /* read model and write model in parallel */
689
0
  if (rcfg->model_buf && model_mode_is_used(rcfg->cmp_mode) && model_mode_is_used(last_info->cmp_mode_used)) {
690
0
    if (rcfg->rdcu_model_adr == last_info->rdcu_new_model_adr_used &&
691
0
        rcfg->samples == last_info->samples_used) {
692
0
      debug_print("The last updated model buffer and the current model buffer overlap exactly in the SRAM of the RDCU. Skip model transfer.");
693
0
    } else {
694
0
      uint32_t new_model_size_4byte;
695
696
      /* set the model in the local mirror... */
697
0
      if (rdcu_write_sram_16(rcfg->model_buf, rcfg->rdcu_model_adr,
698
0
                 rcfg->samples * IMA_SAM2BYT) < 0)
699
0
        return -1;
700
701
0
      new_model_size_4byte = last_info->samples_used * IMA_SAM2BYT;
702
0
      if (rdcu_sync_sram_mirror_parallel(last_info->rdcu_new_model_adr_used,
703
0
                 (new_model_size_4byte+3) & ~0x3U,
704
0
                 rcfg->rdcu_model_adr,
705
0
                 samples_4byte, rdcu_get_data_mtu()))
706
0
        return -1;
707
      /* wait for it */
708
0
      rdcu_syncing();
709
0
      if (rcfg->icu_new_model_buf) {
710
0
        if (rdcu_read_sram(rcfg->icu_new_model_buf,
711
0
               last_info->rdcu_new_model_adr_used,
712
0
               new_model_size_4byte) < 0)
713
0
          return -1;
714
0
      }
715
0
    }
716
  /* write model */
717
0
  } else if (rcfg->model_buf && model_mode_is_used(rcfg->cmp_mode)) {
718
    /* set the model in the local mirror... */
719
0
    if (rdcu_write_sram_16(rcfg->model_buf, rcfg->rdcu_model_adr,
720
0
               rcfg->samples * IMA_SAM2BYT) < 0)
721
0
      return -1;
722
723
0
    if (rdcu_sync_mirror_to_sram(rcfg->rdcu_model_adr, samples_4byte,
724
0
               rdcu_get_data_mtu()))
725
0
      return -1;
726
  /* read model */
727
0
  } else if (model_mode_is_used(last_info->cmp_mode_used)) {
728
0
    if (rdcu_read_model(last_info, rcfg->icu_new_model_buf) < 0)
729
0
      return -1;
730
0
  }
731
732
  /* ...and wait for completion */
733
0
  rdcu_syncing();
734
735
0
  if (rdcu_start_compression())
736
0
    return -1;
737
738
0
  return 0;
739
0
}
740