Skip to content

Commit cc267b4

Browse files
committed
[RLE] Support multiple symbols/pairs in single transaction
This commit adds valid signals to PlainData interface. CompressedData interface uses `count > 0` to define valid symbol count pair. This is in preparation for a multisymbol RLE encoder implementation. Signed-off-by: Maciej Dudek <[email protected]>
1 parent f8e2d3d commit cc267b4

File tree

3 files changed

+196
-91
lines changed

3 files changed

+196
-91
lines changed

xls/modules/rle/rle_common.x

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,17 @@
1919
// Structure is used as an input and an output to and from
2020
// a preprocessing stage as well as an input to a RLE encoder.
2121
// It is also used as an output from RLE decoder.
22-
pub struct PlainData<SYMB_WIDTH: u32> {
23-
symbol: bits[SYMB_WIDTH], // symbol
24-
last: bool, // flush RLE
22+
pub struct PlainData<SYMB_WIDTH: u32, SYMB_COUNT: u32> {
23+
symbols: bits[SYMB_WIDTH][SYMB_COUNT], // symbols
24+
symbol_valids: bits[1][SYMB_COUNT], // symbol valid
25+
last: bool, // flush RLE
2526
}
2627

2728
// Structure contains compressed (symbol, counter) pairs.
2829
// Structure is used as an output from RLE encoder and
2930
// as an input to RLE decoder.
30-
pub struct CompressedData<SYMBOL_WIDTH: u32, COUNT_WIDTH: u32> {
31-
symbol: bits[SYMBOL_WIDTH], // symbol
32-
count: bits[COUNT_WIDTH], // symbol counter
33-
last: bool, // flush RLE
31+
pub struct CompressedData<SYMBOL_WIDTH: u32, COUNT_WIDTH: u32, PAIR_COUNT: u32> {
32+
symbols: bits[SYMBOL_WIDTH][PAIR_COUNT], // symbol
33+
counts: bits[COUNT_WIDTH][PAIR_COUNT], // symbol counter
34+
last: bool, // flush RLE
3435
}

xls/modules/rle/rle_dec.x

Lines changed: 114 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ struct RunLengthDecoderState<SYMBOL_WIDTH: u32, COUNT_WIDTH: u32> {
6363
}
6464
// RLE decoder implementation
6565
pub proc RunLengthDecoder<SYMBOL_WIDTH: u32, COUNT_WIDTH: u32> {
66-
input_r: chan<DecInData<SYMBOL_WIDTH, COUNT_WIDTH>> in;
67-
output_s: chan<DecOutData<SYMBOL_WIDTH>> out;
66+
input_r: chan<DecInData<SYMBOL_WIDTH, COUNT_WIDTH, 1>> in;
67+
output_s: chan<DecOutData<SYMBOL_WIDTH, 1>> out;
6868

6969
init {(
7070
RunLengthDecoderState<SYMBOL_WIDTH, COUNT_WIDTH> {
@@ -75,34 +75,38 @@ pub proc RunLengthDecoder<SYMBOL_WIDTH: u32, COUNT_WIDTH: u32> {
7575
)}
7676

7777
config (
78-
input_r: chan<DecInData<SYMBOL_WIDTH, COUNT_WIDTH>> in,
79-
output_s: chan<DecOutData<SYMBOL_WIDTH>> out,
78+
input_r: chan<DecInData<SYMBOL_WIDTH, COUNT_WIDTH, 1>> in,
79+
output_s: chan<DecOutData<SYMBOL_WIDTH, 1>> out,
8080
) {(input_r, output_s)}
8181

8282
next (tok: token, state: RunLengthDecoderState<SYMBOL_WIDTH, COUNT_WIDTH>) {
8383
let state_input = DecInData {
84-
symbol: state.symbol,
85-
count: state.count,
84+
symbols: [state.symbol],
85+
counts: [state.count],
8686
last: state.last
8787
};
8888
let recv_next_symbol = (state.count == bits[COUNT_WIDTH]:0);
8989
let (tok, input) = recv_if(tok, input_r, recv_next_symbol, state_input);
90-
let next_count = if input.count == bits[COUNT_WIDTH]:0 {
91-
fail!("invalid_count_0", input.count)
90+
let next_count = if input.counts[0] == bits[COUNT_WIDTH]:0 {
91+
input.counts[0]
9292
} else {
93-
input.count - bits[COUNT_WIDTH]:1
93+
input.counts[0] - bits[COUNT_WIDTH]:1
9494
};
9595
let done_sending = (next_count == bits[COUNT_WIDTH]:0);
9696
let send_last = input.last && done_sending;
97-
let data_tok = send(tok, output_s, DecOutData {
98-
symbol: input.symbol,
99-
last: send_last
97+
let symbol_valid = input.counts[0] > bits[COUNT_WIDTH]:0;
98+
let data_tok = send_if(tok, output_s,
99+
symbol_valid || send_last,
100+
DecOutData {
101+
symbols: [input.symbols[0]],
102+
symbol_valids: [symbol_valid],
103+
last: send_last
100104
});
101105
if (send_last) {
102106
zero!<RunLengthDecoderState>()
103107
} else {
104108
RunLengthDecoderState {
105-
symbol: input.symbol,
109+
symbol: input.symbols[0],
106110
count: next_count,
107111
last: input.last,
108112
}
@@ -116,8 +120,8 @@ proc RunLengthDecoder32 {
116120
init {()}
117121

118122
config (
119-
input_r: chan<DecInData<32, 2>> in,
120-
output_s: chan<DecOutData<32>> out,
123+
input_r: chan<DecInData<32, 2, 1>> in,
124+
output_s: chan<DecOutData<32, 1>> out,
121125
) {
122126
spawn RunLengthDecoder<u32:32, u32:2>(input_r, output_s);
123127
()
@@ -136,8 +140,8 @@ const TEST_COUNT_WIDTH = u32:32;
136140
type TestSymbol = bits[TEST_SYMBOL_WIDTH];
137141
type TestCount = bits[TEST_COUNT_WIDTH];
138142
type TestStimulus = (TestSymbol, TestCount);
139-
type TestDecInData = DecInData<TEST_SYMBOL_WIDTH, TEST_COUNT_WIDTH>;
140-
type TestDecOutData = DecOutData<TEST_SYMBOL_WIDTH>;
143+
type TestDecInData = DecInData<TEST_SYMBOL_WIDTH, TEST_COUNT_WIDTH, 1>;
144+
type TestDecOutData = DecOutData<TEST_SYMBOL_WIDTH, 1>;
141145

142146
// Check RLE decoder on a transaction
143147
#[test_proc]
@@ -171,13 +175,13 @@ proc RunLengthDecoderTransactionTest {
171175
in enumerate(TransactionTestStimuli) {
172176
let last = counter == (array_size(TransactionTestStimuli) - u32:1);
173177
let data_in = TestDecInData{
174-
symbol: stimulus.0,
175-
count: stimulus.1,
178+
symbols: [stimulus.0],
179+
counts: [stimulus.1],
176180
last: last
177181
};
178182
let tok = send(tok, dec_input_s, data_in);
179183
trace_fmt!("Sent {} stimuli, symbol: 0x{:x}, count:{}, last: {}",
180-
counter + u32:1, data_in.symbol, data_in.count, data_in.last);
184+
counter + u32:1, data_in.symbols[0], data_in.counts[0], data_in.last);
181185
(tok)
182186
}(tok);
183187
let TransationTestOutputs: TestSymbol[14] = [
@@ -194,13 +198,14 @@ proc RunLengthDecoderTransactionTest {
194198
in enumerate(TransationTestOutputs) {
195199
let last = counter == (array_size(TransationTestOutputs) - u32:1);
196200
let data_out = TestDecOutData{
197-
symbol: symbol,
201+
symbols: [symbol],
202+
symbol_valids: [bits[1]:1],
198203
last: last
199204
};
200205
let (tok, dec_output) = recv(tok, dec_output_r);
201206
trace_fmt!(
202207
"Received {} transactions, symbol: 0x{:x}, last: {}",
203-
counter, dec_output.symbol, dec_output.last
208+
counter, dec_output.symbols[0], dec_output.last
204209
);
205210
assert_eq(dec_output, data_out);
206211
(tok)
@@ -210,6 +215,81 @@ proc RunLengthDecoderTransactionTest {
210215
}
211216
}
212217

218+
// Check that RLE decoder will remove empty pairs, `count == 0`.
219+
// Check that RLE decoder will set `symbol_valids` to 0 only in
220+
// the last output packet.
221+
#[test_proc]
222+
proc RunLengthDecoderZeroCountTest {
223+
terminator: chan<bool> out; // test termination request
224+
dec_input_s: chan<TestDecInData> out;
225+
dec_output_r: chan<TestDecOutData> in;
226+
227+
init {()}
228+
229+
config(terminator: chan<bool> out) {
230+
let (dec_input_s, dec_input_r) = chan<TestDecInData>;
231+
let (dec_output_s, dec_output_r) = chan<TestDecOutData>;
232+
233+
spawn RunLengthDecoder<TEST_SYMBOL_WIDTH, TEST_COUNT_WIDTH>(
234+
dec_input_r, dec_output_s);
235+
(terminator, dec_input_s, dec_output_r)
236+
}
237+
238+
next(tok: token, state: ()) {
239+
let ZeroCountTestStimuli: TestStimulus[6] =[
240+
(TestSymbol:0xB, TestCount:0x2),
241+
(TestSymbol:0x1, TestCount:0x0),
242+
(TestSymbol:0xC, TestCount:0x1),
243+
(TestSymbol:0xC, TestCount:0x0),
244+
(TestSymbol:0x3, TestCount:0x3),
245+
(TestSymbol:0x2, TestCount:0x0),
246+
];
247+
let tok = for ((counter, stimulus), tok):
248+
((u32, (TestSymbol, TestCount)) , token)
249+
in enumerate(ZeroCountTestStimuli) {
250+
let last = counter == (array_size(ZeroCountTestStimuli) - u32:1);
251+
let data_in = TestDecInData{
252+
symbols: [stimulus.0],
253+
counts: [stimulus.1],
254+
last: last
255+
};
256+
let tok = send(tok, dec_input_s, data_in);
257+
trace_fmt!("Sent {} stimuli, symbol: 0x{:x}, count:{}, last: {}",
258+
counter + u32:1, data_in.symbols[0], data_in.counts[0], data_in.last);
259+
(tok)
260+
}(tok);
261+
let ZeroCountTestOutputs: TestDecOutData[7] = [
262+
TestDecOutData{symbols: [TestSymbol: 0xB],
263+
symbol_valids: [true], last: false},
264+
TestDecOutData{symbols: [TestSymbol: 0xB],
265+
symbol_valids: [true], last: false},
266+
TestDecOutData{symbols: [TestSymbol: 0xC],
267+
symbol_valids: [true], last: false},
268+
TestDecOutData{symbols: [TestSymbol: 0x3],
269+
symbol_valids: [true], last: false},
270+
TestDecOutData{symbols: [TestSymbol: 0x3],
271+
symbol_valids: [true], last: false},
272+
TestDecOutData{symbols: [TestSymbol: 0x3],
273+
symbol_valids: [true], last: false},
274+
TestDecOutData{symbols: [TestSymbol: 0x2],
275+
symbol_valids: [false], last: true},
276+
];
277+
let tok = for ((counter, output), tok):
278+
((u32, TestDecOutData) , token)
279+
in enumerate(ZeroCountTestOutputs) {
280+
let (tok, dec_output) = recv(tok, dec_output_r);
281+
trace_fmt!(
282+
"Received {} transactions, symbols: 0x{:x}, last: {}",
283+
counter + u32:1, dec_output.symbols, dec_output.last
284+
);
285+
assert_eq(dec_output, output);
286+
(tok)
287+
}(tok);
288+
send(tok, terminator, true);
289+
()
290+
}
291+
}
292+
213293
// Check that RLE decoder will create 2 `last` output packets,
214294
// when 2 `last` input packets were consumed.
215295
#[test_proc]
@@ -232,35 +312,37 @@ proc RunLengthDecoderLastAfterLastTest {
232312
next(tok: token, state: ()) {
233313
let LastAfterLastTestStimuli: TestDecInData[2] =[
234314
TestDecInData {
235-
symbol: TestSymbol:0x1,
236-
count: TestCount:0x1,
315+
symbols: [TestSymbol:0x1],
316+
counts: [TestCount:0x1],
237317
last:true
238318
},
239319
TestDecInData {
240-
symbol: TestSymbol:0x2,
241-
count: TestCount:0x1,
320+
symbols: [TestSymbol:0x2],
321+
counts: [TestCount:0x1],
242322
last:true
243323
},
244324
];
245325
let tok = for ((counter, stimulus), tok):
246326
((u32, TestDecInData) , token)
247327
in enumerate(LastAfterLastTestStimuli) {
248328
let tok = send(tok, dec_input_s, stimulus);
249-
trace_fmt!("Sent {} stimuli, symbol: 0x{:x}, count:{}, last: {}",
250-
counter + u32:1, stimulus.symbol, stimulus.count, stimulus.last);
329+
trace_fmt!("Sent {} stimuli, symbols: 0x{:x}, counts:{}, last: {}",
330+
counter + u32:1, stimulus.symbols, stimulus.counts, stimulus.last);
251331
(tok)
252332
}(tok);
253333
let LastAfterLastTestOutputs: TestDecOutData[2] = [
254-
TestDecOutData{symbol: TestSymbol: 0x1, last: true},
255-
TestDecOutData{symbol: TestSymbol: 0x2, last: true},
334+
TestDecOutData{symbols: [TestSymbol: 0x1],
335+
symbol_valids: [true], last: true},
336+
TestDecOutData{symbols: [TestSymbol: 0x2],
337+
symbol_valids: [true], last: true},
256338
];
257339
let tok = for ((counter, output), tok):
258340
((u32, TestDecOutData) , token)
259341
in enumerate(LastAfterLastTestOutputs) {
260342
let (tok, dec_output) = recv(tok, dec_output_r);
261343
trace_fmt!(
262-
"Received {} transactions, symbol: 0x{:x}, last: {}",
263-
counter + u32:1, dec_output.symbol, dec_output.last
344+
"Received {} transactions, symbols: 0x{:x}, last: {}",
345+
counter + u32:1, dec_output.symbols, dec_output.last
264346
);
265347
assert_eq(dec_output, output);
266348
(tok)

0 commit comments

Comments
 (0)