Skip to content

Commit

Permalink
modules/zstd: Add raw block decoder
Browse files Browse the repository at this point in the history
Internal-tag: [#51343]
Signed-off-by: Robert Winkler <[email protected]>
  • Loading branch information
rw1nkler authored and lpawelcz committed Dec 27, 2023
1 parent d2b4b32 commit ac24f27
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 0 deletions.
16 changes: 16 additions & 0 deletions xls/modules/zstd/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,19 @@ cc_test(
"@com_google_fuzztest//fuzztest:googletest_fixture_adapter",
],
)

xls_dslx_library(
name = "raw_block_dec_dslx",
srcs = [
"raw_block_dec.x",
],
deps = [
":buffer_dslx",
":common_dslx",
],
)

xls_dslx_test(
name = "raw_block_dec_dslx_test",
library = ":raw_block_dec_dslx",
)
96 changes: 96 additions & 0 deletions xls/modules/zstd/raw_block_dec.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2023 The XLS Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This file contains the implementation of RawBlockDecoder responsible for decoding
// ZSTD Raw Blocks. More information about Raw Block's format can be found in:
// https://datatracker.ietf.org/doc/html/rfc8878#section-3.1.1.2.2

import xls.modules.zstd.common as common

type BlockDataPacket = common::BlockDataPacket;
type BlockData = common::BlockData;

struct RawBlockDecoderState {
prev_id: u32, // ID of the previous block
prev_last: bool, // if the previous packet was the last one that makes up the whole block
prev_valid: bool, // if prev_id and prev_last contain valid data
}

const DATA_WIDTH = common::DATA_WIDTH;
const ZERO_RAW_BLOCK_DECODER_STATE = zero!<RawBlockDecoderState>();

// RawBlockDecoder is responsible for decoding Raw Blocks,
// it should be a part of the ZSTD Decoder pipeline.
pub proc RawBlockDecoder {
input_r: chan<BlockDataPacket> in;
output_s: chan<BlockDataPacket> out;

init { (ZERO_RAW_BLOCK_DECODER_STATE) }

config(
input_r: chan<BlockDataPacket> in,
output_s: chan<BlockDataPacket> out
) {(input_r, output_s)}

next(tok: token, state: RawBlockDecoderState) {
let (tok, data) = recv(tok, input_r);
if state.prev_valid && (data.id != state.prev_id) && (state.prev_last == false) {
trace_fmt!("ID changed but previous packet have no last!");
fail!("no_last", ());
} else {};

let tok = send(tok, output_s, data);

RawBlockDecoderState {
prev_valid: true,
prev_id: data.id,
prev_last: data.last
}
}
}

#[test_proc]
proc RawBlockDecoderTest {
terminator: chan<bool> out;
dec_input_s: chan<BlockDataPacket> out;
dec_output_r: chan<BlockDataPacket> in;

config(terminator: chan<bool> out) {
let (dec_input_s, dec_input_r) = chan<BlockDataPacket>;
let (dec_output_s, dec_output_r) = chan<BlockDataPacket>;
spawn RawBlockDecoder(dec_input_r, dec_output_s);
(terminator, dec_input_s, dec_output_r)
}

init { }

next(tok: token, state: ()) {
let data_to_send: BlockDataPacket[5] = [
BlockDataPacket { id: u32:1, last: u1:false, last_block: u1:false, data: BlockData:1, length: u32:32 },
BlockDataPacket { id: u32:1, last: u1:false, last_block: u1:false, data: BlockData:2, length: u32:32 },
BlockDataPacket { id: u32:1, last: u1:true, last_block: u1:false, data: BlockData:3, length: u32:32 },
BlockDataPacket { id: u32:2, last: u1:false, last_block: u1:false, data: BlockData:4, length: u32:32 },
BlockDataPacket { id: u32:2, last: u1:true, last_block: u1:true, data: BlockData:5, length: u32:32 },
];

let tok = for ((_, data), tok): ((u32, BlockDataPacket), token) in enumerate(data_to_send) {
let tok = send(tok, dec_input_s, data);
let (tok, received_data) = recv(tok, dec_output_r);
assert_eq(data, received_data);
(tok)
}(tok);

send(tok, terminator, true);
}
}

0 comments on commit ac24f27

Please sign in to comment.