diff --git a/fpga/etc/fpga.json b/fpga/etc/fpga.json index 5f982e2a8..dbf7aaa6f 100644 --- a/fpga/etc/fpga.json +++ b/fpga/etc/fpga.json @@ -33,14 +33,25 @@ "hier_0_axi_dma_axi_dma_0": { "vlnv": "xilinx.com:ip:axi_dma:7.1", "memory-view": { - "M_AXI_SG": { - "bram_0_axi_bram_ctrl_0": { - "Mem0": { + "M_AXI_MM2S": { + "pcie_0_axi_pcie_0": { + "BAR0": { "baseaddr": 0, - "highaddr": 8191, - "size": 8192 + "highaddr": 4294967295, + "size": 4294967296 } - }, + } + }, + "M_AXI_S2MM": { + "pcie_0_axi_pcie_0": { + "BAR0": { + "baseaddr": 0, + "highaddr": 4294967295, + "size": 4294967296 + } + } + }, + "M_AXI_SG": { "hier_0_axi_dma_axi_dma_1": { "Reg": { "baseaddr": 8192, @@ -109,6 +120,27 @@ "size": 4096 } }, + "mem_0": { + "Reg": { + "baseaddr": 57344, + "highaddr": 61439, + "size": 4096 + } + }, + "rtds2gpu_0": { + "Reg": { + "baseaddr": 61440, + "highaddr": 65535, + "size": 4096 + } + }, + "bram_0_axi_bram_ctrl_0": { + "Mem0": { + "baseaddr": 65536, + "highaddr": 73727, + "size": 8192 + } + }, "pcie_0_axi_pcie_0": { "CTL0": { "baseaddr": 268435456, @@ -116,24 +148,6 @@ "size": 268435456 } } - }, - "M_AXI_MM2S": { - "pcie_0_axi_pcie_0": { - "BAR0": { - "baseaddr": 0, - "highaddr": 4294967295, - "size": 4294967296 - } - } - }, - "M_AXI_S2MM": { - "pcie_0_axi_pcie_0": { - "BAR0": { - "baseaddr": 0, - "highaddr": 4294967295, - "size": 4294967296 - } - } } }, "ports": [ @@ -234,7 +248,7 @@ "name": "S04_AXIS" } ], - "num_ports": 7 + "num_ports": 8 }, "hier_0_hls_dft_0": { "vlnv": "acs.eonerc.rwth-aachen.de:hls:hls_dft:1.1", @@ -274,17 +288,24 @@ "irq_case": "pcie_0_axi_pcie_intc_0:7" } }, + "mem_0": { + "vlnv": "xilinx.com:hls:mem:1.6", + "memory-view": { + "m_axi_gmem": { + "pcie_0_axi_pcie_0": { + "BAR0": { + "baseaddr": 0, + "highaddr": 4294967295, + "size": 4294967296 + } + } + } + } + }, "pcie_0_axi_pcie_0": { "vlnv": "xilinx.com:ip:axi_pcie:2.8", "memory-view": { "M_AXI": { - "bram_0_axi_bram_ctrl_0": { - "Mem0": { - "baseaddr": 0, - "highaddr": 8191, - "size": 8192 - } - }, "hier_0_axi_dma_axi_dma_1": { "Reg": { "baseaddr": 8192, @@ -353,6 +374,27 @@ "size": 4096 } }, + "mem_0": { + "Reg": { + "baseaddr": 57344, + "highaddr": 61439, + "size": 4096 + } + }, + "rtds2gpu_0": { + "Reg": { + "baseaddr": 61440, + "highaddr": 65535, + "size": 4096 + } + }, + "bram_0_axi_bram_ctrl_0": { + "Mem0": { + "baseaddr": 65536, + "highaddr": 73727, + "size": 8192 + } + }, "pcie_0_axi_pcie_0": { "CTL0": { "baseaddr": 268435456, @@ -382,6 +424,27 @@ "pcie_0_axi_reset_0": { "vlnv": "xilinx.com:ip:axi_gpio:2.0" }, + "rtds2gpu_0": { + "vlnv": "xilinx.com:hls:rtds2gpu:1.0", + "memory-view": { + "m_axi_axi_mm": { + "pcie_0_axi_pcie_0": { + "BAR0": { + "baseaddr": 0, + "highaddr": 4294967295, + "size": 4294967296 + } + } + } + }, + "ports": [ + { + "role": "slave", + "target": "hier_0_axis_interconnect_0_axis_interconnect_0_xbar:7", + "name": "rtds_input" + } + ] + }, "timer_0_axi_timer_0": { "vlnv": "xilinx.com:ip:axi_timer:2.0", "irqs": { diff --git a/fpga/include/villas/fpga/ips/dma.hpp b/fpga/include/villas/fpga/ips/dma.hpp index 963c20cda..12cf0236a 100644 --- a/fpga/include/villas/fpga/ips/dma.hpp +++ b/fpga/include/villas/fpga/ips/dma.hpp @@ -43,7 +43,10 @@ public: bool init(); bool reset(); + // memory-mapped to stream (MM2S) bool write(const MemoryBlock& mem, size_t len); + + // stream to memory-mapped (S2MM) bool read(const MemoryBlock& mem, size_t len); size_t writeComplete() diff --git a/fpga/include/villas/fpga/ips/rtds2gpu.hpp b/fpga/include/villas/fpga/ips/rtds2gpu.hpp new file mode 100644 index 000000000..bcca8c069 --- /dev/null +++ b/fpga/include/villas/fpga/ips/rtds2gpu.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include +#include + +#include "rtds2gpu/xrtds2gpu.h" + +namespace villas { +namespace fpga { +namespace ip { + + +class Rtds2Gpu : public IpNode +{ +public: + friend class Rtds2GpuFactory; + + bool init(); + + void dump(); + + bool startOnce(const MemoryBlock& mem, size_t frameSize); + + bool isDone(); + +private: + static constexpr const char* registerMemory = "Reg"; + static constexpr const char* axiInterface = "m_axi_axi_mm"; + static constexpr const char* streamInterface = "rtds_input"; + + std::list getMemoryBlocks() const + { return { registerMemory }; } + + XRtds2gpu xInstance; +}; + + +class Rtds2GpuFactory : public IpNodeFactory { +public: + Rtds2GpuFactory(); + + IpCore* create() + { return new Rtds2Gpu; } + + std::string + getName() const + { return "Rtds2Gpu"; } + + std::string + getDescription() const + { return "HLS RTDS2GPU IP"; } + + Vlnv getCompatibleVlnv() const + { return {"xilinx.com:hls:rtds2gpu:"}; } +}; + +} // namespace ip +} // namespace fpga +} // namespace villas diff --git a/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu.h b/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu.h new file mode 100644 index 000000000..38770aadb --- /dev/null +++ b/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu.h @@ -0,0 +1,114 @@ +// ============================================================== +// File generated by Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC +// Version: 2017.3 +// Copyright (C) 1986-2017 Xilinx, Inc. All Rights Reserved. +// +// ============================================================== + +#ifndef XRTDS2GPU_H +#define XRTDS2GPU_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#ifndef __linux__ +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xil_io.h" +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include "xrtds2gpu_hw.h" + +/**************************** Type Definitions ******************************/ +#ifdef __linux__ +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +#else +typedef struct { + u16 DeviceId; + u32 Ctrl_BaseAddress; +} XRtds2gpu_Config; +#endif + +typedef struct { + u32 Ctrl_BaseAddress; + u32 IsReady; +} XRtds2gpu; + +/***************** Macros (Inline Functions) Definitions *********************/ +#ifndef __linux__ +#define XRtds2gpu_WriteReg(BaseAddress, RegOffset, Data) \ + Xil_Out32((BaseAddress) + (RegOffset), (u32)(Data)) +#define XRtds2gpu_ReadReg(BaseAddress, RegOffset) \ + Xil_In32((BaseAddress) + (RegOffset)) +#else +#define XRtds2gpu_WriteReg(BaseAddress, RegOffset, Data) \ + *(volatile u32*)((BaseAddress) + (RegOffset)) = (u32)(Data) +#define XRtds2gpu_ReadReg(BaseAddress, RegOffset) \ + *(volatile u32*)((BaseAddress) + (RegOffset)) + +#define Xil_AssertVoid(expr) assert(expr) +#define Xil_AssertNonvoid(expr) assert(expr) + +#define XST_SUCCESS 0 +#define XST_DEVICE_NOT_FOUND 2 +#define XST_OPEN_DEVICE_FAILED 3 +#define XIL_COMPONENT_IS_READY 1 +#endif + +/************************** Function Prototypes *****************************/ +#ifndef __linux__ +int XRtds2gpu_Initialize(XRtds2gpu *InstancePtr, u16 DeviceId); +XRtds2gpu_Config* XRtds2gpu_LookupConfig(u16 DeviceId); +int XRtds2gpu_CfgInitialize(XRtds2gpu *InstancePtr, XRtds2gpu_Config *ConfigPtr); +#else +int XRtds2gpu_Initialize(XRtds2gpu *InstancePtr, const char* InstanceName); +int XRtds2gpu_Release(XRtds2gpu *InstancePtr); +#endif + +void XRtds2gpu_Start(XRtds2gpu *InstancePtr); +u32 XRtds2gpu_IsDone(XRtds2gpu *InstancePtr); +u32 XRtds2gpu_IsIdle(XRtds2gpu *InstancePtr); +u32 XRtds2gpu_IsReady(XRtds2gpu *InstancePtr); +void XRtds2gpu_EnableAutoRestart(XRtds2gpu *InstancePtr); +void XRtds2gpu_DisableAutoRestart(XRtds2gpu *InstancePtr); + +void XRtds2gpu_Set_baseaddr(XRtds2gpu *InstancePtr, u32 Data); +u32 XRtds2gpu_Get_baseaddr(XRtds2gpu *InstancePtr); +void XRtds2gpu_Set_data_offset(XRtds2gpu *InstancePtr, u32 Data); +u32 XRtds2gpu_Get_data_offset(XRtds2gpu *InstancePtr); +void XRtds2gpu_Set_doorbell_offset(XRtds2gpu *InstancePtr, u32 Data); +u32 XRtds2gpu_Get_doorbell_offset(XRtds2gpu *InstancePtr); +void XRtds2gpu_Set_status_i(XRtds2gpu *InstancePtr, u32 Data); +u32 XRtds2gpu_Get_status_i(XRtds2gpu *InstancePtr); +u32 XRtds2gpu_Get_status_o(XRtds2gpu *InstancePtr); +void XRtds2gpu_Set_frame_size(XRtds2gpu *InstancePtr, u32 Data); +u32 XRtds2gpu_Get_frame_size(XRtds2gpu *InstancePtr); + +void XRtds2gpu_InterruptGlobalEnable(XRtds2gpu *InstancePtr); +void XRtds2gpu_InterruptGlobalDisable(XRtds2gpu *InstancePtr); +void XRtds2gpu_InterruptEnable(XRtds2gpu *InstancePtr, u32 Mask); +void XRtds2gpu_InterruptDisable(XRtds2gpu *InstancePtr, u32 Mask); +void XRtds2gpu_InterruptClear(XRtds2gpu *InstancePtr, u32 Mask); +u32 XRtds2gpu_InterruptGetEnabled(XRtds2gpu *InstancePtr); +u32 XRtds2gpu_InterruptGetStatus(XRtds2gpu *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu_hw.h b/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu_hw.h new file mode 100644 index 000000000..198963c7e --- /dev/null +++ b/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu_hw.h @@ -0,0 +1,63 @@ +// ============================================================== +// File generated by Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC +// Version: 2017.3 +// Copyright (C) 1986-2017 Xilinx, Inc. All Rights Reserved. +// +// ============================================================== + +// CTRL +// 0x00 : Control signals +// bit 0 - ap_start (Read/Write/COH) +// bit 1 - ap_done (Read/COR) +// bit 2 - ap_idle (Read) +// bit 3 - ap_ready (Read) +// bit 7 - auto_restart (Read/Write) +// others - reserved +// 0x04 : Global Interrupt Enable Register +// bit 0 - Global Interrupt Enable (Read/Write) +// others - reserved +// 0x08 : IP Interrupt Enable Register (Read/Write) +// bit 0 - Channel 0 (ap_done) +// bit 1 - Channel 1 (ap_ready) +// others - reserved +// 0x0c : IP Interrupt Status Register (Read/TOW) +// bit 0 - Channel 0 (ap_done) +// bit 1 - Channel 1 (ap_ready) +// others - reserved +// 0x10 : Data signal of baseaddr +// bit 31~0 - baseaddr[31:0] (Read/Write) +// 0x14 : reserved +// 0x18 : Data signal of data_offset +// bit 31~0 - data_offset[31:0] (Read/Write) +// 0x1c : reserved +// 0x20 : Data signal of doorbell_offset +// bit 31~0 - doorbell_offset[31:0] (Read/Write) +// 0x24 : reserved +// 0x28 : Data signal of status_i +// bit 31~0 - status_i[31:0] (Read/Write) +// 0x2c : reserved +// 0x30 : Data signal of status_o +// bit 31~0 - status_o[31:0] (Read) +// 0x34 : reserved +// 0x38 : Data signal of frame_size +// bit 31~0 - frame_size[31:0] (Read/Write) +// 0x3c : reserved +// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake) + +#define XRTDS2GPU_CTRL_ADDR_AP_CTRL 0x00 +#define XRTDS2GPU_CTRL_ADDR_GIE 0x04 +#define XRTDS2GPU_CTRL_ADDR_IER 0x08 +#define XRTDS2GPU_CTRL_ADDR_ISR 0x0c +#define XRTDS2GPU_CTRL_ADDR_BASEADDR_DATA 0x10 +#define XRTDS2GPU_CTRL_BITS_BASEADDR_DATA 32 +#define XRTDS2GPU_CTRL_ADDR_DATA_OFFSET_DATA 0x18 +#define XRTDS2GPU_CTRL_BITS_DATA_OFFSET_DATA 32 +#define XRTDS2GPU_CTRL_ADDR_DOORBELL_OFFSET_DATA 0x20 +#define XRTDS2GPU_CTRL_BITS_DOORBELL_OFFSET_DATA 32 +#define XRTDS2GPU_CTRL_ADDR_STATUS_I_DATA 0x28 +#define XRTDS2GPU_CTRL_BITS_STATUS_I_DATA 32 +#define XRTDS2GPU_CTRL_ADDR_STATUS_O_DATA 0x30 +#define XRTDS2GPU_CTRL_BITS_STATUS_O_DATA 32 +#define XRTDS2GPU_CTRL_ADDR_FRAME_SIZE_DATA 0x38 +#define XRTDS2GPU_CTRL_BITS_FRAME_SIZE_DATA 32 + diff --git a/fpga/lib/CMakeLists.txt b/fpga/lib/CMakeLists.txt index eea93a1c9..10165cdd0 100644 --- a/fpga/lib/CMakeLists.txt +++ b/fpga/lib/CMakeLists.txt @@ -15,6 +15,9 @@ set(SOURCES ips/bram.cpp ips/rtds.cpp + ips/rtds2gpu/rtds2gpu.cpp + ips/rtds2gpu/xrtds2gpu.c + kernel/kernel.c kernel/pci.c kernel/vfio.cpp diff --git a/fpga/lib/ips/dma.cpp b/fpga/lib/ips/dma.cpp index 3d8f9a3b6..7408461df 100644 --- a/fpga/lib/ips/dma.cpp +++ b/fpga/lib/ips/dma.cpp @@ -165,7 +165,7 @@ Dma::write(const MemoryBlock& mem, size_t len) mem.getAddrSpaceId()); const void* buf = reinterpret_cast(translation.getLocalAddr(0)); - logger->debug("Write to address: {:p}", buf); + logger->debug("Write to stream from address {:p}", buf); return hasScatterGather() ? writeSG(buf, len) : writeSimple(buf, len); } @@ -180,7 +180,7 @@ Dma::read(const MemoryBlock& mem, size_t len) mem.getAddrSpaceId()); void* buf = reinterpret_cast(translation.getLocalAddr(0)); - logger->debug("Read from address: {:p}", buf); + logger->debug("Read from stream and write to address {:p}", buf); return hasScatterGather() ? readSG(buf, len) : readSimple(buf, len); } diff --git a/fpga/lib/ips/rtds2gpu/rtds2gpu.cpp b/fpga/lib/ips/rtds2gpu/rtds2gpu.cpp new file mode 100644 index 000000000..50bb34c90 --- /dev/null +++ b/fpga/lib/ips/rtds2gpu/rtds2gpu.cpp @@ -0,0 +1,87 @@ +#include +#include + +#include +#include + +#include "log.hpp" + +namespace villas { +namespace fpga { +namespace ip { + +static Rtds2GpuFactory factory; + +bool Rtds2Gpu::init() +{ + xInstance.IsReady = XIL_COMPONENT_IS_READY; + xInstance.Ctrl_BaseAddress = getBaseAddr(registerMemory); + + // make sure IP is stopped for now + XRtds2gpu_DisableAutoRestart(&xInstance); + + dump(); + + return true; +} + +void Rtds2Gpu::dump() +{ + const auto baseaddr = XRtds2gpu_Get_baseaddr(&xInstance); + const auto data_offset = XRtds2gpu_Get_data_offset(&xInstance); + const auto doorbell_offset = XRtds2gpu_Get_doorbell_offset(&xInstance); + const auto frame_size = XRtds2gpu_Get_frame_size(&xInstance); + const auto status = XRtds2gpu_Get_status_o(&xInstance); + + logger->debug("Rtds2Gpu registers (IP base {:#x}):", xInstance.Ctrl_BaseAddress); + logger->debug(" Base address (bytes): {:#x}", baseaddr); + logger->debug(" Doorbell offset (bytes): {:#x}", doorbell_offset); + logger->debug(" Data offset (bytes): {:#x}", data_offset); + logger->debug(" Frame size (words): {:#x}", frame_size); + logger->debug(" Status: {:#x}", status); +} + +bool Rtds2Gpu::startOnce(const MemoryBlock& mem, size_t frameSize) +{ + auto& mm = MemoryManager::get(); + + auto translationFromIp = mm.getTranslation( + getMasterAddrSpaceByInterface(axiInterface), + mem.getAddrSpaceId()); + + // make sure IP is stopped for now + XRtds2gpu_DisableAutoRestart(&xInstance); +// while(not XRtds2gpu_IsIdle(&xInstance) and not XRtds2gpu_IsDone(&xInstance)); + + // set address of memory block in HLS IP + XRtds2gpu_Set_baseaddr(&xInstance, translationFromIp.getLocalAddr(0)); + + XRtds2gpu_Set_doorbell_offset(&xInstance, 0); + XRtds2gpu_Set_data_offset(&xInstance, 4); + XRtds2gpu_Set_frame_size(&xInstance, frameSize); + + // prepare memory with all zeroes + auto translationFromProcess = mm.getTranslationFromProcess(mem.getAddrSpaceId()); + auto memory = reinterpret_cast(translationFromProcess.getLocalAddr(0)); + memset(memory, 0, mem.getSize()); + + // start IP +// XRtds2gpu_EnableAutoRestart(&xInstance); + XRtds2gpu_Start(&xInstance); + + return true; +} + +bool Rtds2Gpu::isDone() +{ + return XRtds2gpu_IsDone(&xInstance); +} + +Rtds2GpuFactory::Rtds2GpuFactory() : + IpNodeFactory(getName()) +{ +} + +} // namespace ip +} // namespace fpga +} // namespace villas diff --git a/fpga/lib/ips/rtds2gpu/xrtds2gpu.c b/fpga/lib/ips/rtds2gpu/xrtds2gpu.c new file mode 100644 index 000000000..f7f1dadb6 --- /dev/null +++ b/fpga/lib/ips/rtds2gpu/xrtds2gpu.c @@ -0,0 +1,228 @@ +// ============================================================== +// File generated by Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC +// Version: 2017.3 +// Copyright (C) 1986-2017 Xilinx, Inc. All Rights Reserved. +// +// ============================================================== + +/***************************** Include Files *********************************/ +#include + +/************************** Function Implementation *************************/ +#ifndef __linux__ +int XRtds2gpu_CfgInitialize(XRtds2gpu *InstancePtr, XRtds2gpu_Config *ConfigPtr) { + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + InstancePtr->Ctrl_BaseAddress = ConfigPtr->Ctrl_BaseAddress; + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + return XST_SUCCESS; +} +#endif + +void XRtds2gpu_Start(XRtds2gpu *InstancePtr) { + u32 Data; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_AP_CTRL) & 0x80; + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_AP_CTRL, Data | 0x01); +} + +u32 XRtds2gpu_IsDone(XRtds2gpu *InstancePtr) { + u32 Data; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_AP_CTRL); + return (Data >> 1) & 0x1; +} + +u32 XRtds2gpu_IsIdle(XRtds2gpu *InstancePtr) { + u32 Data; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_AP_CTRL); + return (Data >> 2) & 0x1; +} + +u32 XRtds2gpu_IsReady(XRtds2gpu *InstancePtr) { + u32 Data; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_AP_CTRL); + // check ap_start to see if the pcore is ready for next input + return !(Data & 0x1); +} + +void XRtds2gpu_EnableAutoRestart(XRtds2gpu *InstancePtr) { + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_AP_CTRL, 0x80); +} + +void XRtds2gpu_DisableAutoRestart(XRtds2gpu *InstancePtr) { + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_AP_CTRL, 0); +} + +void XRtds2gpu_Set_baseaddr(XRtds2gpu *InstancePtr, u32 Data) { + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_BASEADDR_DATA, Data); +} + +u32 XRtds2gpu_Get_baseaddr(XRtds2gpu *InstancePtr) { + u32 Data; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_BASEADDR_DATA); + return Data; +} + +void XRtds2gpu_Set_data_offset(XRtds2gpu *InstancePtr, u32 Data) { + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_DATA_OFFSET_DATA, Data); +} + +u32 XRtds2gpu_Get_data_offset(XRtds2gpu *InstancePtr) { + u32 Data; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_DATA_OFFSET_DATA); + return Data; +} + +void XRtds2gpu_Set_doorbell_offset(XRtds2gpu *InstancePtr, u32 Data) { + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_DOORBELL_OFFSET_DATA, Data); +} + +u32 XRtds2gpu_Get_doorbell_offset(XRtds2gpu *InstancePtr) { + u32 Data; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_DOORBELL_OFFSET_DATA); + return Data; +} + +void XRtds2gpu_Set_status_i(XRtds2gpu *InstancePtr, u32 Data) { + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_STATUS_I_DATA, Data); +} + +u32 XRtds2gpu_Get_status_i(XRtds2gpu *InstancePtr) { + u32 Data; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_STATUS_I_DATA); + return Data; +} + +u32 XRtds2gpu_Get_status_o(XRtds2gpu *InstancePtr) { + u32 Data; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_STATUS_O_DATA); + return Data; +} + +void XRtds2gpu_Set_frame_size(XRtds2gpu *InstancePtr, u32 Data) { + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_FRAME_SIZE_DATA, Data); +} + +u32 XRtds2gpu_Get_frame_size(XRtds2gpu *InstancePtr) { + u32 Data; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_FRAME_SIZE_DATA); + return Data; +} + +void XRtds2gpu_InterruptGlobalEnable(XRtds2gpu *InstancePtr) { + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_GIE, 1); +} + +void XRtds2gpu_InterruptGlobalDisable(XRtds2gpu *InstancePtr) { + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_GIE, 0); +} + +void XRtds2gpu_InterruptEnable(XRtds2gpu *InstancePtr, u32 Mask) { + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Register = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_IER); + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_IER, Register | Mask); +} + +void XRtds2gpu_InterruptDisable(XRtds2gpu *InstancePtr, u32 Mask) { + u32 Register; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + Register = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_IER); + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_IER, Register & (~Mask)); +} + +void XRtds2gpu_InterruptClear(XRtds2gpu *InstancePtr, u32 Mask) { + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_ISR, Mask); +} + +u32 XRtds2gpu_InterruptGetEnabled(XRtds2gpu *InstancePtr) { + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + return XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_IER); +} + +u32 XRtds2gpu_InterruptGetStatus(XRtds2gpu *InstancePtr) { + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + return XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_ISR); +} + diff --git a/fpga/scripts/hwdef-parse.py b/fpga/scripts/hwdef-parse.py index 09abe905a..d93cd77af 100755 --- a/fpga/scripts/hwdef-parse.py +++ b/fpga/scripts/hwdef-parse.py @@ -36,7 +36,9 @@ whitelist = [ [ 'xilinx.com', 'ip', 'axi_gpio' ], [ 'xilinx.com', 'ip', 'axi_bram_ctrl' ], [ 'xilinx.com', 'ip', 'axis_data_fifo' ], - [ 'xilinx.com', 'ip', 'axi_pcie' ] + [ 'xilinx.com', 'ip', 'axi_pcie' ], + [ 'xilinx.com', 'hls', 'rtds2gpu' ], + [ 'xilinx.com', 'hls', 'mem' ] ] # List of VLNI ids of AXI4-Stream infrastructure IP cores which do not alter data diff --git a/fpga/tests/CMakeLists.txt b/fpga/tests/CMakeLists.txt index 00d80dcfa..6eb34491a 100644 --- a/fpga/tests/CMakeLists.txt +++ b/fpga/tests/CMakeLists.txt @@ -5,6 +5,7 @@ set(SOURCES dma.cpp fifo.cpp rtds.cpp + rtds2gpu.cpp timer.cpp graph.cpp ) diff --git a/fpga/tests/rtds2gpu.cpp b/fpga/tests/rtds2gpu.cpp new file mode 100644 index 000000000..adc2603ae --- /dev/null +++ b/fpga/tests/rtds2gpu.cpp @@ -0,0 +1,109 @@ +/** FIFO unit test. + * + * @file + * @author Steffen Vogel + * @copyright 2017, Steffen Vogel + * @license GNU General Public License (version 3) + * + * VILLASfpga + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "global.hpp" + + +static constexpr size_t SAMPLE_SIZE = 4; +static constexpr size_t SAMPLE_COUNT = 8; +static constexpr size_t FRAME_SIZE = SAMPLE_COUNT * SAMPLE_SIZE; + + +Test(fpga, rtds2gpu, .description = "Rtds2Gpu") +{ + auto logger = loggerGetOrCreate("unittest:rtds2gpu"); + + for(auto& ip : state.cards.front()->ips) { + if(*ip != villas::fpga::Vlnv("xilinx.com:hls:rtds2gpu:")) + continue; + + logger->info("Testing {}", *ip); + + auto rtds2gpu = reinterpret_cast(*ip); + + auto dmaMem0 = villas::HostDmaRam::getAllocator(0).allocate(FRAME_SIZE + 4); + auto dmaMem1 = villas::HostDmaRam::getAllocator(0).allocate(FRAME_SIZE + 4); + +// continue; + + + + auto axiSwitch = reinterpret_cast( + state.cards.front()->lookupIp(villas::fpga::Vlnv("xilinx.com:ip:axis_switch:"))); + cr_assert_not_null(axiSwitch); + + auto dma = reinterpret_cast( + state.cards.front()->lookupIp(villas::fpga::Vlnv("xilinx.com:ip:axi_dma:"))); + cr_assert_not_null(dma); + + memset(&dmaMem0, 0x55, dmaMem0.getMemoryBlock().getSize()); + memset(&dmaMem1, 0x11, dmaMem1.getMemoryBlock().getSize()); + + puts("Before:"); + for(size_t i = 0; i < dmaMem0.getMemoryBlock().getSize(); i++) { + printf("0x%02x ", dmaMem0[i]); + } + puts(""); + + rtds2gpu.dump(); + + cr_assert(axiSwitch->connect(7, 6)); + cr_assert(axiSwitch->connect(6, 7)); + + + + cr_assert(rtds2gpu.startOnce(dmaMem0.getMemoryBlock(), SAMPLE_COUNT), + "Preparing Rtds2Gpu IP failed"); + + cr_assert(dma->write(dmaMem1.getMemoryBlock(), FRAME_SIZE)); + +// cr_assert(axiSwitch->connect(6, 6)); // loopback +// cr_assert(dma->read(dmaMem1.getMemoryBlock(), FRAME_SIZE)); +// cr_assert(dma->readComplete()); + + cr_assert(dma->writeComplete()); + + puts("After:"); + for(size_t i = 0; i < dmaMem0.getMemoryBlock().getSize(); i++) { + printf("0x%02x ", dmaMem0[i]); + } + puts(""); + + + rtds2gpu.dump(); + + cr_assert(rtds2gpu.isDone()); + + logger->info(TXT_GREEN("Passed")); + } +}