Skip to content

Commit 1a12c5e

Browse files
rw1nklerlpawelcz
authored andcommitted
modules/zstd: Add raw block decoder
Internal-tag: [#51343] Signed-off-by: Robert Winkler <[email protected]>
1 parent b2b790d commit 1a12c5e

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

xls/modules/zstd/BUILD

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,19 @@ cc_test(
139139
"@com_google_fuzztest//fuzztest:googletest_fixture_adapter",
140140
],
141141
)
142+
143+
xls_dslx_library(
144+
name = "raw_block_dec_dslx",
145+
srcs = [
146+
"raw_block_dec.x",
147+
],
148+
deps = [
149+
":buffer_dslx",
150+
":common_dslx",
151+
],
152+
)
153+
154+
xls_dslx_test(
155+
name = "raw_block_dec_dslx_test",
156+
library = ":raw_block_dec_dslx",
157+
)

xls/modules/zstd/raw_block_dec.x

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright 2023 The XLS Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// This file contains the implementation of RawBlockDecoder responsible for decoding
16+
// ZSTD Raw Blocks. More information about Raw Block's format can be found in:
17+
// https://datatracker.ietf.org/doc/html/rfc8878#section-3.1.1.2.2
18+
19+
import xls.modules.zstd.common as common
20+
21+
type BlockDataPacket = common::BlockDataPacket;
22+
type BlockData = common::BlockData;
23+
24+
struct RawBlockDecoderState {
25+
prev_id: u32, // ID of the previous block
26+
prev_last: bool, // if the previous packet was the last one that makes up the whole block
27+
prev_valid: bool, // if prev_id and prev_last contain valid data
28+
}
29+
30+
const DATA_WIDTH = common::DATA_WIDTH;
31+
const ZERO_RAW_BLOCK_DECODER_STATE = zero!<RawBlockDecoderState>();
32+
33+
// RawBlockDecoder is responsible for decoding Raw Blocks,
34+
// it should be a part of the ZSTD Decoder pipeline.
35+
pub proc RawBlockDecoder {
36+
input_r: chan<BlockDataPacket> in;
37+
output_s: chan<BlockDataPacket> out;
38+
39+
init { (ZERO_RAW_BLOCK_DECODER_STATE) }
40+
41+
config(
42+
input_r: chan<BlockDataPacket> in,
43+
output_s: chan<BlockDataPacket> out
44+
) {(input_r, output_s)}
45+
46+
next(tok: token, state: RawBlockDecoderState) {
47+
let (tok, data) = recv(tok, input_r);
48+
if state.prev_valid && (data.id != state.prev_id) && (state.prev_last == false) {
49+
trace_fmt!("ID changed but previous packet have no last!");
50+
fail!("no_last", ());
51+
} else {};
52+
53+
let tok = send(tok, output_s, data);
54+
55+
RawBlockDecoderState {
56+
prev_valid: true,
57+
prev_id: data.id,
58+
prev_last: data.last
59+
}
60+
}
61+
}
62+
63+
#[test_proc]
64+
proc RawBlockDecoderTest {
65+
terminator: chan<bool> out;
66+
dec_input_s: chan<BlockDataPacket> out;
67+
dec_output_r: chan<BlockDataPacket> in;
68+
69+
config(terminator: chan<bool> out) {
70+
let (dec_input_s, dec_input_r) = chan<BlockDataPacket>;
71+
let (dec_output_s, dec_output_r) = chan<BlockDataPacket>;
72+
spawn RawBlockDecoder(dec_input_r, dec_output_s);
73+
(terminator, dec_input_s, dec_output_r)
74+
}
75+
76+
init { }
77+
78+
next(tok: token, state: ()) {
79+
let data_to_send: BlockDataPacket[5] = [
80+
BlockDataPacket { id: u32:1, last: u1:false, last_block: u1:false, data: BlockData:1, length: u32:32 },
81+
BlockDataPacket { id: u32:1, last: u1:false, last_block: u1:false, data: BlockData:2, length: u32:32 },
82+
BlockDataPacket { id: u32:1, last: u1:true, last_block: u1:false, data: BlockData:3, length: u32:32 },
83+
BlockDataPacket { id: u32:2, last: u1:false, last_block: u1:false, data: BlockData:4, length: u32:32 },
84+
BlockDataPacket { id: u32:2, last: u1:true, last_block: u1:true, data: BlockData:5, length: u32:32 },
85+
];
86+
87+
let tok = for ((_, data), tok): ((u32, BlockDataPacket), token) in enumerate(data_to_send) {
88+
let tok = send(tok, dec_input_s, data);
89+
let (tok, received_data) = recv(tok, dec_output_r);
90+
assert_eq(data, received_data);
91+
(tok)
92+
}(tok);
93+
94+
send(tok, terminator, true);
95+
}
96+
}

0 commit comments

Comments
 (0)