summaryrefslogtreecommitdiff
path: root/mac/design/test/sacki/src/sacki_decomp.pl
blob: ce20c01674f96fccea35db55e80bb2e8839ba0ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/perl
#
# Generate decompression tables.
#
use warnings;
use strict;

# Number of bits in look-up table index.
# Minimum is 6 = the larger code.
my $nb_bits = 8;
# Use as much code as possible.
my $fast_table = 0;

my ($max_eaten, $max_produced) = ($nb_bits, $nb_bits * 4);
my ($max_nok, $undef_nok, $max_nb_nok) = (22, 31, 3);
my ($bits_eaten, $bits_produced, $bits_nok) = (4, 6, 5);

die if $max_eaten >= 1 << $bits_eaten;
die if $max_produced >= 1 << $bits_produced;
die if $max_nok >= 1 << $bits_nok;
die if $undef_nok >= 1 << $bits_nok;
die if $bits_eaten + $bits_produced + $max_nb_nok * $bits_nok > 32;

print <<EOF;
/* Autogenerated file, do not edit. */

#define SACKI_DECOMP_UNDEF_NOK $undef_nok

/** SACKI decompression table entry. */
struct sacki_decomp_t
{
    /** Bits eaten in the input byte, maximum = $max_eaten. */
    uint eaten:$bits_eaten;
    /** Bits produced for this code sequence, maximum = $max_produced. */
    uint produced:$bits_produced;
    /** Position of first nok, maximum = $max_nok. If undefined: $undef_nok. */
    uint nok0:$bits_nok;
    /** Position of second nok. */
    uint nok1:$bits_nok;
    /** Position of third nok. */
    uint nok2:$bits_nok;
};
typedef struct sacki_decomp_t sacki_decomp_t;

static const sacki_decomp_t sacki_decomp[] = {
EOF

my %decomp = (
    # MSB first.
    '0' => '0000',
    '001' => '010',
    '101' => '100',
    '011' => '001',
    '0111' => '1000',
    '001111' => '110',
    '101111' => '101',
    '11111' => '11',
);

# For each possible input bit sequence, find the corresponding uncompressed
# semantic.
for my $i (0 .. (1 << $nb_bits) - 1)
{
    my $in = $i;
    my $left = $nb_bits;
    my $eaten = 0;
    my $produced = 0;
    my $done = 0;
    my @nok;
    my @codes;
    until ($done)
    {
	$done = 1;
	for (keys %decomp)
	{
	    my $n = length ($_);
	    my $b = oct ("0b$_");
	    if ($left >= $n && ($in & (1 << $n) - 1) == $b)
	    {
		$left -= $n;
		$eaten += $n;
		$in >>= $n;
		my $codel = length ($decomp{$_});
		my $code = oct ("0b$decomp{$_}");
		for my $j (0 .. $codel - 1)
		{
		    push @nok, $produced + $j if $code & 1;
		    $code >>= 1;
		}
		$produced += $codel;
		unshift @codes, $_;
		$done = 0 if $fast_table;
                last unless $fast_table;
	    }
	}
    }
    die if scalar @nok > $max_nb_nok;
    for (@nok)
    {
	die if $_ > $max_nok;
    }
    push @nok, $undef_nok for (1 .. $max_nb_nok);
    die if $eaten > $max_eaten;
    die if $produced > $max_produced;
    printf "    { %1d, %2d", $eaten, $produced;
    printf ", %2d", $nok[$_] for (0 .. $max_nb_nok - 1);
    print " }, /* ", sprintf ("%.8b", $i), ': ', join ('-', @codes), ' -> ',
	join ('-', @decomp{@codes}), " */\n";
}

print "};\n";