Program Listing for File fromhost_buffer_flx.cpp

Return to documentation for file (fromhost_buffer_flx.cpp)

#include "fromhost_buffer.hpp"
#include <memory>

FlxFromHostBuffer::FlxFromHostBuffer(std::shared_ptr<Device> d)
    : FromHostBuffer(d){};


FlxFromHostBuffer::~FlxFromHostBuffer()
{
    m_device->dma_stop(m_dmaid);
}


void FlxFromHostBuffer::allocate_buffer(size_t size,
                            const std::string& name,
                            bool /*vmem*/, bool free_previous_cmem)
{
    m_size = size;
    m_buffer = std::make_unique<CmemBuffer>(size, name, free_previous_cmem);
    uint8_t* vaddr = reinterpret_cast<uint8_t*>(m_buffer->vaddr);
    m_encoder.set_destination_parameters(vaddr, m_buffer->size);
    m_buffer->pc_ptr = m_buffer->paddr;
}


void FlxFromHostBuffer::dma_start_continuous()
{
    m_device->dma_from_host(m_buffer.get(), m_dmaid);
    m_buffer->pc_ptr = m_buffer->paddr;
    m_device->dma_set_sw_ptr(m_dmaid, m_buffer->pc_ptr);
}

void FlxFromHostBuffer::dma_start_circular_trickle_buffer()
{
    const auto trickle_config_size = dma_get_write_offset();
    if (trickle_config_size > 0) {
        m_device->dma_from_host_trickle(m_buffer.get(), m_dmaid, trickle_config_size);
    }
}

void FlxFromHostBuffer::set_oneshot_trickle_buffer()
{
    const auto trickle_config_size = dma_get_write_offset();
    constexpr static auto WAITING_TIME = std::chrono::milliseconds(6000); //< 800 [MB] / 160 [MBps] = (buffer size) / (elink bandwidth) = 5 seconds + 1 second for wiggle room
    if(trickle_config_size > 0)
    {
        m_device->dma_set_oneshot(m_buffer.get(), m_dmaid, trickle_config_size);

        const auto start = std::chrono::high_resolution_clock::now(); // Start timer

        while(m_device->dma_enabled(m_dmaid)){
            const auto now = std::chrono::high_resolution_clock::now();
            const auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);

            if(elapsed >= WAITING_TIME){
                ers::error(felix_log::fromhost_buffer_felix_issue(std::format("The firmware was not able to read in time DMA buffer with ID:{}", m_dmaid)));
                break; // Exit the loop if the DMA is still enabled after 6 seconds
            }
        }
    }
}

bool FlxFromHostBuffer::can_write_trickle(){
    return not m_device->dma_enabled(m_dmaid);
}

size_t FlxFromHostBuffer::dma_free_bytes()
{
    bool even =  m_device->dma_cmp_even_bits(m_dmaid);
    uint64_t pc_wr_ptr = m_device->dma_get_sw_ptr(m_dmaid);
    uint64_t fw_rd_ptr = m_device->dma_get_fw_ptr(m_dmaid);
    return dma_compute_free_bytes(fw_rd_ptr, pc_wr_ptr, even);
}


bool FlxFromHostBuffer::dma_is_full()
{
    u_long read_ptr = m_device->dma_get_fw_ptr(m_dmaid);
    u_long write_ptr  = m_device->dma_get_sw_ptr(m_dmaid);
    return (write_ptr == read_ptr and not m_device->dma_cmp_even_bits(m_dmaid));
}


uint64_t FlxFromHostBuffer::dma_get_read_offset()
{
    return ( m_device->dma_get_fw_ptr(m_dmaid) - m_buffer->paddr );
}


uint64_t FlxFromHostBuffer::dma_get_write_offset()
{
    return ( m_buffer->pc_ptr - m_buffer->paddr );
}


uint64_t FlxFromHostBuffer::dma_get_write_ptr()
{
    return ( m_buffer->pc_ptr - m_buffer->paddr + m_buffer->vaddr );
}


void FlxFromHostBuffer::dma_set_write_offset(uint64_t offset)
{
    m_buffer->pc_ptr = offset + m_buffer->paddr;
    m_device->dma_set_sw_ptr(m_dmaid, m_buffer->pc_ptr);
}


void FlxFromHostBuffer::dma_advance_write_ptr(size_t bytes)
{
    m_buffer->pc_ptr += bytes;
    if(m_buffer->pc_ptr == m_buffer->pend){
        m_buffer->pc_ptr = m_buffer->paddr;
    }
    m_device->dma_set_sw_ptr(m_dmaid, m_buffer->pc_ptr);
}