Skip to content
Snippets Groups Projects
Commit a7b4ee0b authored by Dominik Loidolt's avatar Dominik Loidolt
Browse files

add compression configuration guessing feature

if samples or buffer_length is 0, the tools try now tool to find a plausible vaule for the parameters
some code refactoring
add more verbose error messages
small bug fixes

added feature to guess the compression configuration
some code restructuring
added more detailed error messages
small bug fixes
parent ed7c7796
No related branches found
No related tags found
1 merge request!2added feature to guess the compression configuration
This commit is part of merge request !2. Comments created here will be created in the context of that merge request.
...@@ -2,8 +2,13 @@ ...@@ -2,8 +2,13 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [Unreleased] ## [Unreleased]
## [0.06] - 12-11-2021
- if samples = 0 the cmp_tool counts the samples in the data file and uses them - if samples = 0 the cmp_tool counts the samples in the data file and uses them
- if buffer_length = 0 the 2*samples parameter is used as buffer_length - if buffer_length = 0 the 2*samples parameter is used as buffer_length
- added feature to guess the compression configuration
- some code restructuring
- added more detailed error messages
- small bug fixes
## [0.05] - 23-04-2021 ## [0.05] - 23-04-2021
### Removed ### Removed
- discard old file format. Now the only input format is like: 12 AB 23 CD .. .. - discard old file format. Now the only input format is like: 12 AB 23 CD .. ..
......
...@@ -2,9 +2,11 @@ CC = gcc ...@@ -2,9 +2,11 @@ CC = gcc
SOURCEDIR = lib SOURCEDIR = lib
INCLUDEDIR = include INCLUDEDIR = include
BUILDDIR = ./ BUILDDIR = ./
CFLAGS := -Wall -Wextra -std=gnu99 -pedantic -Wshadow CFLAGS := -Wall -Wextra -std=gnu99 -pedantic -Wshadow \
-Wunreachable-code #-Wdocumentation #-Wsign-conversion
RELCFLAGS := -O2 # Release flags RELCFLAGS := -O2 # Release flags
DBCFLAGS := -O0 -g3 #debug flags DBCFLAGS := -O0 -g3 #debug flags
COVFLAGS := -fprofile-arcs -ftest-coverage #coverage flags
CPPFLAGS := -I $(INCLUDEDIR) CPPFLAGS := -I $(INCLUDEDIR)
LDFLAGS := -lm LDFLAGS := -lm
SOURCES := cmp_tool.c \ SOURCES := cmp_tool.c \
...@@ -18,6 +20,7 @@ SOURCES := cmp_tool.c \ ...@@ -18,6 +20,7 @@ SOURCES := cmp_tool.c \
$(SOURCEDIR)/cmp_icu.c \ $(SOURCEDIR)/cmp_icu.c \
$(SOURCEDIR)/decmp.c \ $(SOURCEDIR)/decmp.c \
$(SOURCEDIR)/rdcu_pkt_to_file.c \ $(SOURCEDIR)/rdcu_pkt_to_file.c \
$(SOURCEDIR)/cmp_guess.c \
$(SOURCEDIR)/cmp_tool_lib.c $(SOURCEDIR)/cmp_tool_lib.c
TARGET := cmp_tool TARGET := cmp_tool
...@@ -34,3 +37,13 @@ all: $(SOURCES) ...@@ -34,3 +37,13 @@ all: $(SOURCES)
debug: $(SOURCES) debug: $(SOURCES)
$(CC) $(CPPFLAGS) $(CFLAGS) $(DBCFLAGS) $^ -o $(TARGET) $(LDFLAGS) $(CC) $(CPPFLAGS) $(CFLAGS) $(DBCFLAGS) $^ -o $(TARGET) $(LDFLAGS)
integration: $(SOURCES)
$(CC) $(CPPFLAGS) $(CFLAGS) $(DBCFLAGS) $(COVFLAGS) $^ -o $(TARGET) $(LDFLAGS)
pytest test/cmp_tool/cmp_tool_integration_test.py
lcov --rc lcov_branch_coverage=1 --capture --directory ./ --output-file coverage.info
genhtml --rc lcov_branch_coverage=1 --branch-coverage coverage.info --output-directory out
#firefox out/index.html
clean:
rm -rf $(TARGET) *.gcno *.gcda coverage.info out
# PLATO Compression/Decompression Tool # PLATO Compression/Decompression Tool
If you find a bug or have a feature request please file an [issue][1] or send me an [email][2] If you find a bug or have a feature request please file an [issue][1] or send
Compiled executable can be found [here](https://gitlab.phaidra.org/loidoltd15/cmp_tool/-/tags). me an [email][2].
Compiled executables can be found [here][3].
## Usage ## Usage
**usage:** `./cmp_tool [options] [<argument>]`
**usage:** `cmp_tool [options] [<argument>]`
### General Options ### General Options
| Options | Description | | Options | Description |
| ----------------- | ---------------------------------------------------------------------------------- | |:------------------|:------------------------------------------------------------------------------|
| `-h, --help` | Print this help text and exit | | `-h, --help` | Print some help text and exit |
| `-V, --version` | Print program version and exit | | `-V, --version` | Print program version and exit |
| `-v, --verbose` | Print various debugging information | | `-v, --verbose` | Print various debugging information |
| `-n, --model_cfg` | Print a default model configuration and exit<sup>[1](#myfootnote2)</sup> | | `-n, --model_cfg` | Print a default model configuration and exit<sup>[1](#fnote1)</sup> |
| `--diff_cfg` | Print a default 1d-differencing configuration and exit<sup>[1](#myfootnote2)</sup> | | `--diff_cfg` | Print a default 1d-differencing configuration and exit<sup>[1](#fnote1)</sup> |
| `-a, --rdcu_par` | Print additional RDCU control parameters | | `-a, --rdcu_par` | Add additional RDCU control parameters |
| `-o <prefix>` | Use the `<prefix>` for output files<sup>[2](#myfootnote2)</sup> | | `-o <prefix>` | Use the `<prefix>` for output files<sup>[2](#fnote2)</sup> |
<a name="myfootnote1">1</a>) **NOTE:** In the default configurations the samples and buffer_length parameter is set to 0! <a name="fnote1">1</a>) **NOTE:** In the default configurations the **samples**
<a name="myfootnote2">2</a>) **NOTE:** If the -o option is not used the `<prefix>` will be set to "OUTPUT". and **buffer_length** parameter is set to **0**!
<a name="fnote2">2</a>) **NOTE:** If the -o option is not used the `<prefix>`
will be set to "OUTPUT".
### Compression Options ### Compression Options
| Options | Description | | Options | Description |
| --------------------------- | ----------------------------------------------------------------------------------- | |:----------------------------|:-------------------------------------------------------------------------------------|
| `-c <file>` | File containing the compressing configuration | | `-c <file>` | File containing the compressing configuration |
| `-d <file>` | File containing the data to be compressed | | `-d <file>` | File containing the data to be compressed |
| `-m <file>` | File containing the model of the data to be compressed | | `-m <file>` | File containing the model of the data to be compressed |
| `--rdcu_pkt` | Generate RMAP packets for a RDCU compression<sup>[3](#myfootnote3)</sup> | | `--rdcu_pkt` | Generate RMAP packets for an RDCU compression<sup>[3](#fnoot3)</sup> |
| `--last_info <.info file>` | Generate RMAP packets for a RDCU compression with parallel read of the last results | | `--last_info <.info file>` | Generate RMAP packets for an RDCU compression with parallel read of the last results |
<a name="myfootnote2">3</a>) **NOTE:** When using the `--rdcu_pkt` option the configuration of the RMAP parameters <a name="foot3">3</a>) **NOTE:** When using the `--rdcu_pkt` option the
can be found in the `.rdcu_pkt_mode_cfg file`. The generated packets can be configuration of the RMAP parameters can be found in the `.rdcu_pkt_mode_cfg file`.
found in the `TC_FILES` directory. The generated packets can be found in the `TC_FILES` directory.
### Decompression Options ### Decompression Options
| Options | Description | | Options | Description |
| ----------- | ------------------------------------------------ | |:----------- |:-------------------------------------------------|
| `-i <file>` | File containing the decompression information | | `-i <file>` | File containing the decompression information |
| `-d <file>` | File containing the compressed data | | `-d <file>` | File containing the compressed data |
| `-m <file>` | File containing the model of the compressed data | | `-m <file>` | File containing the model of the compressed data |
### Data Formart ### Guessing Options
| Options | Description |
|:------------------------|:--------------------------------------------------------------------------------|
| `--guess <mode>` | Search for a good configuration for compression \<mode\><sup>[4](#fnoot4)</sup> |
| `-d <file>` | File containing the data to be compressed |
| `-m <file>` | File containing the model of the data to be compressed |
| `--guess_level <level>` | Set guess level to \<level\> (optional)<sup>[5](#fnoot5)</sup> |
<a name="fnoot4">4</a>) **NOTE:** \<mode\> can be either the compression mode
number or the keyword: `RDCU`. The RDCU mode automatically selects the correct
RDCU-compatible compression mode depending on if the Model (-m) option is set.
<a name="fnoot5">5</a>) **Supported levels:**
| guess level | Description |
|:------------|:--------------------------------|
| `1` | fast mode (not implemented yet) |
| `2` | default mode |
| `3` | brute force |
**Example of Compression Parmeter guessing:**
``./cmp_tool --guess RDCU -d test_data/test_data1.dat -o myguess``
This command creates the file `myguess.cfg` with the guessed compression parameters.
### Data Format
The input data must be formatted as two hex numbers separated by a space. The input data must be formatted as two hex numbers separated by a space.
For example: `12 AB 34 CD`. For example: `12 AB 34 CD`.
## How to use the tool ## How to use the tool
A simple example to show how the compression tool works. A simple example to show how the compression tool works.
0. Run `make` to build the tool 0. Download the [tool][3] or run `make` to build the tool
1. Create a configuration file 1. Create a configuration file
* Create a cfg directory * Create a cfg directory
...@@ -55,38 +91,41 @@ A simple example to show how the compression tool works. ...@@ -55,38 +91,41 @@ A simple example to show how the compression tool works.
`./cmp_tool --diff_cfg > cfg/default_config_1d.cfg` `./cmp_tool --diff_cfg > cfg/default_config_1d.cfg`
* To create a default model mode configuration: * To create a default model mode configuration:
`./cmp_tool --model_cfg > cfg/default_config_model.cfg` `./cmp_tool --model_cfg > cfg/default_config_model.cfg`
* Change the the `samples` and `buffer_length` parameters from `0` to `50` in the `default_config_1d.cfg` and `default_config_model.cfg` files * Change the the **`samples`** and **`buffer_length`** parameters from `0` to `50`
in the `default_config_1d.cfg` and `default_config_model.cfg` files
2. Compress data with the default configurations: 2. Compress data with the default configurations:
* Create a directory for the compressed data. * Create a directory for the compressed data
`mkdir compressed` `mkdir compressed`
* 1d-differencing mode compression * 1d-differencing mode compression
`./cmp_tool -c cfg/default_config_1d.cfg -d test_data/test_data1.dat -o compressed/data1` `./cmp_tool -c cfg/default_config_1d.cfg -d test_data/test_data1.dat -o compressed/data1`
This creates these two files in the compressed directory:
This creates this two files in compressed directory: `data1.cmp` -> compressed `test_data1.dat` file
`data1.cmp ` -> compressed `test_data1.dat` data
`data1.info` -> decompression information for `data1.cmp` `data1.info` -> decompression information for `data1.cmp`
* Model mode compression * Model mode compression
`./cmp_tool -c cfg/default_config_model.cfg -d test_data/test_data2.dat -m test_data/test_data1.dat -o compressed/data2` `./cmp_tool -c cfg/default_config_model.cfg -d test_data/test_data2.dat -m test_data/test_data1.dat -o compressed/data2`
We use `test_data1.dat`as the first model for `test_data2.dat` We use `test_data1.dat` as the first model for `test_data2.dat`.
Creates this three files in compressed directory: Creates these three files in the compressed directory:
`data2.cmp ` -> compressed `test_data3.dat` data `data2.cmp ` -> compressed `test_data3.dat` file
`data2.info` -> decompression information for `data2.cmp` `data2.info` -> decompression information for `data2.cmp`
`data2_upmodel.dat` -> updated model used to **compress** the next data in model mode `data2_upmodel.dat` -> updated model used to **compress** the next data in model mode
3. Decompress the data 3. Decompress the data
* Create a directory for the decompressed data. * Create a directory for the decompressed data
`mkdir decompressed` `mkdir decompressed`
* Decompress `data1.cmp` * Decompress `data1.cmp`
`./cmp_tool -i compressed/data1.info -d compressed/data1.cmp -o decompressed/test_data1` `./cmp_tool -i compressed/data1.info -d compressed/data1.cmp -o decompressed/test_data1`
Creates this file in the decompressed directory:
`test_data1.dat ` -> decompressed `data1.cmp` file
* Decompress `data2.cmp` * Decompress `data2.cmp`
`./cmp_tool -i compressed/data2.info -d compressed/data2.cmp -m decompressed/test_data1.dat -o decompressed/test_data2` `./cmp_tool -i compressed/data2.info -d compressed/data2.cmp -m decompressed/test_data1.dat -o decompressed/test_data2`
As for the compression we use `test_data1.dat` as our model for decompression. As for the compression we use `test_data1.dat` as our model for decompression.
Creates these two files in the decompressed directory:
`test_data2.dat ` -> decompressed `data2.cmp` file
`data2_upmodel.dat` -> updated model used to **decompress** the next data in model mode
4. Bonus: Check if the decompressed data are equal to the original data 4. Bonus: Check if the decompressed data are equal to the original data
The moment of truth! The moment of truth!
`diff test_data/test_data1.dat decompressed/test_data1.dat` `diff test_data/test_data1.dat decompressed/test_data1.dat`
...@@ -95,6 +134,6 @@ A simple example to show how the compression tool works. ...@@ -95,6 +134,6 @@ A simple example to show how the compression tool works.
And also check if the updated model is the same And also check if the updated model is the same
`diff compressed/data2_upmodel.dat decompressed/test_data2_upmodel.dat` `diff compressed/data2_upmodel.dat decompressed/test_data2_upmodel.dat`
[1]: <https://gitlab.phaidra.org/loidoltd15/cmp_tool/-/issues> "issues" [1]: <https://gitlab.phaidra.org/loidoltd15/cmp_tool/-/issues> "issues"
[2]: <mailto:dominik.loidolt@univie.ac.at?subject=%5BIssue%5D%20Cmd_Tool> "email" [2]: <mailto:dominik.loidolt@univie.ac.at?subject=%5BIssue%5D%20Cmd_Tool> "email"
[3]: <https://gitlab.phaidra.org/loidoltd15/cmp_tool/-/releases> "release"
\ No newline at end of file
...@@ -19,30 +19,37 @@ ...@@ -19,30 +19,37 @@
* @see Data Compression User Manual PLATO-UVIE-PL-UM-0001 * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
*/ */
#include <stdio.h>
#include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <getopt.h> #include <getopt.h>
#include "include/cmp_tool_lib.h" #include "include/cmp_tool_lib.h"
#include "include/cmp_icu.h" #include "include/cmp_icu.h"
#include "include/cmp_rdcu.h"
#include "include/decmp.h" #include "include/decmp.h"
#include "include/cmp_guess.h"
#include "include/rdcu_pkt_to_file.h"
#define VERSION "0.06" #define VERSION "0.06"
#define BUFFER_LENGTH_DEF_FAKTOR 2
/* /*
* For long options that have no equivalent short option, use a * For long options that have no equivalent short option, use a
* non-character as a pseudo short option, starting with CHAR_MAX + 1. * non-character as a pseudo short option, starting with CHAR_MAX + 1.
*/ */
enum { enum {
RDCU_PKT_OPTION = CHAR_MAX + 1, DIFF_CFG_OPTION = CHAR_MAX + 1,
DIFF_CFG_OPTION, GUESS_OPTION,
RDCU_PAR_OPTION, GUESS_LEVEL,
RDCU_PKT_OPTION,
LAST_INFO, LAST_INFO,
}; };
static struct option const long_options[] = { static const struct option long_options[] = {
{"rdcu_par", no_argument, NULL, 'a'}, {"rdcu_par", no_argument, NULL, 'a'},
{"model_cfg", no_argument, NULL, 'n'}, {"model_cfg", no_argument, NULL, 'n'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
...@@ -50,10 +57,12 @@ static struct option const long_options[] = { ...@@ -50,10 +57,12 @@ static struct option const long_options[] = {
{"version", no_argument, NULL, 'V'}, {"version", no_argument, NULL, 'V'},
{"rdcu_pkt", no_argument, NULL, RDCU_PKT_OPTION}, {"rdcu_pkt", no_argument, NULL, RDCU_PKT_OPTION},
{"diff_cfg", no_argument, NULL, DIFF_CFG_OPTION}, {"diff_cfg", no_argument, NULL, DIFF_CFG_OPTION},
{"last_info", required_argument, NULL, LAST_INFO} {"guess", required_argument, NULL, GUESS_OPTION},
{"guess_level", required_argument, NULL, GUESS_LEVEL},
{"last_info", required_argument, NULL, LAST_INFO},
{NULL, 0, NULL, 0}
}; };
/* prefix of the generated output file names */ /* prefix of the generated output file names */
static const char *output_prefix = DEFAULT_OUTPUT_PREFIX; static const char *output_prefix = DEFAULT_OUTPUT_PREFIX;
...@@ -72,167 +81,16 @@ static const char *last_info_file_name; ...@@ -72,167 +81,16 @@ static const char *last_info_file_name;
static int verbose_en; static int verbose_en;
/* generate packets to setup a RDCU compression */ /* find a good set of compression parameters for a given dataset */
static int gen_rdcu_write_pkts(struct cmp_cfg *cfg) static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
{ int guess_level);
int error;
error = init_rmap_pkt_to_file();
if (error) {
fprintf(stderr, "%s: Read RMAP packet config file .rdcu_pkt_mode_cfg failed.\n",
PROGRAM_NAME);
return -1;
}
if (last_info_file_name) {
/* generation of packets for parallel read/write RDCU setup */
struct cmp_info last_info = {0};
error = read_cmp_info(last_info_file_name, &last_info, verbose_en);
if (error) {
fprintf(stderr, "%s: %s: Importing last decompression information file failed.\n",
PROGRAM_NAME, last_info_file_name);
return -1;
}
error = gen_rdcu_parallel_pkts(cfg, &last_info);
if (error)
return -1;
}
/* generation of packets for non-parallel read/write RDCU setup */
error = gen_write_rdcu_pkts(cfg);
if (error)
return -1;
return 0;
}
/* compress the data and write the results to files */ /* compress the data and write the results to files */
static int compression(struct cmp_cfg *cfg, struct cmp_info *info) static int compression(struct cmp_cfg *cfg, struct cmp_info *info);
{
int error;
uint32_t cmp_size_byte;
cfg->icu_output_buf = NULL;
if (rdcu_pkt_mode) {
printf("Generate compression setup packets ... \n");
error = gen_rdcu_write_pkts(cfg);
if (error)
goto error;
else
printf("... DONE\n");
}
printf("Compress data ... ");
if (cfg->buffer_length == 0) {
cfg->buffer_length = (cfg->samples+1) * BUFFER_LENGTH_DEF_FAKTOR; /* +1 to prevent malloc(0)*/
printf("No buffer_length parameter set. Use buffer_length = %u as compression buffer size.\n",
cfg->buffer_length);
}
cfg->icu_output_buf = malloc(cfg->buffer_length * size_of_a_sample(cfg->cmp_mode));
if (cfg->icu_output_buf == NULL) {
fprintf(stderr, "%s: Error allocating memory for output buffer.\n", PROGRAM_NAME);
goto error;
}
error = icu_compress_data(cfg, info);
if (error || info->cmp_err != 0) {
printf("Compression error %#X\n", info->cmp_err);
goto error;
} else
printf("DONE\n");
if (rdcu_pkt_mode) {
printf("Generate the read results packets ... ");
error = gen_read_rdcu_pkts(info);
if (error)
goto error;
else
printf("DONE\n");
}
printf("Write compressed data to file %s.cmp ... ", output_prefix);
/* length of cmp_size in bytes words (round up to 4 bytes) */
cmp_size_byte = (info->cmp_size + 31)/32 * 4;
error = write_cmp_data_file(cfg->icu_output_buf, cmp_size_byte,
output_prefix, ".cmp", verbose_en);
if (error)
goto error;
else
printf("DONE\n");
free(cfg->icu_output_buf);
cfg->icu_output_buf = NULL;
printf("Write decompression information to file %s.info ... ",
output_prefix);
error = write_info(info, output_prefix, print_rdcu_cfg);
if (error)
goto error;
else
printf("DONE\n");
if (verbose_en) {
printf("\n");
print_cmp_info(info);
printf("\n");
}
return 0;
error:
printf("FAILED\n");
free(cfg->icu_output_buf);
return -1;
}
/* decompress the data and write the results in file(s)*/ /* decompress the data and write the results in file(s)*/
static int decompression(uint32_t *decomp_input_buf, uint16_t *input_model_buf, static int decompression(uint32_t *decomp_input_buf, uint16_t *input_model_buf,
struct cmp_info *info) struct cmp_info *info);
{
int error;
uint16_t *decomp_output;
printf("Decompress data ... ");
if (info->samples_used == 0)
return 0; /* nothing to decompress */
decomp_output = malloc(info->samples_used *
size_of_a_sample(info->cmp_mode_used));
if (decomp_output == NULL) {
printf("FAILED\n");
fprintf(stderr, "%s: Error allocating memory for decompressed data.\n", PROGRAM_NAME);
return -1;
}
error = decompress_data(decomp_input_buf, input_model_buf, info,
decomp_output);
if (error) {
printf("FAILED\n");
free(decomp_output);
return -1;
}
else
printf("DONE\n");
printf("Write decompressed data to file %s.dat ... ", output_prefix);
error = write_to_file16(decomp_output, info->samples_used,
output_prefix, ".dat", verbose_en);
free(decomp_output);
if (error) {
printf("FAILED\n");
return -1;
} else
printf("DONE\n");
return 0;
}
/** /**
...@@ -254,10 +112,14 @@ int main(int argc, char **argv) ...@@ -254,10 +112,14 @@ int main(int argc, char **argv)
const char *info_file_name = NULL; const char *info_file_name = NULL;
const char *data_file_name = NULL; const char *data_file_name = NULL;
const char *model_file_name = NULL; const char *model_file_name = NULL;
const char *guess_cmp_mode = NULL;
const char *program_name = argv[0];
int cmp_operation = 0;
int print_model_cfg = 0; int print_model_cfg = 0;
int guess_operation = 0;
int guess_level = DEFAULT_GUESS_LEVEL;
int print_diff_cfg = 0; int print_diff_cfg = 0;
int cmp_operation = 0;
struct cmp_cfg cfg = {0}; /* compressor configuration struct */ struct cmp_cfg cfg = {0}; /* compressor configuration struct */
struct cmp_info info = {0}; /* decompression information struct */ struct cmp_info info = {0}; /* decompression information struct */
...@@ -268,7 +130,7 @@ int main(int argc, char **argv) ...@@ -268,7 +130,7 @@ int main(int argc, char **argv)
/* show help if no arguments are provided */ /* show help if no arguments are provided */
if (argc < 2) { if (argc < 2) {
Print_Help(*argv); print_help(program_name);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -286,7 +148,7 @@ int main(int argc, char **argv) ...@@ -286,7 +148,7 @@ int main(int argc, char **argv)
data_file_name = optarg; data_file_name = optarg;
break; break;
case 'h': /* --help */ case 'h': /* --help */
Print_Help(*argv); print_help(argv[0]);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
case 'i': case 'i':
...@@ -305,12 +167,19 @@ int main(int argc, char **argv) ...@@ -305,12 +167,19 @@ int main(int argc, char **argv)
verbose_en = 1; verbose_en = 1;
break; break;
case 'V': /* --version */ case 'V': /* --version */
printf("%s %s\n", PROGRAM_NAME, VERSION); printf("%s version %s\n", PROGRAM_NAME, VERSION);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
case DIFF_CFG_OPTION: case DIFF_CFG_OPTION:
print_diff_cfg = 1; print_diff_cfg = 1;
break; break;
case GUESS_OPTION:
guess_operation = 1;
guess_cmp_mode = optarg;
break;
case GUESS_LEVEL:
guess_level = atoi(optarg);
break;
case RDCU_PKT_OPTION: case RDCU_PKT_OPTION:
rdcu_pkt_mode = 1; rdcu_pkt_mode = 1;
break; break;
...@@ -319,11 +188,39 @@ int main(int argc, char **argv) ...@@ -319,11 +188,39 @@ int main(int argc, char **argv)
last_info_file_name = optarg; last_info_file_name = optarg;
break; break;
default: default:
Print_Help(*argv); print_help(program_name);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
} }
} }
argc -= optind;
argv += optind;
if (argc > 0) {
printf("%s: To many arguments.\n", PROGRAM_NAME);
print_help(argv[0]);
exit(EXIT_FAILURE);
}
#if 0
if (argc > 0) {
if(!data_file_name)
data_file_name = argv[0];
else {
printf("You can define the data file using either the -d option or the first argument, but not both.\n");
print_help(program_name);
exit(EXIT_FAILURE);
}
}
if (argc > 1) {
if(!model_file_name)
model_file_name = argv[1];
else {
printf("You can define the model file using either the -m option or the second argument, but not both.\n");
print_help(program_name);
exit(EXIT_FAILURE);
}
}
#endif
if (print_model_cfg == 1) { if (print_model_cfg == 1) {
print_cfg(&DEFAULT_CFG_MODEL, print_rdcu_cfg); print_cfg(&DEFAULT_CFG_MODEL, print_rdcu_cfg);
...@@ -340,22 +237,22 @@ int main(int argc, char **argv) ...@@ -340,22 +237,22 @@ int main(int argc, char **argv)
VERSION); VERSION);
printf("#########################################################\n\n"); printf("#########################################################\n\n");
if (!cfg_file_name && !info_file_name) { if (!data_file_name) {
fprintf(stderr, "%s: No configuration file (-c option) or decompression information file (-i option) specified.\n", fprintf(stderr, "%s: No data file (-d option) specified.\n",
PROGRAM_NAME); PROGRAM_NAME);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!data_file_name) { if (!cfg_file_name && !info_file_name && !guess_operation) {
fprintf(stderr, "%s: No data file (-d option) specified.\n", fprintf(stderr, "%s: No configuration file (-c option) or decompression information file (-i option) specified.\n",
PROGRAM_NAME); PROGRAM_NAME);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* read input data and .cfg or .info */ /* read input data and .cfg or .info */
if (cmp_operation) { /* compression mode */ if (cmp_operation || guess_operation) { /* compression mode */
printf("### Compression ###\n"); if (cmp_operation) {
/* printf("### Compression ###\n"); */
printf("Importing configuration file %s ... ", cfg_file_name); printf("Importing configuration file %s ... ", cfg_file_name);
error = read_cmp_cfg(cfg_file_name, &cfg, verbose_en); error = read_cmp_cfg(cfg_file_name, &cfg, verbose_en);
if (error) if (error)
...@@ -363,19 +260,26 @@ int main(int argc, char **argv) ...@@ -363,19 +260,26 @@ int main(int argc, char **argv)
else else
printf("DONE\n"); printf("DONE\n");
}
printf("Importing data file %s ... ", data_file_name);
/* count the samples in the data file when samples == 0 */ /* count the samples in the data file when samples == 0 */
if (cfg.samples == 0) { if (cfg.samples == 0) {
size = read_file16(data_file_name, NULL, 0, 0); size = read_file16(data_file_name, NULL, 0, 0);
if (size < 0) if (size < 0)
goto fail; goto fail;
/* TODO: check size%size_of_a_sample(cfg.cmp_mode) == 0 */ if (size%size_of_a_sample(cfg.cmp_mode) != 0) {
fprintf(stderr, "\n%s: %s: Error: The data file is not correct formatted. Expected multiple of %zu hex words.\n",
PROGRAM_NAME, data_file_name, size_of_a_sample(cfg.cmp_mode));
goto fail;
}
cfg.samples = size/size_of_a_sample(cfg.cmp_mode); cfg.samples = size/size_of_a_sample(cfg.cmp_mode);
printf("No samples parameter set. Use samples = %u.\n", printf("\nNo samples parameter set. Use samples = %u.\n... ",
cfg.samples); cfg.samples);
} }
printf("Importing data file %s ... ", data_file_name);
cfg.input_buf = malloc(cfg.samples * size_of_a_sample(cfg.cmp_mode)); cfg.input_buf = malloc(cfg.samples * size_of_a_sample(cfg.cmp_mode));
if (!cfg.input_buf) { if (!cfg.input_buf) {
fprintf(stderr, "%s: Error allocating memory for input data buffer.\n", PROGRAM_NAME); fprintf(stderr, "%s: Error allocating memory for input data buffer.\n", PROGRAM_NAME);
...@@ -392,8 +296,8 @@ int main(int argc, char **argv) ...@@ -392,8 +296,8 @@ int main(int argc, char **argv)
} else { /* decompression mode*/ } else { /* decompression mode*/
uint32_t cmp_size_byte; uint32_t cmp_size_byte;
printf("### Decompression ###\n\n"); /* printf("### Decompression ###\n\n"); */
printf("Importing decompression information file ... "); printf("Importing decompression information file %s ... ", info_file_name);
error = read_cmp_info(info_file_name, &info, verbose_en); error = read_cmp_info(info_file_name, &info, verbose_en);
if (error) if (error)
...@@ -418,9 +322,10 @@ int main(int argc, char **argv) ...@@ -418,9 +322,10 @@ int main(int argc, char **argv)
printf("DONE\n"); printf("DONE\n");
} }
/* read in model for compressed or decompression */ /* read in model */
if ((cmp_operation && model_mode_is_used(cfg.cmp_mode)) || if ((cmp_operation && model_mode_is_used(cfg.cmp_mode)) ||
(!cmp_operation && model_mode_is_used(info.cmp_mode_used))) { (!cmp_operation && model_mode_is_used(info.cmp_mode_used)) ||
(guess_operation && model_file_name)) {
uint32_t model_length; uint32_t model_length;
if (!model_file_name) { if (!model_file_name) {
...@@ -430,7 +335,7 @@ int main(int argc, char **argv) ...@@ -430,7 +335,7 @@ int main(int argc, char **argv)
printf("Importing model file %s ... ", model_file_name); printf("Importing model file %s ... ", model_file_name);
if (cmp_operation) if (cmp_operation || guess_operation)
model_length = cfg.samples; model_length = cfg.samples;
else else
model_length = info.samples_used; model_length = info.samples_used;
...@@ -447,15 +352,18 @@ int main(int argc, char **argv) ...@@ -447,15 +352,18 @@ int main(int argc, char **argv)
else else
printf("DONE\n"); printf("DONE\n");
if (cmp_operation) if (cmp_operation || guess_operation)
cfg.model_buf = input_model_buf; cfg.model_buf = input_model_buf;
} }
if (cmp_operation) { /* perform a compression */ if (guess_operation) {
error = guess_cmp_pars(&cfg, guess_cmp_mode, guess_level);
if (error)
goto fail;
} else if (cmp_operation) { /* perform a compression */
error = compression(&cfg, &info); error = compression(&cfg, &info);
if (error) if (error)
goto fail; goto fail;
} else { /* perform a decompression */ } else { /* perform a decompression */
error = decompression(decomp_input_buf, input_model_buf, &info); error = decompression(decomp_input_buf, input_model_buf, &info);
if (error) if (error)
...@@ -463,8 +371,9 @@ int main(int argc, char **argv) ...@@ -463,8 +371,9 @@ int main(int argc, char **argv)
} }
/* write our the updated model for compressed or decompression */ /* write our the updated model for compressed or decompression */
if ((cmp_operation && model_mode_is_used(cfg.cmp_mode)) || if (!guess_operation &&
(!cmp_operation && model_mode_is_used(info.cmp_mode_used))) { ((cmp_operation && model_mode_is_used(cfg.cmp_mode)) ||
(!cmp_operation && model_mode_is_used(info.cmp_mode_used)))) {
printf("Write updated model to file %s_upmodel.dat ... ", printf("Write updated model to file %s_upmodel.dat ... ",
output_prefix); output_prefix);
error = write_to_file16(input_model_buf, info.samples_used, error = write_to_file16(input_model_buf, info.samples_used,
...@@ -475,7 +384,6 @@ int main(int argc, char **argv) ...@@ -475,7 +384,6 @@ int main(int argc, char **argv)
printf("DONE\n"); printf("DONE\n");
} }
free(cfg.input_buf); free(cfg.input_buf);
free(decomp_input_buf); free(decomp_input_buf);
free(input_model_buf); free(input_model_buf);
...@@ -491,3 +399,208 @@ fail: ...@@ -491,3 +399,208 @@ fail:
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* generate packets to setup a RDCU compression */
static int gen_rdcu_write_pkts(struct cmp_cfg *cfg)
{
int error;
error = init_rmap_pkt_to_file();
if (error) {
fprintf(stderr, "%s: Read RMAP packet config file .rdcu_pkt_mode_cfg failed.\n",
PROGRAM_NAME);
return -1;
}
if (last_info_file_name) {
/* generation of packets for parallel read/write RDCU setup */
struct cmp_info last_info = {0};
error = read_cmp_info(last_info_file_name, &last_info, verbose_en);
if (error) {
fprintf(stderr, "%s: %s: Importing last decompression information file failed.\n",
PROGRAM_NAME, last_info_file_name);
return -1;
}
error = gen_rdcu_parallel_pkts(cfg, &last_info);
if (error)
return -1;
}
/* generation of packets for non-parallel read/write RDCU setup */
error = gen_write_rdcu_pkts(cfg);
if (error)
return -1;
return 0;
}
/* find a good set of compression parameters for a given dataset */
static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode,
int guess_level)
{
int error;
uint32_t cmp_size;
float cr;
printf("Search for a good set of compression parameters (level: %d) ... ", guess_level);
if (!strcmp(guess_cmp_mode, "RDCU")) {
if (cfg->model_buf)
cfg->cmp_mode = CMP_GUESS_DEF_MODE_MODEL;
else
cfg->cmp_mode = CMP_GUESS_DEF_MODE_DIFF;
} else {
error = cmp_mode_parse(guess_cmp_mode, &cfg->cmp_mode);
if (error) {
fprintf(stderr, "%s: Error: unknown compression mode: %s\n", PROGRAM_NAME, guess_cmp_mode);
return -1;
}
}
if (model_mode_is_used(cfg->cmp_mode) && !cfg->model_buf) {
fprintf(stderr, "%s: Error: model mode needs model data (-m option)\n", PROGRAM_NAME);
return -1;
}
cmp_size = cmp_guess(cfg, guess_level);
if (!cmp_size)
return -1;
printf("DONE\n");
printf("Write the guessed compression configuration to file %s.cfg ... ", output_prefix);
error = write_cfg(cfg, output_prefix, print_rdcu_cfg, verbose_en);
if (error)
return -1;
printf("DONE\n");
cr = (8.0 * cfg->samples * size_of_a_sample(cfg->cmp_mode))/cmp_size;
printf("Guessed parameters can compress the data with a CR of %.2f.\n", cr);
return 0;
}
/* compress the data and write the results to files */
static int compression(struct cmp_cfg *cfg, struct cmp_info *info)
{
int error;
uint32_t cmp_size_byte;
cfg->icu_output_buf = NULL;
if (cfg->buffer_length == 0) {
cfg->buffer_length = (cfg->samples+1) * BUFFER_LENGTH_DEF_FAKTOR; /* +1 to prevent malloc(0)*/
printf("No buffer_length parameter set. Use buffer_length = %u as compression buffer size.\n",
cfg->buffer_length);
}
if (rdcu_pkt_mode) {
printf("Generate compression setup packets ...\n");
error = gen_rdcu_write_pkts(cfg);
if (error)
goto error_cleanup;
else
printf("... DONE\n");
}
printf("Compress data ... ");
cfg->icu_output_buf = malloc(cfg->buffer_length * size_of_a_sample(cfg->cmp_mode));
if (cfg->icu_output_buf == NULL) {
fprintf(stderr, "%s: Error allocating memory for output buffer.\n", PROGRAM_NAME);
goto error_cleanup;
}
error = icu_compress_data(cfg, info);
if (error || info->cmp_err != 0) {
printf("\nCompression error 0x%02X\n... ", info->cmp_err);
if ((info->cmp_err >> SMALL_BUFFER_ERR_BIT) & 1U)
fprintf(stderr, "%s: the buffer for the compressed data is too small. Try a larger buffer_length parameter.\n", PROGRAM_NAME);
goto error_cleanup;
} else
printf("DONE\n");
if (rdcu_pkt_mode) {
printf("Generate the read results packets ... ");
error = gen_read_rdcu_pkts(info);
if (error)
goto error_cleanup;
else
printf("DONE\n");
}
printf("Write compressed data to file %s.cmp ... ", output_prefix);
/* length of cmp_size in bytes words (round up to 4 bytes) */
cmp_size_byte = (info->cmp_size + 31)/32 * 4;
error = write_cmp_data_file(cfg->icu_output_buf, cmp_size_byte,
output_prefix, ".cmp", verbose_en);
if (error)
goto error_cleanup;
else
printf("DONE\n");
free(cfg->icu_output_buf);
cfg->icu_output_buf = NULL;
printf("Write decompression information to file %s.info ... ",
output_prefix);
error = write_info(info, output_prefix, print_rdcu_cfg);
if (error)
goto error_cleanup;
else
printf("DONE\n");
if (verbose_en) {
printf("\n");
print_cmp_info(info);
printf("\n");
}
return 0;
error_cleanup:
free(cfg->icu_output_buf);
return -1;
}
/* decompress the data and write the results in file(s)*/
static int decompression(uint32_t *decomp_input_buf, uint16_t *input_model_buf,
struct cmp_info *info)
{
int error;
uint16_t *decomp_output;
printf("Decompress data ... ");
if (info->samples_used == 0)
return 0; /* nothing to decompress */
decomp_output = malloc(info->samples_used *
size_of_a_sample(info->cmp_mode_used));
if (decomp_output == NULL) {
fprintf(stderr, "%s: Error allocating memory for decompressed data.\n", PROGRAM_NAME);
return -1;
}
error = decompress_data(decomp_input_buf, input_model_buf, info,
decomp_output);
if (error) {
free(decomp_output);
return -1;
}
printf("DONE\n");
printf("Write decompressed data to file %s.dat ... ", output_prefix);
error = write_to_file16(decomp_output, info->samples_used,
output_prefix, ".dat", verbose_en);
free(decomp_output);
if (error)
return -1;
printf("DONE\n");
return 0;
}
/**
* @file cmp_guess.h
* @author Dominik Loidolt (dominik.loidolt@univie.ac.at),
* @date 2020
*
* @copyright GPLv2
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* @brief helps the user to find a good compression parameters for a given
* dataset
*/
#ifndef CMP_GUESS_H
#define CMP_GUESS_H
#include "cmp_support.h"
#define DEFAULT_GUESS_LEVEL 2
#define CMP_GUESS_DEF_MODE_DIFF MODE_DIFF_ZERO
#define CMP_GUESS_DEF_MODE_MODEL MODE_MODEL_MULTI
/* how often the model is updated before it is reset default value */
#define CMP_GUESS_N_MODEL_UPDATE_DEF 8
uint32_t cmp_guess(struct cmp_cfg *cfg, int level);
void cmp_guess_set_model_updates(int n_model_updates);
uint16_t cmp_guess_model_value(int n_model_updates);
#endif /* CMP_GUESS_H */
...@@ -25,4 +25,9 @@ ...@@ -25,4 +25,9 @@
int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info); int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info);
int cmp_pre_process(struct cmp_cfg *cfg);
int cmp_map_to_pos(struct cmp_cfg *cfg);
uint32_t cmp_encode_data(struct cmp_cfg *cfg);
#endif /* _CMP_ICU_H_ */ #endif /* _CMP_ICU_H_ */
...@@ -62,6 +62,8 @@ ...@@ -62,6 +62,8 @@
#define SAM2BYT \ #define SAM2BYT \
2 /* sample to byte conversion factor; one samples has 16 bits (2 bytes) */ 2 /* sample to byte conversion factor; one samples has 16 bits (2 bytes) */
#define CMP_GOOD_SPILL_DIFF_MULTI 2 /* good guess for the spill parameter using the MODE_DIFF_MULTI */
/** /**
* @brief The cmp_cfg structure can contain the complete configuration of the HW as * @brief The cmp_cfg structure can contain the complete configuration of the HW as
* well as the SW compressor. * well as the SW compressor.
...@@ -163,6 +165,7 @@ int model_mode_is_used(unsigned int cmp_mode); ...@@ -163,6 +165,7 @@ int model_mode_is_used(unsigned int cmp_mode);
int diff_mode_is_used(unsigned int cmp_mode); int diff_mode_is_used(unsigned int cmp_mode);
int raw_mode_is_used(unsigned int cmp_mode); int raw_mode_is_used(unsigned int cmp_mode);
int rdcu_supported_mode_is_used(unsigned int cmp_mode); int rdcu_supported_mode_is_used(unsigned int cmp_mode);
int cmp_mode_available(unsigned int cmp_mode);
int zero_escape_mech_is_used(unsigned int cmp_mode); int zero_escape_mech_is_used(unsigned int cmp_mode);
int multi_escape_mech_is_used(unsigned int cmp_mode); int multi_escape_mech_is_used(unsigned int cmp_mode);
......
...@@ -15,12 +15,9 @@ ...@@ -15,12 +15,9 @@
* more details. * more details.
*/ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "cmp_support.h" #include "cmp_support.h"
#include "rdcu_pkt_to_file.h"
#define PROGRAM_NAME "cmp_tool" #define PROGRAM_NAME "cmp_tool"
#define MAX_CONFIG_LINE 256 #define MAX_CONFIG_LINE 256
...@@ -29,7 +26,7 @@ ...@@ -29,7 +26,7 @@
#define BUFFER_LENGTH_DEF_FAKTOR 2 #define BUFFER_LENGTH_DEF_FAKTOR 2
void Print_Help(const char *argv); void print_help(const char *program_name);
int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en); int read_cmp_cfg(const char *file_name, struct cmp_cfg *cfg, int verbose_en);
int read_cmp_info(const char *file_name, struct cmp_info *info, int verbose_en); int read_cmp_info(const char *file_name, struct cmp_info *info, int verbose_en);
...@@ -38,7 +35,7 @@ ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t n_word, ...@@ -38,7 +35,7 @@ ssize_t read_file8(const char *file_name, uint8_t *buf, uint32_t n_word,
int verbose_en); int verbose_en);
ssize_t read_file16(const char *file_name, uint16_t *buf, uint32_t samples, ssize_t read_file16(const char *file_name, uint16_t *buf, uint32_t samples,
int verbose_en); int verbose_en);
ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t buf_len, ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t samples,
int verbose_en); int verbose_en);
int write_cmp_data_file(const void *buf, uint32_t buf_size, const char int write_cmp_data_file(const void *buf, uint32_t buf_size, const char
...@@ -46,6 +43,9 @@ int write_cmp_data_file(const void *buf, uint32_t buf_size, const char ...@@ -46,6 +43,9 @@ int write_cmp_data_file(const void *buf, uint32_t buf_size, const char
int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char int write_to_file16(const uint16_t *buf, uint32_t buf_len, const char
*output_prefix, const char *name_extension, int verbose); *output_prefix, const char *name_extension, int verbose);
int write_info(const struct cmp_info *info, const char *output_prefix, int write_info(const struct cmp_info *info, const char *output_prefix,
int machine_cfg); int rdcu_cfg);
int write_cfg(const struct cmp_cfg *cfg, const char *output_prefix, int rdcu_cfg,
int verbose);
void print_cfg(const struct cmp_cfg *cfg, int rdcu_cfg); void print_cfg(const struct cmp_cfg *cfg, int rdcu_cfg);
uint32_t cmp_mode_parse(const char *cmp_mode_str, uint32_t *cmp_mode);
...@@ -17,9 +17,6 @@ ...@@ -17,9 +17,6 @@
*/ */
#include <stddef.h>
#include <stdio.h>
#include "../include/cmp_data_types.h" #include "../include/cmp_data_types.h"
#include "../include/cmp_support.h" #include "../include/cmp_support.h"
#include "../include/cmp_debug.h" #include "../include/cmp_debug.h"
...@@ -295,7 +292,7 @@ struct S_FX_EFX add_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b) ...@@ -295,7 +292,7 @@ struct S_FX_EFX add_S_FX_EFX(struct S_FX_EFX a, struct S_FX_EFX b)
* @note change the data buffer in-place * @note change the data buffer in-place
* @note the exposure_flags are not rounded * @note the exposure_flags are not rounded
* *
* @param data_buf a S_FX_EFX formatted data buffer * @param data S_FX_EFX formatted data buffer
* @param samples the size of the data buffer measured in S_FX_EFX samples * @param samples the size of the data buffer measured in S_FX_EFX samples
* @param round number of bits to round; if zero no rounding takes place * @param round number of bits to round; if zero no rounding takes place
* *
...@@ -318,8 +315,7 @@ int lossy_rounding_S_FX_EFX(struct S_FX_EFX *data, unsigned int samples, ...@@ -318,8 +315,7 @@ int lossy_rounding_S_FX_EFX(struct S_FX_EFX *data, unsigned int samples,
if (round == 0) if (round == 0)
return 0; return 0;
for (i = 0; i < samples; i++) for (i = 0; i < samples; i++) {
{
data[i].FX = round_fwd(data[i].FX, round); data[i].FX = round_fwd(data[i].FX, round);
data[i].EFX = round_fwd(data[i].EFX, round); data[i].EFX = round_fwd(data[i].EFX, round);
} }
...@@ -431,8 +427,7 @@ int lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int samples, ...@@ -431,8 +427,7 @@ int lossy_rounding_S_FX_NCOB(struct S_FX_NCOB *data_buf, unsigned int samples,
if (round == 0) if (round == 0)
return 0; return 0;
for (i = 0; i < samples; i++) for (i = 0; i < samples; i++) {
{
data_buf[i].FX = round_fwd(data_buf[i].FX, round); data_buf[i].FX = round_fwd(data_buf[i].FX, round);
data_buf[i].NCOB_X = round_fwd(data_buf[i].NCOB_X, round); data_buf[i].NCOB_X = round_fwd(data_buf[i].NCOB_X, round);
data_buf[i].NCOB_Y = round_fwd(data_buf[i].NCOB_Y, round); data_buf[i].NCOB_Y = round_fwd(data_buf[i].NCOB_Y, round);
...@@ -559,8 +554,7 @@ int lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf, ...@@ -559,8 +554,7 @@ int lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
if (round == 0) /* round 0 means loss less compression, no further processing is necessary */ if (round == 0) /* round 0 means loss less compression, no further processing is necessary */
return 0; return 0;
for (i = 0; i < samples; i++) for (i = 0; i < samples; i++) {
{
data_buf[i].FX = round_fwd(data_buf[i].FX, round); data_buf[i].FX = round_fwd(data_buf[i].FX, round);
data_buf[i].NCOB_X = round_fwd(data_buf[i].NCOB_X, round); data_buf[i].NCOB_X = round_fwd(data_buf[i].NCOB_X, round);
data_buf[i].NCOB_Y = round_fwd(data_buf[i].NCOB_Y, round); data_buf[i].NCOB_Y = round_fwd(data_buf[i].NCOB_Y, round);
...@@ -587,8 +581,7 @@ int de_lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf, ...@@ -587,8 +581,7 @@ int de_lossy_rounding_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
if (round_used == 0) /* round 0 means loss less compression, no further processing is necessary */ if (round_used == 0) /* round 0 means loss less compression, no further processing is necessary */
return 0; return 0;
for (i = 0; i < samples_used; i++) for (i = 0; i < samples_used; i++) {
{
uint32_t mask = (~0U << (32-round_used)); uint32_t mask = (~0U << (32-round_used));
if (data_buf[i].FX & mask) { if (data_buf[i].FX & mask) {
......
lib/cmp_guess.c 0 → 100644
+ 319
0
View file @ a7b4ee0b
/**
* @file cmp_guess.c
* @author Dominik Loidolt (dominik.loidolt@univie.ac.at),
* @date 2021
*
* @copyright GPLv2
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* @brief helps the user to find a good compression parameters for a given
* dataset
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../include/cmp_icu.h"
#include "../include/cmp_guess.h"
/* how often the model is updated before it is rested */
static int num_model_updates = CMP_GUESS_N_MODEL_UPDATE_DEF;
/**
* @brief sets how often the model is updated before model reset for the
* cmp_guess function
* @note the default value is CMP_GUESS_N_MODEL_UPDATE_DEF
* @note this is needed to guess a good model_value
*
* @param n_model_updates number of model updates
*/
void cmp_guess_set_model_updates(int n_model_updates)
{
num_model_updates = n_model_updates;
}
/**
* @brief guess a good model value
*
* @param n_model_updates number of model updates
*
* @returns guessed model_value
*/
uint16_t cmp_guess_model_value(int n_model_updates)
{
if (n_model_updates <= 2)
return 8;
if (n_model_updates <= 5)
return 10;
if (n_model_updates <= 11)
return 11;
if (n_model_updates <= 21)
return 12;
else
return 13;
}
/**
* @brief guess a good configuration with pre_cal_method
*
* @param cfg compression configuration structure
*
* @returns the size in bits of the compressed data of the guessed
* configuration; 0 on error
*/
static uint32_t pre_cal_method(struct cmp_cfg *cfg)
{
uint32_t g;
uint32_t cmp_size;
uint32_t cmp_size_best = ~0U;
uint32_t golomb_par_best = 0;
uint32_t spill_best = 0;
for (g = MIN_RDCU_GOLOMB_PAR; g < MAX_RDCU_GOLOMB_PAR; ++g) {
uint32_t s = cmp_get_good_spill(g, cfg->cmp_mode);
cfg->golomb_par = g;
cfg->spill = s;
cmp_size = cmp_encode_data(cfg);
if (cmp_size == 0) {
return 0;
} else if (cmp_size < cmp_size_best) {
cmp_size_best = cmp_size;
golomb_par_best = g;
spill_best = s;
}
}
cfg->golomb_par = golomb_par_best;
cfg->spill = spill_best;
return cmp_size_best;
}
/**
* @brief guess a good configuration with brute force method
*
* @param cfg compression configuration structure
*
* @returns the size in bits of the compressed data of the guessed
* configuration; 0 on error
*/
#define CMP_GUESS_MAX_CAL_STEPS 20274
static uint32_t brute_force(struct cmp_cfg *cfg)
{
uint32_t g, s;
uint32_t n_cal_steps = 0, last = 0;
const uint32_t max_cal_steps = CMP_GUESS_MAX_CAL_STEPS;
uint32_t cmp_size;
uint32_t cmp_size_best = ~0U;
uint32_t golomb_par_best = 0;
uint32_t spill_best = 0;
uint32_t percent;
/* short cut for zero escape mechanism */
if (zero_escape_mech_is_used(cfg->cmp_mode))
return pre_cal_method(cfg);
printf("0%%... ");
fflush(stdout);
for (g = MIN_RDCU_GOLOMB_PAR; g < MAX_RDCU_GOLOMB_PAR; ++g) {
for (s = MIN_RDCU_SPILL; s < get_max_spill(g, cfg->cmp_mode); ++s) {
cfg->golomb_par = g;
cfg->spill = s;
cmp_size = cmp_encode_data(cfg);
if (cmp_size == 0) {
return 0;
} else if (cmp_size < cmp_size_best) {
cmp_size_best = cmp_size;
golomb_par_best = g;
spill_best = s;
}
}
n_cal_steps += s;
percent = n_cal_steps*100/max_cal_steps;
if (percent > 5+last && percent < 100) {
last = percent;
printf("%u%%... ", percent);
fflush(stdout);
}
}
printf("100%% ");
cfg->golomb_par = golomb_par_best;
cfg->spill = spill_best;
return cmp_size_best;
}
/**
* @brief guessed rdcu specific adaptive parameters
*
* @param cfg compression configuration structure
* @note internal use only
*/
static void add_rdcu_pars_internal(struct cmp_cfg *cfg)
{
if (cfg->golomb_par == MIN_RDCU_GOLOMB_PAR) {
cfg->ap1_golomb_par = cfg->golomb_par + 1;
cfg->ap2_golomb_par = cfg->golomb_par + 2;
} else if (cfg->golomb_par == MAX_RDCU_GOLOMB_PAR) {
cfg->ap1_golomb_par = cfg->golomb_par - 2;
cfg->ap2_golomb_par = cfg->golomb_par - 1;
} else {
cfg->ap1_golomb_par = cfg->golomb_par - 1;
cfg->ap2_golomb_par = cfg->golomb_par + 1;
}
cfg->ap1_spill = cmp_get_good_spill(cfg->ap1_golomb_par, cfg->cmp_mode);
cfg->ap2_spill = cmp_get_good_spill(cfg->ap2_golomb_par, cfg->cmp_mode);
if (model_mode_is_used(cfg->cmp_mode)) {
cfg->rdcu_data_adr = DEFAULT_CFG_MODEL.rdcu_data_adr;
cfg->rdcu_model_adr = DEFAULT_CFG_MODEL.rdcu_model_adr;
cfg->rdcu_new_model_adr = DEFAULT_CFG_MODEL.rdcu_new_model_adr;
cfg->rdcu_buffer_adr = DEFAULT_CFG_MODEL.rdcu_buffer_adr;
} else {
cfg->rdcu_data_adr = DEFAULT_CFG_DIFF.rdcu_data_adr;
cfg->rdcu_model_adr = DEFAULT_CFG_DIFF.rdcu_model_adr;
cfg->rdcu_new_model_adr = DEFAULT_CFG_DIFF.rdcu_new_model_adr;
cfg->rdcu_buffer_adr = DEFAULT_CFG_DIFF.rdcu_buffer_adr;
}
}
/**
* @brief guess a good compression configuration
* @details use the referenced in the cfg struct (samples, input_buf, model_buf
* (optional)) and the cmp_mode to find a good set of compression parameters
* @note compression parameters in the cfg struct (golomb_par, spill, model_value,
* ap1_.., ap2_.., buffer_length, ...) are overwritten by this function
*
* @param cfg compression configuration structure
* @param level guess_level 1 -> fast; 2 -> default; 3 -> slow(brute force)
*
* @returns the size in bits of the compressed data of the guessed
* configuration; 0 on error
*/
uint32_t cmp_guess(struct cmp_cfg *cfg, int level)
{
size_t size;
struct cmp_cfg work_cfg;
int err;
uint32_t cmp_size = 0;
if (!cfg)
return 0;
if (!cfg->input_buf)
return 0;
if (!rdcu_supported_mode_is_used(cfg->cmp_mode)) {
printf("This compression mode is not implied yet.\n");
return 0;
}
/* make a working copy of the input data (and model) because the
* following function works inplace */
work_cfg = *cfg;
work_cfg.input_buf = NULL;
work_cfg.model_buf = NULL;
work_cfg.icu_new_model_buf = NULL;
work_cfg.icu_output_buf = NULL;
work_cfg.buffer_length = 0;
size = cfg->samples * size_of_a_sample(work_cfg.cmp_mode);
if (size == 0)
goto error;
work_cfg.input_buf = malloc(size);
if (!work_cfg.input_buf) {
printf("malloc() failed!\n");
goto error;
}
memcpy(work_cfg.input_buf, cfg->input_buf, size);
if (cfg->model_buf && model_mode_is_used(cfg->cmp_mode)) {
work_cfg.model_buf = malloc(size);
if (!work_cfg.model_buf) {
printf("malloc() failed!\n");
goto error;
}
memcpy(work_cfg.model_buf, cfg->model_buf, size);
work_cfg.icu_new_model_buf = malloc(size);
if (!work_cfg.icu_new_model_buf) {
printf("malloc() failed!\n");
goto error;
}
}
err = cmp_pre_process(&work_cfg);
if (err)
goto error;
err = cmp_map_to_pos(&work_cfg);
if (err)
goto error;
/* find the best parameters */
switch (level) {
case 3:
cmp_size = brute_force(&work_cfg);
break;
case 1:
printf("guess level 1 not implied yet use guess level 2\n");
/* fall through */
case 2:
cmp_size = pre_cal_method(&work_cfg);
break;
default:
fprintf(stderr, "cmp_tool: guess level not supported!\n");
goto error;
break;
}
if (!cmp_size)
goto error;
free(work_cfg.input_buf);
free(work_cfg.model_buf);
free(work_cfg.icu_new_model_buf);
cfg->golomb_par = work_cfg.golomb_par;
cfg->spill = work_cfg.spill;
cfg->model_value = cmp_guess_model_value(num_model_updates);
if (rdcu_supported_mode_is_used(cfg->cmp_mode))
add_rdcu_pars_internal(cfg);
cfg->buffer_length = ((cmp_size + 32)&~0x1FU)/(size_of_a_sample(work_cfg.cmp_mode)*8);
return cmp_size;
error:
free(work_cfg.input_buf);
free(work_cfg.model_buf);
free(work_cfg.icu_new_model_buf);
return 0;
}
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include "../include/cmp_debug.h" #include "../include/cmp_debug.h"
/** /**
* @brief check if the compressor configuration is valid for a SW compression, * @brief check if the compressor configuration is valid for a SW compression,
* see the user manual for more information (PLATO-UVIE-PL-UM-0001). * see the user manual for more information (PLATO-UVIE-PL-UM-0001).
...@@ -62,9 +61,8 @@ int icu_cmp_cfg_valid(const struct cmp_cfg *cfg, struct cmp_info *info) ...@@ -62,9 +61,8 @@ int icu_cmp_cfg_valid(const struct cmp_cfg *cfg, struct cmp_info *info)
cfg_invalid++; cfg_invalid++;
} }
if (cfg->samples == 0) { if (cfg->samples == 0)
debug_print("Warning: The samples parameter is 0. No data are compressed. This behavior may not be intended.\n"); debug_print("Warning: The samples parameter is 0. No data are compressed. This behavior may not be intended.\n");
}
/* icu_output_buf can be NULL if rdcu compression is used */ /* icu_output_buf can be NULL if rdcu compression is used */
if (cfg->icu_output_buf == NULL) { if (cfg->icu_output_buf == NULL) {
...@@ -310,7 +308,7 @@ static int diff_32(uint32_t *data_buf, unsigned int samples, unsigned int round) ...@@ -310,7 +308,7 @@ static int diff_32(uint32_t *data_buf, unsigned int samples, unsigned int round)
* @note change the data_buf in-place * @note change the data_buf in-place
* @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
* *
* @param data_buf pointer to a S_FX data buffer * @param data pointer to a S_FX data buffer
* @param samples amount of data samples in the data buffer * @param samples amount of data samples in the data buffer
* @param round number of bits to round; if zero no rounding takes place * @param round number of bits to round; if zero no rounding takes place
* *
...@@ -344,7 +342,7 @@ static int diff_S_FX(struct S_FX *data, unsigned int samples, unsigned int ...@@ -344,7 +342,7 @@ static int diff_S_FX(struct S_FX *data, unsigned int samples, unsigned int
* @note change the data_buf in-place * @note change the data_buf in-place
* @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
* *
* @param data_buf pointer to a S_FX_EFX data buffer * @param data pointer to a S_FX_EFX data buffer
* @param samples amount of data samples in the data buffer * @param samples amount of data samples in the data buffer
* @param round number of bits to round; if zero no rounding takes place * @param round number of bits to round; if zero no rounding takes place
* *
...@@ -378,7 +376,7 @@ static int diff_S_FX_EFX(struct S_FX_EFX *data, unsigned int samples, unsigned ...@@ -378,7 +376,7 @@ static int diff_S_FX_EFX(struct S_FX_EFX *data, unsigned int samples, unsigned
* @note change the data_buf in-place * @note change the data_buf in-place
* @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
* *
* @param data_buf pointer to a S_FX_NCOB data buffer * @param data pointer to a S_FX_NCOB data buffer
* @param samples amount of data samples in the data buffer * @param samples amount of data samples in the data buffer
* @param round number of bits to round; if zero no rounding takes place * @param round number of bits to round; if zero no rounding takes place
* *
...@@ -412,7 +410,7 @@ static int diff_S_FX_NCOB(struct S_FX_NCOB *data, unsigned int samples, unsigned ...@@ -412,7 +410,7 @@ static int diff_S_FX_NCOB(struct S_FX_NCOB *data, unsigned int samples, unsigned
* @note change the data_buf in-place * @note change the data_buf in-place
* @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index * @note output is I_0 = I_0, I_i = I_i - I_i-1, where i is the array index
* *
* @param data_buf pointer to a S_FX_EFX_NCOB_ECOB data buffer * @param data pointer to a S_FX_EFX_NCOB_ECOB data buffer
* @param samples amount of data samples in the data buffer * @param samples amount of data samples in the data buffer
* @param round number of bits to round; if zero no rounding takes place * @param round number of bits to round; if zero no rounding takes place
* *
...@@ -540,7 +538,6 @@ static int model_32(uint32_t *data_buf, uint32_t *model_buf, unsigned int sample ...@@ -540,7 +538,6 @@ static int model_32(uint32_t *data_buf, uint32_t *model_buf, unsigned int sample
* @note update the model_buf in-place if up_model_buf = NULL * @note update the model_buf in-place if up_model_buf = NULL
* *
* @param data_buf pointer to the S_FX data buffer to process * @param data_buf pointer to the S_FX data buffer to process
* @param model_buf pointer to the model buffer of the data to process
* @param model_buf pointer to the updated model buffer (if NULL model_buf * @param model_buf pointer to the updated model buffer (if NULL model_buf
* will be overwrite with the updated model) * will be overwrite with the updated model)
* @param samples amount of data samples in the data_buf and model_buf buffer * @param samples amount of data samples in the data_buf and model_buf buffer
...@@ -607,7 +604,7 @@ int model_S_FX(struct S_FX *data_buf, struct S_FX *model_buf, ...@@ -607,7 +604,7 @@ int model_S_FX(struct S_FX *data_buf, struct S_FX *model_buf,
* @returns 0 on success, error otherwise * @returns 0 on success, error otherwise
*/ */
int pre_process(struct cmp_cfg *cfg) int cmp_pre_process(struct cmp_cfg *cfg)
{ {
if (!cfg) if (!cfg)
return -1; return -1;
...@@ -934,13 +931,12 @@ static int map_to_pos_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf, ...@@ -934,13 +931,12 @@ static int map_to_pos_S_FX_EFX_NCOB_ECOB(struct S_FX_EFX_NCOB_ECOB *data_buf,
* *
* @note change the data_buf in-place * @note change the data_buf in-place
* *
* @param data_buf pointer to the data to process * @param cfg configuration contains all parameters required for compression
* @param buf_len length of the data to process
* *
* @returns 0 on success, error otherwise * @returns 0 on success, error otherwise
*/ */
static int map_to_pos(struct cmp_cfg *cfg) int cmp_map_to_pos(struct cmp_cfg *cfg)
{ {
int zero_mode_used; int zero_mode_used;
...@@ -1114,7 +1110,7 @@ static encoder_ptr select_encoder(unsigned int golomb_par) ...@@ -1114,7 +1110,7 @@ static encoder_ptr select_encoder(unsigned int golomb_par)
* @param nBits number of bits to put in the bitstream * @param nBits number of bits to put in the bitstream
* @param destAddr this is the pointer to the beginning of the bitstream * @param destAddr this is the pointer to the beginning of the bitstream
* @param dest_len length of the bitstream buffer (starting at destAddr) * @param dest_len length of the bitstream buffer (starting at destAddr)
* @returns number of bits written, 0 if the number was too big, -1 if the * @returns TODO number of bits written, 0 if the number was too big, -2 if the
* destAddr buffer is to small to store the bitstream * destAddr buffer is to small to store the bitstream
* @note works in SRAM2 * @note works in SRAM2
*/ */
...@@ -1127,6 +1123,9 @@ static unsigned int put_n_bits32(unsigned int value, unsigned int bitOffset, ...@@ -1127,6 +1123,9 @@ static unsigned int put_n_bits32(unsigned int value, unsigned int bitOffset,
unsigned int bitsLeft, shiftRight, shiftLeft, localEndPos; unsigned int bitsLeft, shiftRight, shiftLeft, localEndPos;
unsigned int mask; unsigned int mask;
if (!destAddr)
return nBits;
/* check if destination buffer is large enough */ /* check if destination buffer is large enough */
/* TODO: adapt that to the other science products */ /* TODO: adapt that to the other science products */
if ((bitOffset + nBits) > (((dest_len+1)/2)*2 * 16)) { if ((bitOffset + nBits) > (((dest_len+1)/2)*2 * 16)) {
...@@ -1336,9 +1335,8 @@ static int encode_outlier_zero(uint32_t value_to_encode, int max_bits, ...@@ -1336,9 +1335,8 @@ static int encode_outlier_zero(uint32_t value_to_encode, int max_bits,
/* put the data unencoded in the bitstream */ /* put the data unencoded in the bitstream */
err = put_n_bits32(value_to_encode, enc->cmp_size, max_bits, err = put_n_bits32(value_to_encode, enc->cmp_size, max_bits,
cfg->icu_output_buf, cfg->buffer_length); cfg->icu_output_buf, cfg->buffer_length);
if (err <= 0) { if (err <= 0)
return err; return err;
}
enc->cmp_size += max_bits; enc->cmp_size += max_bits;
...@@ -1449,23 +1447,18 @@ int encode_value(uint32_t value_to_encode, int bit_len, struct cmp_cfg *cfg, ...@@ -1449,23 +1447,18 @@ int encode_value(uint32_t value_to_encode, int bit_len, struct cmp_cfg *cfg,
} }
static int encode_16(uint16_t *data_to_encode, struct cmp_cfg *cfg, static int encode_16(struct cmp_cfg *cfg, struct encoder_struct *enc)
struct encoder_struct *enc)
{ {
size_t i; size_t i;
uint16_t *data_to_encode;
if (!cfg) if (!cfg)
return -1; return -1;
if (!cfg->samples)
return 0;
if (!data_to_encode)
return -1;
if (!enc) if (!enc)
return -1; return -1;
data_to_encode = cfg->input_buf;
for (i = 0; i < cfg->samples; i++) { for (i = 0; i < cfg->samples; i++) {
int err = encode_value(data_to_encode[i], 16, cfg, enc); int err = encode_value(data_to_encode[i], 16, cfg, enc);
...@@ -1614,7 +1607,7 @@ static int encode_S_FX_EFX_NCOB_ECOB(struct cmp_cfg *cfg, struct encoder_struct ...@@ -1614,7 +1607,7 @@ static int encode_S_FX_EFX_NCOB_ECOB(struct cmp_cfg *cfg, struct encoder_struct
} }
/* pad the bitstream with zeros */ /* pad the bitstream with zeros */
int pad_bitstream(struct cmp_cfg *cfg, uint32_t cmp_size, struct cmp_info *info) int pad_bitstream(struct cmp_cfg *cfg, uint32_t cmp_size)
{ {
int n_bits = 0; int n_bits = 0;
...@@ -1628,21 +1621,15 @@ int pad_bitstream(struct cmp_cfg *cfg, uint32_t cmp_size, struct cmp_info *info) ...@@ -1628,21 +1621,15 @@ int pad_bitstream(struct cmp_cfg *cfg, uint32_t cmp_size, struct cmp_info *info)
n_bits = put_n_bits32(0, cmp_size, n_pad_bits, n_bits = put_n_bits32(0, cmp_size, n_pad_bits,
cfg->icu_output_buf, cfg->icu_output_buf,
cfg->buffer_length); cfg->buffer_length);
if (n_bits <= 0) { if (n_bits <= 0)
/* the icu_output_buf is to small to store the whole bitstream */
if (info) {
info->cmp_err |= 1UL << SMALL_BUFFER_ERR_BIT; /* set small buffer error */
info->cmp_size = 0;
}
return -2; return -2;
} }
} }
}
return n_bits; return n_bits;
} }
static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info) uint32_t cmp_encode_data(struct cmp_cfg *cfg)
{ {
struct encoder_struct enc; struct encoder_struct enc;
int err, n_bits; int err, n_bits;
...@@ -1659,7 +1646,7 @@ static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info) ...@@ -1659,7 +1646,7 @@ static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info)
case MODE_MODEL_MULTI: case MODE_MODEL_MULTI:
case MODE_DIFF_ZERO: case MODE_DIFF_ZERO:
case MODE_DIFF_MULTI: case MODE_DIFF_MULTI:
err = encode_16((uint16_t *)cfg->input_buf, cfg, &enc); err = encode_16(cfg, &enc);
break; break;
case MODE_RAW_S_FX: case MODE_RAW_S_FX:
err = encode_raw_S_FX(cfg, &enc); err = encode_raw_S_FX(cfg, &enc);
...@@ -1704,15 +1691,7 @@ static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info) ...@@ -1704,15 +1691,7 @@ static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info)
break; break;
} }
if (err == -2) { n_bits = pad_bitstream(cfg, enc.cmp_size);
/* the icu_output_buf is to small to store the whole bitstream */
info->cmp_err |= 1UL << SMALL_BUFFER_ERR_BIT; /* set small buffer error */
return err;
}
if (info)
info->cmp_size = enc.cmp_size;
n_bits = pad_bitstream(cfg, enc.cmp_size, info);
if (n_bits < 0) if (n_bits < 0)
return n_bits; return n_bits;
...@@ -1720,12 +1699,16 @@ static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info) ...@@ -1720,12 +1699,16 @@ static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info)
{ {
size_t i; size_t i;
uint32_t *p = (uint32_t *)cfg->icu_output_buf; uint32_t *p = (uint32_t *)cfg->icu_output_buf;
if (p)
for (i = 0; i < (enc.cmp_size + n_bits)/32; i++) for (i = 0; i < (enc.cmp_size + n_bits)/32; i++)
cpu_to_be32s(&p[i]); cpu_to_be32s(&p[i]);
} }
#endif /*__BYTE_ORDER__ */ #endif /*__BYTE_ORDER__ */
return 0; if (err)
return err;
else
return enc.cmp_size;
} }
...@@ -1756,6 +1739,7 @@ static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info) ...@@ -1756,6 +1739,7 @@ static int encode_data(struct cmp_cfg *cfg, struct cmp_info *info)
int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info) int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info)
{ {
int err; int err;
int cmp_size = 0;
err = set_info(cfg, info); err = set_info(cfg, info);
if (err) if (err)
...@@ -1765,17 +1749,22 @@ int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info) ...@@ -1765,17 +1749,22 @@ int icu_compress_data(struct cmp_cfg *cfg, struct cmp_info *info)
if (err) if (err)
return err; return err;
err = pre_process(cfg); err = cmp_pre_process(cfg);
if (err) if (err)
return err; return err;
err = map_to_pos(cfg); err = cmp_map_to_pos(cfg);
if (err) if (err)
return err; return err;
err = encode_data(cfg, info); cmp_size = cmp_encode_data(cfg);
if (err) if (cmp_size == -2 && info)
return err; /* the icu_output_buf is to small to store the whole bitstream */
info->cmp_err |= 1UL << SMALL_BUFFER_ERR_BIT; /* set small buffer error */
if (cmp_size < 0)
return cmp_size;
if (info)
info->cmp_size = cmp_size;
return 0; return 0;
} }
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
* @see Data Compression User Manual PLATO-UVIE-PL-UM-0001 * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001
*/ */
#include <stdio.h>
#include "../include/cmp_support.h" #include "../include/cmp_support.h"
#include "../include/cmp_data_types.h" #include "../include/cmp_data_types.h"
...@@ -246,6 +245,26 @@ int rdcu_supported_mode_is_used(unsigned int cmp_mode) ...@@ -246,6 +245,26 @@ int rdcu_supported_mode_is_used(unsigned int cmp_mode)
} }
/**
* @brief check if the mode is available
*
* @param cmp_mode compression mode
*
* @returns 1 when mode is available, otherwise 0
*/
int cmp_mode_available(unsigned int cmp_mode)
{
if (diff_mode_is_used(cmp_mode) ||
model_mode_is_used(cmp_mode) ||
raw_mode_is_used(cmp_mode))
return 1;
else
return 0;
}
/** /**
* @brief check if zero escape symbol mechanism mode is used * @brief check if zero escape symbol mechanism mode is used
* *
...@@ -442,7 +461,7 @@ uint32_t cmp_get_good_spill(unsigned int golomb_par, unsigned int cmp_mode) ...@@ -442,7 +461,7 @@ uint32_t cmp_get_good_spill(unsigned int golomb_par, unsigned int cmp_mode)
317, 324, 330, 336, 344, 351, 358, 363, 370, 377, 383, 391, 397, 317, 324, 330, 336, 344, 351, 358, 363, 370, 377, 383, 391, 397,
405, 411, 418, 424, 431, 452 }; 405, 411, 418, 424, 431, 452 };
if (zero_escape_mech_is_used(cmp_mode) || cmp_mode == MODE_DIFF_MULTI) if (zero_escape_mech_is_used(cmp_mode))
return get_max_spill(golomb_par, cmp_mode); return get_max_spill(golomb_par, cmp_mode);
if (cmp_mode == MODE_MODEL_MULTI) { if (cmp_mode == MODE_MODEL_MULTI) {
...@@ -452,6 +471,9 @@ uint32_t cmp_get_good_spill(unsigned int golomb_par, unsigned int cmp_mode) ...@@ -452,6 +471,9 @@ uint32_t cmp_get_good_spill(unsigned int golomb_par, unsigned int cmp_mode)
return LUT_RDCU_MULIT[golomb_par]; return LUT_RDCU_MULIT[golomb_par];
} }
if (cmp_mode == MODE_DIFF_MULTI)
return CMP_GOOD_SPILL_DIFF_MULTI;
return 0; return 0;
} }
...@@ -553,7 +575,8 @@ unsigned int size_of_bitstream(unsigned int cmp_size) ...@@ -553,7 +575,8 @@ unsigned int size_of_bitstream(unsigned int cmp_size)
/** /**
* @brief calculate the need bytes for the model * @brief calculate the need bytes for the model
* *
* @param cmp_size compressed data size, measured in bits * @param samples amount of model samples
* @param cmp_mode compression mode
* *
* @returns the size in bytes to store the hole bitstream * @returns the size in bytes to store the hole bitstream
*/ */
...@@ -588,18 +611,16 @@ void print_cmp_cfg(const struct cmp_cfg *cfg) ...@@ -588,18 +611,16 @@ void print_cmp_cfg(const struct cmp_cfg *cfg)
printf("input_buf: %p\n", (void *)cfg->input_buf); printf("input_buf: %p\n", (void *)cfg->input_buf);
if (cfg->input_buf != NULL) { if (cfg->input_buf != NULL) {
printf("input data:"); printf("input data:");
for (i = 0; i < cfg->samples; i++) { for (i = 0; i < cfg->samples; i++)
printf(" %04X", ((uint16_t *)cfg->input_buf)[i]); printf(" %04X", ((uint16_t *)cfg->input_buf)[i]);
}
printf("\n"); printf("\n");
} }
printf("rdcu_data_adr: 0x%06X\n", cfg->rdcu_data_adr); printf("rdcu_data_adr: 0x%06X\n", cfg->rdcu_data_adr);
printf("model_buf: %p\n", (void *)cfg->model_buf); printf("model_buf: %p\n", (void *)cfg->model_buf);
if (cfg->model_buf != NULL) { if (cfg->model_buf != NULL) {
printf("model data:"); printf("model data:");
for (i = 0; i < cfg->samples; i++) { for (i = 0; i < cfg->samples; i++)
printf(" %04X", ((uint16_t *)cfg->model_buf)[i]); printf(" %04X", ((uint16_t *)cfg->model_buf)[i]);
}
printf("\n"); printf("\n");
} }
printf("rdcu_model_adr: 0x%06X\n", cfg->rdcu_model_adr); printf("rdcu_model_adr: 0x%06X\n", cfg->rdcu_model_adr);
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment