Koheron / koheron-sdk

SDK for FPGA / Linux Instruments
https://www.koheron.com/software-development-kit/
Other
101 stars 41 forks source link

Using S2MM DMA in Koheron SDK #548

Open jahampel opened 2 years ago

jahampel commented 2 years ago

I am currently working on porting a design that utilizes an AXI S2MM DMA to the Alpha-250 board using the Koheron SDK, but I'm having problems figuring out how to access the DMA through the C++ driver. The documentation on this topic is a bit sparse (either that, or I just couldn't find the correct page), and I unfortunately was not able to figure it out by looking at the phase noise analyzer reference design.

The reference design utilizes three memory regions that the S2MM driver (dma-s2mm.hpp) seems to require -- ram (at 0x1e000000), dma (at 0x80000000) and axi_hp0 (at 0xf8000000) as per the config.yml file. When I build the block design and open it in the Vivado GUI, the dma region is the same as in the config file, but the axi_hp0 memory region is at 0x1e000000 while there is no memory region at all assigned to 0xf80000000. This made it quite difficult for me to figure it out from the reference design, and, alas, I still haven't been able to.

The S2MM driver seems to require the memory regions dma, axi_hp0 and ram in the config file (please correct me if I'm wrong). If I leave out any one of them, the design fails to build with the error message <memory I left out> is not a member of 'mem'. So all three of them need to have addresses assigned to them and all three of them probably should do something, but I was not able to find out which one of them should be which. The design I'm working with only has two memory regions associated with the S2MM IP -- axi_dma_0 and the PS axi_hp0 -- and I cannot find out what the third one is supposed to be, as it does not seem to be assigned to anything in the block design of the reference design, despite having an address offset and address range in the config.yml file.

I must apologize that I unfortunately cannot share my design as it is confidential but I hope that my explanation outlines my problem reasonably well.

Now my questions:

I know the third question is a lot to ask, but I would already be very thankful if you could answer my first and second question.

Thank you in advance, Jakob

tvanderbruggen commented 2 years ago

The DmaS2MM driver only requires the memory regions dma and axi_hp0, which are corresponding the regions axi_dma_0 and the PS axi_hp0 in your design (basically you need to rename axi_dma_0 to dma).

To transfer data from the S2MM IP to a given memory use the function start_transfer(uint32_t dest_addr, uint32_t length) where dest_addr is the destination memory address and length is the number of bytes to transfer.

In the phase noise analyzer design the destination is the ram memory, which is a dedicated RAM buffer not accessible to the OS. But the ram memory is not required to use the DmaS2MM driver, and you can use the destination memory required by your design instead.

You can define your destination memory region in the config.yml file:

memory:
  # ... Other memories ...
  - name: dest_mem       # Your destination memory
    offset: '0xXXXXXXXX' # Its address
    range: YYY           # Its size
  - name: dma
    offset: '0x80000000'
    range: 64K
  - name: axi_hp0
    offset: '0xF8008000'
    range: 4K

and use the parameters when calling start_transfer:

// dma is the instance of the DmaS2MM driver
dma.start_transfer(mem::dest_mem, sizeof(int32_t) * n); // Transfers n int32_t to dest_mem 
dma.wait_for_transfer(dma_transfer_duration); // Wait for transfer to be done (dma_transfer_duration in seconds)
// The data are now loaded in the dest_mem memory

I hope this answers your question.

jahampel commented 2 years ago

Indeed, this is exactly what I have been looking for. I believe I understand it now. Thank you for your swift response and explanation!