LCOV - code coverage report
Current view: top level - src - fromhost_buffer_file.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 100 122 82.0 %
Date: 2025-09-09 12:09:29 Functions: 12 16 75.0 %

          Line data    Source code
       1             : #include "fromhost_buffer.hpp"
       2             : #include "log.hpp"
       3             : #include <cstdint>
       4             : 
       5           5 : FileFromHostBuffer::FileFromHostBuffer(std::shared_ptr<Device> d, std::string &filename, bool fifo)
       6             :     : FromHostBuffer(d),
       7           5 :       m_file(filename, m_encoder.get_block_size(), DiskIO::FWRITE, fifo),
       8           5 :       m_rd_odd(false),
       9          15 :       m_wr_odd(false){};
      10             : 
      11           5 : FileFromHostBuffer::~FileFromHostBuffer()
      12             : {
      13           5 :     m_reader_thread.join();
      14           5 :     LOG_INFO("Reader thread joined");
      15           5 : }
      16             : 
      17           5 : void FileFromHostBuffer::allocate_buffer(size_t size,
      18             :                                          const std::string &name,
      19             :                                          bool vmem, bool free_previous_cmem)
      20             : {
      21           5 :     m_size = size;
      22           5 :     if (vmem)
      23             :     {
      24           5 :         m_buffer = std::make_unique<VmemBuffer>(size);
      25             :     }
      26             :     else
      27             :     {
      28           0 :         m_buffer = std::make_unique<CmemBuffer>(size, name, free_previous_cmem);
      29             :     }
      30           5 :     uint8_t *vaddr = reinterpret_cast<uint8_t *>(m_buffer->vaddr);
      31           5 :     m_encoder.set_destination_parameters(vaddr, m_buffer->size);
      32           5 : }
      33             : 
      34           5 : void FileFromHostBuffer::dma_start_continuous()
      35             : {
      36           5 :     m_buffer->pend = m_buffer->paddr + m_buffer->size;
      37           5 :     m_buffer->pc_ptr = m_buffer->paddr;
      38           5 :     m_buffer->emu_fw_ptr = m_buffer->paddr;
      39           5 :     LOG_INFO("  cmem buffer [0x%x,0x%x] %lu Blocks", m_buffer->paddr, m_buffer->pend, m_buffer->size/1024);
      40           5 :     LOG_INFO("  cmem virtual address 0x%x", m_buffer->vaddr);
      41           5 :     LOG_INFO("  fw_ptr 0x%x", m_buffer->emu_fw_ptr);
      42           5 :     LOG_INFO("  pc_ptr 0x%x", m_buffer->pc_ptr);
      43           5 :     LOG_INFO("Spawning buffer-to-file reader thread...");
      44           5 :     m_reader_thread = std::thread(&FileFromHostBuffer::copy_from_dma_buffer_to_file, this);
      45           5 : }
      46             : 
      47             : /** Here I only need to update where to start reading, also known as the Firmware pointer emulator (emu_fw_ptr). 
      48             :     The dimensions of the buffer (pend) do not change, also the pointer that tells until where in the buffer has been written (pc_ptr),
      49             :     is updated after writing with dma_set_write_offset()*/
      50           2 : void FileFromHostBuffer::dma_start_circular_trickle_buffer()
      51             : {
      52           2 :     std::unique_lock<std::shared_mutex> lock(m_driver_mutex);
      53           2 :     m_buffer->emu_fw_ptr = m_buffer->paddr;
      54           2 :     m_buffer->pend = m_buffer->paddr + m_trickle_config_size;
      55           2 :     m_fw_reading_trickle.store(true);
      56           2 : }
      57             : 
      58             : 
      59       10025 : size_t FileFromHostBuffer::dma_free_bytes()
      60             : {
      61       10025 :     std::shared_lock<std::shared_mutex> lock(m_driver_mutex);
      62       10025 :     bool even = (m_rd_odd == m_wr_odd);
      63       20050 :     return dma_compute_free_bytes(m_buffer->emu_fw_ptr, m_buffer->pc_ptr, even);
      64       10025 : }
      65             : 
      66           0 : bool FileFromHostBuffer::dma_is_full()
      67             : {
      68           0 :     std::shared_lock<std::shared_mutex> lock(m_driver_mutex);
      69           0 :     return ((m_buffer->emu_fw_ptr == m_buffer->pc_ptr) and (m_rd_odd != m_wr_odd));
      70           0 : }
      71             : 
      72        8586 : bool FileFromHostBuffer::dma_is_empty()
      73             : {
      74        8586 :     std::shared_lock<std::shared_mutex> lock(m_driver_mutex);
      75       15319 :     return ((m_buffer->emu_fw_ptr == m_buffer->pc_ptr) and (m_rd_odd == m_wr_odd));
      76        8586 : }
      77             : 
      78             : // offset read (fw emu)
      79           0 : uint64_t FileFromHostBuffer::dma_get_read_offset()
      80             : {
      81           0 :     std::shared_lock<std::shared_mutex> lock(m_driver_mutex);
      82           0 :     return (m_buffer->emu_fw_ptr - m_buffer->paddr);
      83           0 : }
      84             : 
      85             : // offset write (pc)
      86       10002 : uint64_t FileFromHostBuffer::dma_get_write_offset()
      87             : {
      88       10002 :     std::shared_lock<std::shared_mutex> lock(m_driver_mutex);
      89       10002 :     return (m_buffer->pc_ptr - m_buffer->paddr);
      90       10002 : }
      91             : 
      92             : // offset write (pc)
      93       10004 : void FileFromHostBuffer::dma_set_write_offset(uint64_t offset)
      94             : {
      95       10004 :     uint64_t p_addr = m_buffer->paddr + offset;
      96       10004 :     set_write_ptr_paddr(p_addr);
      97       10004 : }
      98             : 
      99             : // vaddr
     100           0 : uint64_t FileFromHostBuffer::dma_get_write_ptr()
     101             : {
     102           0 :     std::shared_lock<std::shared_mutex> lock(m_driver_mutex);
     103           0 :     return (m_buffer->pc_ptr - m_buffer->paddr + m_buffer->vaddr);
     104           0 : }
     105             : 
     106           0 : void FileFromHostBuffer::dma_advance_write_ptr(size_t bytes)
     107             : {
     108           0 :     if (bytes == 0)
     109             :     {
     110           0 :         return;
     111             :     }
     112           0 :     std::scoped_lock<std::shared_mutex> lock(m_driver_mutex);
     113           0 :     m_buffer->emu_fw_ptr += bytes;
     114           0 :     if (m_buffer->emu_fw_ptr == m_buffer->pend)
     115             :     {
     116           0 :         m_buffer->emu_fw_ptr = m_buffer->paddr;
     117           0 :         m_wr_odd = !m_wr_odd;
     118             :     }
     119           0 : }
     120             : 
     121       10004 : void FileFromHostBuffer::set_write_ptr_paddr(uint64_t p_addr)
     122             : {
     123             :     // write ptr := pc_ptr
     124       10004 :     std::scoped_lock<std::shared_mutex> lock(m_driver_mutex);
     125       10004 :     if (p_addr == m_buffer->pc_ptr)
     126             :     {
     127           1 :         return;
     128             :     }
     129             : 
     130       10003 :     if (p_addr < m_buffer->pc_ptr)
     131             :     {
     132           1 :         unsigned int diff = (p_addr - m_buffer->pc_ptr);
     133           1 :         if (diff > 0.1 * m_buffer->size)
     134             :         {
     135           1 :             m_wr_odd = !m_wr_odd;
     136             :         }
     137             :     }
     138       10003 :     m_buffer->pc_ptr = p_addr;
     139       10003 :     m_reader_cond.notify_one();
     140       10004 : }
     141             : 
     142           5 : void FileFromHostBuffer::copy_from_dma_buffer_to_file()
     143             : {
     144           5 :     LOG_INFO("read_from_dma_buffer thread started");
     145           5 :     uint64_t data_offset;
     146           5 :     int blocks_to_copy(0), copied_blocks(0);
     147             : 
     148        6783 :     while (m_run_flag.load())
     149             :     {
     150             : 
     151        6773 :         {
     152             :             // wait for data in the FromHost DMA buffer
     153        6773 :             std::unique_lock<std::mutex> lk(m_wake_reader_mutex);
     154        6773 :             using namespace std::chrono_literals;
     155       15359 :             m_reader_cond.wait_for(lk, 500ms, [&] { return !dma_is_empty(); });
     156        6773 :         }
     157             : 
     158        6773 :         {
     159             :             // copy current addresses
     160        6773 :             std::shared_lock<std::shared_mutex> lock(m_driver_mutex);
     161        6773 :             bool even = (m_rd_odd == m_wr_odd);
     162        6773 :             data_offset = m_buffer->emu_fw_ptr - m_buffer->paddr;
     163       13546 :             blocks_to_copy = (m_buffer->size - dma_compute_free_bytes(m_buffer->emu_fw_ptr, m_buffer->pc_ptr, even)) / m_encoder.get_block_size();
     164        6773 :         }
     165             : 
     166        6773 :         LOG_TRACE("Blocks to copy %lu", blocks_to_copy);
     167             : 
     168             :         // What it does: if there is no trickle mode, it works normally. All the blocks are copied and the read pointer is advanced.
     169             :         // If the trickle mode is active (m_fw_reading_trickle is TRUE), it emulates the firmware by reading the buffer a maximum of 100 times to avoid an endless loop.
     170        6773 :         int n_copies = 0;
     171        7673 :         do
     172             :         {   
     173        7673 :             copied_blocks = 0;
     174       14606 :             while (blocks_to_copy > copied_blocks)
     175             :             {
     176        6933 :                 uint64_t input = (data_offset + copied_blocks * m_encoder.get_block_size()) % m_buffer->size;
     177        6933 :                 void *input_ptr = reinterpret_cast<void *>(input + m_buffer->vaddr);
     178        6933 :                 size_t max_blocks = blocks_to_copy - copied_blocks;
     179        6933 :                 LOG_DBG("input ptr 0x%lx, buffer start 0x%lx, end 0x%lx size 0%lu", input_ptr, m_buffer->vaddr, m_buffer->vaddr + m_buffer->size, m_buffer->size);
     180        6933 :                 copied_blocks += m_file.block_write(input_ptr, max_blocks);
     181        6933 :                 LOG_DBG("%lu blocks copied to disk", copied_blocks);
     182             :             }
     183             :         }
     184        7682 :         while (m_fw_reading_trickle.load() && n_copies++ < 100);
     185        6773 :         dma_advance_read_ptr(copied_blocks * m_encoder.get_block_size());
     186             :     }
     187           5 : }
     188             : 
     189        6773 : void FileFromHostBuffer::dma_advance_read_ptr(size_t bytes)
     190             : {
     191        6773 :     LOG_TRACE("Advancing of %lu bytes", bytes);
     192        6773 :     if (bytes == 0)
     193             :     {
     194        6773 :         return;
     195             :     }
     196        6733 :     std::scoped_lock<std::shared_mutex> lock(m_driver_mutex);
     197        6733 :     m_buffer->emu_fw_ptr += bytes;
     198        6733 :     if (m_buffer->emu_fw_ptr == m_buffer->pend)
     199             :     {
     200           1 :         m_buffer->emu_fw_ptr = m_buffer->paddr;
     201           1 :         m_rd_odd = !m_rd_odd;
     202             :     }
     203        6733 : }

Generated by: LCOV version 1.0