Program Listing for File decoder.hpp

Return to documentation for file (decoder.hpp)

#ifndef FELIX_DECODER_H_
#define FELIX_DECODER_H_

#include <string>
#include <memory>
#include "device.hpp"
#include "elink.hpp"
#include "tohost_monitor.hpp"
#include "block.hpp"
#include "publisher.hpp"
#include "l0id_decoder.hpp"


struct chunk_buffer
{
    std::uint8_t m_status_byte{};
    size_t chunk_size{};
    std::vector<iovec> iov;

    chunk_buffer() : m_status_byte(0), chunk_size(0){
        iov.emplace_back(&m_status_byte, 1);
    };

    void push_back(iovec&& x) {
        iov.push_back(x);
        chunk_size += x.iov_len;
    }

    void clear() noexcept {
        iov.resize(1);
        chunk_size = 0;
        m_status_byte = 0;
    }

    bool empty() const noexcept {
        // Status byte
        return iov.size() == 1;
    }

    void remove_last_entry() {
        chunk_size -= iov.back().iov_len;
        iov.resize(iov.size()-1);
    }

    void update_status_byte(uint8_t status) {
        m_status_byte |= status;
    }

    uint8_t get_status_byte() const {
        return m_status_byte;
    }

    size_t byte_size() {
        return chunk_size;
    }

    size_t iov_len() {
        return iov.size();
    }

    iovec* iov_addr() {
        return iov.data();
    }

};


class Decoder
{
    public:
        Decoder(const Decoder&) = delete;
        Decoder& operator=(const Decoder&) = delete;

        Decoder(Decoder&&) = default;
        Decoder& operator=(Decoder&&) = default;

        Decoder(const Elink &elink, Publisher &publisher, flx_tohost_format fmt,
            int l0id_decoder_fmt, unsigned int block_size, uint64_t buf_vaddr);

        uint32_t get_last_block(){return m_last_block;}

        uint64_t get_fid(){return m_elink.fid;}

        void set_block_size(unsigned int block_size){m_block_size = block_size;}

        Publisher::Result decode(Block & block);

        ToHostElinkStats get_decoder_stats(){return m_stats;}

        ToHostElinkStats get_decoder_stats_increment(ToHostElinkStats & previous);

    private:
        enum SubchunkType {
            NIL = 0, FIRST, LAST, WHOLE, MIDDLE, TIMEOUT, OOB
        };

        Publisher::Result post_subchunk(uint8_t *data, uint32_t length, SubchunkType type, uint8_t err);

        [[nodiscard]] Publisher::Result check_block_integrity(Block & block);


        Publisher::Result decode_subchunk_headers(Block & block);

        Publisher::Result decode_subchunk_trailers(Block & block);

        void on_successful_send();

    private:
        ToHostElinkStats m_stats;
        Elink m_elink;
        Publisher &m_publisher;
        uint64_t m_buffer_vaddr;
        unsigned int m_block_size;

        uint8_t m_seqnr_err = 0;
        uint8_t m_last_seqnr = 0;
        uint32_t m_last_block = 0;
        uint16_t m_chunk_position = 0;
        std::function< Publisher::Result(Block & block)> m_decode;


        std::unique_ptr<L0Decoder> m_l0id_checker;
        std::vector<std::pair<uint16_t, uint32_t>> m_subchunks;
        chunk_buffer m_scratch;
};

#endif /* FELIX_DECODER_H_ */