/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 | | |