From 3d73c759eadbe6e58d1d339b688dfdefab2c8cf8 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 29 Feb 2024 19:34:27 +0100 Subject: [PATCH] Reformat all code with clang-format Signed-off-by: Steffen Vogel --- common/include/villas/graph/edge.hpp | 3 +- common/include/villas/graph/vertex.hpp | 5 +- .../include/villas/kernel/vfio_container.hpp | 3 +- common/include/villas/memory_manager.hpp | 2 +- common/include/villas/plugin.hpp | 5 +- fpga/gpu/include/villas/gpu.hpp | 83 +- fpga/gpu/kernels.hpp | 10 +- fpga/gpu/src/gpu.cpp | 705 ++- fpga/include/villas/fpga/card.hpp | 46 +- fpga/include/villas/fpga/config.h | 8 +- fpga/include/villas/fpga/core.hpp | 372 +- fpga/include/villas/fpga/dma.h | 12 +- fpga/include/villas/fpga/ips/aurora.hpp | 38 +- .../include/villas/fpga/ips/aurora_xilinx.hpp | 20 +- fpga/include/villas/fpga/ips/bram.hpp | 57 +- fpga/include/villas/fpga/ips/dma.hpp | 227 +- fpga/include/villas/fpga/ips/emc.hpp | 24 +- fpga/include/villas/fpga/ips/fifo.hpp | 33 +- fpga/include/villas/fpga/ips/gpio.hpp | 16 +- fpga/include/villas/fpga/ips/gpu2rtds.hpp | 73 +- fpga/include/villas/fpga/ips/hls.hpp | 191 +- fpga/include/villas/fpga/ips/i2c.hpp | 34 +- fpga/include/villas/fpga/ips/intc.hpp | 38 +- fpga/include/villas/fpga/ips/pcie.hpp | 61 +- fpga/include/villas/fpga/ips/rtds.hpp | 40 +- fpga/include/villas/fpga/ips/rtds2gpu.hpp | 87 +- .../fpga/ips/rtds2gpu/register_types.hpp | 66 +- .../villas/fpga/ips/rtds2gpu/xgpu2rtds_hw.h | 23 +- .../villas/fpga/ips/rtds2gpu/xrtds2gpu.h | 49 +- .../villas/fpga/ips/rtds2gpu/xrtds2gpu_hw.h | 27 +- fpga/include/villas/fpga/ips/timer.hpp | 47 +- fpga/include/villas/fpga/node.hpp | 194 +- fpga/include/villas/fpga/pcie_card.hpp | 47 +- fpga/include/villas/fpga/utils.hpp | 137 +- fpga/include/villas/fpga/vlnv.hpp | 67 +- fpga/lib/card.cpp | 140 +- fpga/lib/dma.cpp | 180 +- fpga/lib/ips/aurora.cpp | 113 +- fpga/lib/ips/bram.cpp | 26 +- fpga/lib/ips/emc.cpp | 180 +- fpga/lib/ips/fifo.cpp | 97 +- fpga/lib/ips/gpio.cpp | 8 +- fpga/lib/ips/intc.cpp | 141 +- fpga/lib/ips/pcie.cpp | 197 +- fpga/lib/ips/rtds.cpp | 105 +- fpga/lib/ips/rtds2gpu/gpu2rtds.cpp | 95 +- fpga/lib/ips/rtds2gpu/rtds2gpu.cpp | 151 +- fpga/lib/ips/rtds2gpu/xrtds2gpu.c | 227 +- fpga/lib/ips/switch.cpp | 166 +- fpga/lib/ips/timer.cpp | 54 +- fpga/lib/memory.cpp | 16 +- fpga/lib/pcie_card.cpp | 79 +- fpga/lib/utils.cpp | 72 +- fpga/lib/vlnv.cpp | 71 +- fpga/src/pcimem.c | 183 +- fpga/src/villas-fpga-pipe.cpp | 189 +- fpga/tests/unit/dma.c | 151 +- fpga/tests/unit/dma.cpp | 112 +- fpga/tests/unit/fifo.cpp | 83 +- fpga/tests/unit/fpga.cpp | 81 +- fpga/tests/unit/global.hpp | 2 +- fpga/tests/unit/gpu.cpp | 155 +- fpga/tests/unit/logging.cpp | 142 +- fpga/tests/unit/main.cpp | 63 +- fpga/tests/unit/rtds.cpp | 131 +- fpga/tests/unit/rtds2gpu.cpp | 420 +- fpga/tests/unit/rtds_rtt.cpp | 95 +- fpga/tests/unit/timer.cpp | 59 +- fpga/thirdparty/CLI11/CLI11.hpp | 4788 +++++++++-------- fpga/thirdparty/rang/rang.hpp | 723 ++- include/villas/config_class.hpp | 2 +- 71 files changed, 6062 insertions(+), 6285 deletions(-) diff --git a/common/include/villas/graph/edge.hpp b/common/include/villas/graph/edge.hpp index 6beaf9137..e2d8c179c 100644 --- a/common/include/villas/graph/edge.hpp +++ b/common/include/villas/graph/edge.hpp @@ -47,6 +47,5 @@ private: #ifndef FMT_LEGACY_OSTREAM_FORMATTER template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; #endif diff --git a/common/include/villas/graph/vertex.hpp b/common/include/villas/graph/vertex.hpp index 71a9f9c3d..4aecf5cbd 100644 --- a/common/include/villas/graph/vertex.hpp +++ b/common/include/villas/graph/vertex.hpp @@ -7,9 +7,9 @@ #pragma once +#include #include #include -#include #include namespace villas { @@ -48,6 +48,5 @@ private: #ifndef FMT_LEGACY_OSTREAM_FORMATTER template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; #endif diff --git a/common/include/villas/kernel/vfio_container.hpp b/common/include/villas/kernel/vfio_container.hpp index d728ffc93..08c747dd6 100644 --- a/common/include/villas/kernel/vfio_container.hpp +++ b/common/include/villas/kernel/vfio_container.hpp @@ -35,7 +35,8 @@ static constexpr size_t EXTENSION_SIZE = VFIO_NOIOMMU_IOMMU + 1; class Container { public: - Container(std::vector required_modules = {"vfio", "vfio_pci", "vfio_iommu_type1"}); + Container(std::vector required_modules = {"vfio", "vfio_pci", + "vfio_iommu_type1"}); // No copying allowed because we manage the vfio state in constructor and destructors Container(Container const &) = delete; diff --git a/common/include/villas/memory_manager.hpp b/common/include/villas/memory_manager.hpp index d9d4cd43d..cfed69b84 100644 --- a/common/include/villas/memory_manager.hpp +++ b/common/include/villas/memory_manager.hpp @@ -8,11 +8,11 @@ #pragma once #include +#include #include #include #include #include -#include #include #include #include diff --git a/common/include/villas/plugin.hpp b/common/include/villas/plugin.hpp index ea472d402..f52bb594e 100644 --- a/common/include/villas/plugin.hpp +++ b/common/include/villas/plugin.hpp @@ -8,11 +8,11 @@ #pragma once +#include #include #include #include #include -#include #include #include #include @@ -152,6 +152,5 @@ template void Registry::dump() { #ifndef FMT_LEGACY_OSTREAM_FORMATTER template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; #endif diff --git a/fpga/gpu/include/villas/gpu.hpp b/fpga/gpu/include/villas/gpu.hpp index f4e1c170d..ada9d13a1 100644 --- a/fpga/gpu/include/villas/gpu.hpp +++ b/fpga/gpu/include/villas/gpu.hpp @@ -9,10 +9,10 @@ #include -#include -#include -#include #include +#include +#include +#include namespace villas { namespace gpu { @@ -20,81 +20,78 @@ namespace gpu { class GpuAllocator; class Gpu { - friend GpuAllocator; + friend GpuAllocator; + public: - Gpu(int gpuId); - ~Gpu(); + Gpu(int gpuId); + ~Gpu(); - bool init(); + bool init(); - std::string getName() const; + std::string getName() const; - GpuAllocator &getAllocator() const - { return *allocator; } + GpuAllocator &getAllocator() const { return *allocator; } + bool makeAccessibleToPCIeAndVA(const MemoryBlock &mem); - bool makeAccessibleToPCIeAndVA(const MemoryBlock &mem); + // Make some memory block accssible for this GPU + bool makeAccessibleFromPCIeOrHostRam(const MemoryBlock &mem); - // Make some memory block accssible for this GPU - bool makeAccessibleFromPCIeOrHostRam(const MemoryBlock &mem); + void memcpySync(const MemoryBlock &src, const MemoryBlock &dst, size_t size); - void memcpySync(const MemoryBlock &src, const MemoryBlock &dst, size_t size); + void memcpyKernel(const MemoryBlock &src, const MemoryBlock &dst, + size_t size); - void memcpyKernel(const MemoryBlock &src, const MemoryBlock &dst, size_t size); - - MemoryTranslation - translate(const MemoryBlock &dst); + MemoryTranslation translate(const MemoryBlock &dst); private: - bool registerIoMemory(const MemoryBlock &mem); - bool registerHostMemory(const MemoryBlock &mem); + bool registerIoMemory(const MemoryBlock &mem); + bool registerHostMemory(const MemoryBlock &mem); private: - class impl; - std::unique_ptr pImpl; + class impl; + std::unique_ptr pImpl; - // Master, will be used to derived slave addr spaces for allocation - MemoryManager::AddressSpaceId masterPciEAddrSpaceId; + // Master, will be used to derived slave addr spaces for allocation + MemoryManager::AddressSpaceId masterPciEAddrSpaceId; - MemoryManager::AddressSpaceId slaveMemoryAddrSpaceId; + MemoryManager::AddressSpaceId slaveMemoryAddrSpaceId; - Logger logger; + Logger logger; - int gpuId; + int gpuId; - std::unique_ptr allocator; + std::unique_ptr allocator; }; - class GpuAllocator : public BaseAllocator { public: - static constexpr size_t GpuPageSize = 64UL << 10; + static constexpr size_t GpuPageSize = 64UL << 10; - GpuAllocator(Gpu &gpu); + GpuAllocator(Gpu &gpu); - std::string getName() const; + std::string getName() const; - std::unique_ptr - allocateBlock(size_t size); + std::unique_ptr + allocateBlock(size_t size); private: - Gpu &gpu; - // TODO: replace by multimap (key is available memory) - std::list> chunks; + Gpu &gpu; + // TODO: replace by multimap (key is available memory) + std::list> chunks; }; class GpuFactory : public Plugin { public: - GpuFactory(); + GpuFactory(); - std::list> - make(); + std::list> make(); - void run(void*); + void run(void *); private: - Logger logger; + Logger logger; }; -} // namespace villas } // namespace gpu +} // namespace villas diff --git a/fpga/gpu/kernels.hpp b/fpga/gpu/kernels.hpp index 1ee054ea8..4e3727c04 100644 --- a/fpga/gpu/kernels.hpp +++ b/fpga/gpu/kernels.hpp @@ -13,11 +13,11 @@ namespace villas { namespace gpu { -__global__ void -kernel_mailbox(volatile uint32_t *mailbox, volatile uint32_t* counter); +__global__ void kernel_mailbox(volatile uint32_t *mailbox, + volatile uint32_t *counter); -__global__ void -kernel_memcpy(volatile uint8_t* dst, volatile uint8_t* src, size_t length); +__global__ void kernel_memcpy(volatile uint8_t *dst, volatile uint8_t *src, + size_t length); -} // namespace villas } // namespace gpu +} // namespace villas diff --git a/fpga/gpu/src/gpu.cpp b/fpga/gpu/src/gpu.cpp index 4bd7787de..755c4ef6c 100644 --- a/fpga/gpu/src/gpu.cpp +++ b/fpga/gpu/src/gpu.cpp @@ -5,16 +5,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include -#include #include +#include #include -#include #include +#include #include #include @@ -23,486 +23,459 @@ #include "kernels.hpp" - using namespace villas::gpu; static GpuFactory gpuFactory; -GpuAllocator::GpuAllocator(Gpu &gpu) : - BaseAllocator(gpu.masterPciEAddrSpaceId), - gpu(gpu) -{ - free = [&](MemoryBlock* mem) { - cudaSetDevice(gpu.gpuId); - if (cudaFree(reinterpret_cast(mem->getOffset())) != cudaSuccess) { - logger->warn("cudaFree() failed for {:#x} of size {:#x}", - mem->getOffset(), mem->getSize()); - } +GpuAllocator::GpuAllocator(Gpu &gpu) + : BaseAllocator(gpu.masterPciEAddrSpaceId), gpu(gpu) { + free = [&](MemoryBlock *mem) { + cudaSetDevice(gpu.gpuId); + if (cudaFree(reinterpret_cast(mem->getOffset())) != cudaSuccess) { + logger->warn("cudaFree() failed for {:#x} of size {:#x}", + mem->getOffset(), mem->getSize()); + } - removeMemoryBlock(*mem); - }; + removeMemoryBlock(*mem); + }; } -std::string -villas::gpu::GpuAllocator::getName() const -{ - std::stringstream name; - name << "GpuAlloc" << getAddrSpaceId(); - return name.str(); +std::string villas::gpu::GpuAllocator::getName() const { + std::stringstream name; + name << "GpuAlloc" << getAddrSpaceId(); + return name.str(); } - -GpuFactory::GpuFactory() : - Plugin("cuda", "CUDA capable GPUs") -{ - logger = villas::logging.get("gpu:factory"); +GpuFactory::GpuFactory() : Plugin("cuda", "CUDA capable GPUs") { + logger = villas::logging.get("gpu:factory"); } // Required to be defined here for PIMPL to compile -Gpu::~Gpu() -{ - auto &mm = MemoryManager::get(); - mm.removeAddressSpace(masterPciEAddrSpaceId); +Gpu::~Gpu() { + auto &mm = MemoryManager::get(); + mm.removeAddressSpace(masterPciEAddrSpaceId); } - // We use PIMPL in order to hide gdrcopy types from the public header class Gpu::impl { public: - gdr_t gdr; - struct pci_device pdev; + gdr_t gdr; + struct pci_device pdev; }; -std::string Gpu::getName() const -{ - cudaDeviceProp deviceProp; - if (cudaGetDeviceProperties(&deviceProp, gpuId) != cudaSuccess) { - // Logger not yet availabe - villas::logging.get("gpu")->error("Cannot retrieve properties for GPU {}", gpuId); - throw std::exception(); - } +std::string Gpu::getName() const { + cudaDeviceProp deviceProp; + if (cudaGetDeviceProperties(&deviceProp, gpuId) != cudaSuccess) { + // Logger not yet availabe + villas::logging.get("gpu")->error("Cannot retrieve properties for GPU {}", + gpuId); + throw std::exception(); + } - std::stringstream name; - name << "gpu" << gpuId << "(" << deviceProp.name << ")"; + std::stringstream name; + name << "gpu" << gpuId << "(" << deviceProp.name << ")"; - return name.str(); + return name.str(); } -bool Gpu::registerIoMemory(const MemoryBlock &mem) -{ - auto &mm = MemoryManager::get(); - const auto pciAddrSpaceId = mm.getPciAddressSpace(); +bool Gpu::registerIoMemory(const MemoryBlock &mem) { + auto &mm = MemoryManager::get(); + const auto pciAddrSpaceId = mm.getPciAddressSpace(); - // Check if we need to map anything at all, maybe it's already reachable - try { - // TODO: there might already be a path through the graph, but there's no - // overlapping window, so this will fail badly! - auto translation = mm.getTranslation(masterPciEAddrSpaceId, - mem.getAddrSpaceId()); - if (translation.getSize() >= mem.getSize()) - // There is already a sufficient path - logger->debug("Already mapped through another mapping"); - return true; - else - logger->warn("There's already a mapping, but too small"); - } catch (const std::out_of_range&) { - // Not yet reachable, that's okay, proceed - } + // Check if we need to map anything at all, maybe it's already reachable + try { + // TODO: there might already be a path through the graph, but there's no + // overlapping window, so this will fail badly! + auto translation = + mm.getTranslation(masterPciEAddrSpaceId, mem.getAddrSpaceId()); + if (translation.getSize() >= mem.getSize()) + // There is already a sufficient path + logger->debug("Already mapped through another mapping"); + return true; + else logger->warn("There's already a mapping, but too small"); + } catch (const std::out_of_range &) { + // Not yet reachable, that's okay, proceed + } + // In order to register IO memory with CUDA, it has to be mapped to the VA + // space of the current process (requirement of CUDA API). Check this now. + MemoryManager::AddressSpaceId mappedBaseAddrSpaceId; + try { + auto path = mm.findPath(mm.getProcessAddressSpace(), mem.getAddrSpaceId()); + // First node in path is the mapped memory space whose virtual address + // we need to hand to CUDA + mappedBaseAddrSpaceId = path.front(); + } catch (const std::out_of_range &) { + logger->error("Memory not reachable from process, but required by CUDA"); + return false; + } - // In order to register IO memory with CUDA, it has to be mapped to the VA - // space of the current process (requirement of CUDA API). Check this now. - MemoryManager::AddressSpaceId mappedBaseAddrSpaceId; - try { - auto path = mm.findPath(mm.getProcessAddressSpace(), mem.getAddrSpaceId()); - // First node in path is the mapped memory space whose virtual address - // we need to hand to CUDA - mappedBaseAddrSpaceId = path.front(); - } catch (const std::out_of_range&) { - logger->error("Memory not reachable from process, but required by CUDA"); - return false; - } + // Determine the base address of the mapped memory region needed by CUDA + const auto translationProcess = + mm.getTranslationFromProcess(mappedBaseAddrSpaceId); + const uintptr_t baseAddrForProcess = translationProcess.getLocalAddr(0); - // Determine the base address of the mapped memory region needed by CUDA - const auto translationProcess = mm.getTranslationFromProcess(mappedBaseAddrSpaceId); - const uintptr_t baseAddrForProcess = translationProcess.getLocalAddr(0); + // Now check that the memory is also reachable via PCIe bus, otherwise GPU + // has no means to access it. + uintptr_t baseAddrOnPci; + size_t sizeOnPci; + try { + auto translationPci = + mm.getTranslation(pciAddrSpaceId, mappedBaseAddrSpaceId); + baseAddrOnPci = translationPci.getLocalAddr(0); + sizeOnPci = translationPci.getSize(); + } catch (const std::out_of_range &) { + logger->error("Memory is not reachable via PCIe bus"); + return false; + } + if (sizeOnPci < mem.getSize()) { + logger->warn( + "VA mapping of IO memory is too small: {:#x} instead of {:#x} bytes", + sizeOnPci, mem.getSize()); + logger->warn("If something later on fails or behaves strangely, this might " + "be the cause!"); + } - // Now check that the memory is also reachable via PCIe bus, otherwise GPU - // has no means to access it. - uintptr_t baseAddrOnPci; - size_t sizeOnPci; - try { - auto translationPci = mm.getTranslation(pciAddrSpaceId, - mappedBaseAddrSpaceId); - baseAddrOnPci = translationPci.getLocalAddr(0); - sizeOnPci = translationPci.getSize(); - } catch (const std::out_of_range&) { - logger->error("Memory is not reachable via PCIe bus"); - return false; - } + cudaSetDevice(gpuId); - if (sizeOnPci < mem.getSize()) { - logger->warn("VA mapping of IO memory is too small: {:#x} instead of {:#x} bytes", - sizeOnPci, mem.getSize()); - logger->warn("If something later on fails or behaves strangely, this might be the cause!"); - } + auto baseAddrVA = reinterpret_cast(baseAddrForProcess); + if (cudaHostRegister(baseAddrVA, sizeOnPci, cudaHostRegisterIoMemory) != + cudaSuccess) { + logger->error("Cannot register IO memory for block {}", + mem.getAddrSpaceId()); + return false; + } + void *devicePointer = nullptr; + if (cudaHostGetDevicePointer(&devicePointer, baseAddrVA, 0) != cudaSuccess) { + logger->error("Cannot retrieve device pointer for IO memory"); + return false; + } - cudaSetDevice(gpuId); + mm.createMapping(reinterpret_cast(devicePointer), baseAddrOnPci, + sizeOnPci, "CudaIoMem", masterPciEAddrSpaceId, + pciAddrSpaceId); - auto baseAddrVA = reinterpret_cast(baseAddrForProcess); - if (cudaHostRegister(baseAddrVA, sizeOnPci, cudaHostRegisterIoMemory) != cudaSuccess) { - logger->error("Cannot register IO memory for block {}", mem.getAddrSpaceId()); - return false; - } - - void* devicePointer = nullptr; - if (cudaHostGetDevicePointer(&devicePointer, baseAddrVA, 0) != cudaSuccess) { - logger->error("Cannot retrieve device pointer for IO memory"); - return false; - } - - mm.createMapping(reinterpret_cast(devicePointer), baseAddrOnPci, - sizeOnPci, "CudaIoMem", masterPciEAddrSpaceId, pciAddrSpaceId); - - return true; + return true; } -bool -Gpu::registerHostMemory(const MemoryBlock &mem) -{ - auto &mm = MemoryManager::get(); +bool Gpu::registerHostMemory(const MemoryBlock &mem) { + auto &mm = MemoryManager::get(); - auto translation = mm.getTranslationFromProcess(mem.getAddrSpaceId()); - auto localBase = reinterpret_cast(translation.getLocalAddr(0)); + auto translation = mm.getTranslationFromProcess(mem.getAddrSpaceId()); + auto localBase = reinterpret_cast(translation.getLocalAddr(0)); - int ret = cudaHostRegister(localBase, mem.getSize(), 0); - if (ret != cudaSuccess) { - logger->error("Cannot register memory block {} addr={:p} size={:#x} to CUDA: ret={}", - mem.getAddrSpaceId(), localBase, mem.getSize(), ret); - return false; - } + int ret = cudaHostRegister(localBase, mem.getSize(), 0); + if (ret != cudaSuccess) { + logger->error( + "Cannot register memory block {} addr={:p} size={:#x} to CUDA: ret={}", + mem.getAddrSpaceId(), localBase, mem.getSize(), ret); + return false; + } - void* devicePointer = nullptr; - ret = cudaHostGetDevicePointer(&devicePointer, localBase, 0); - if (ret != cudaSuccess) { - logger->error("Cannot retrieve device pointer for IO memory: ret={}", ret); - return false; - } + void *devicePointer = nullptr; + ret = cudaHostGetDevicePointer(&devicePointer, localBase, 0); + if (ret != cudaSuccess) { + logger->error("Cannot retrieve device pointer for IO memory: ret={}", ret); + return false; + } - mm.createMapping(reinterpret_cast(devicePointer), 0, mem.getSize(), - "CudaHostMem", masterPciEAddrSpaceId, mem.getAddrSpaceId()); + mm.createMapping(reinterpret_cast(devicePointer), 0, mem.getSize(), + "CudaHostMem", masterPciEAddrSpaceId, mem.getAddrSpaceId()); - return true; + return true; } -bool Gpu::makeAccessibleToPCIeAndVA(const MemoryBlock &mem) -{ - if (pImpl->gdr == nullptr) { - logger->warn("GDRcopy not available"); - return false; - } +bool Gpu::makeAccessibleToPCIeAndVA(const MemoryBlock &mem) { + if (pImpl->gdr == nullptr) { + logger->warn("GDRcopy not available"); + return false; + } - auto &mm = MemoryManager::get(); + auto &mm = MemoryManager::get(); - try { - auto path = mm.findPath(masterPciEAddrSpaceId, mem.getAddrSpaceId()); - // If first hop is the PCIe bus, we know that memory is off-GPU - if (path.front() == mm.getPciAddressSpace()) - throw std::out_of_range("Memory block is outside of this GPU"); + try { + auto path = mm.findPath(masterPciEAddrSpaceId, mem.getAddrSpaceId()); + // If first hop is the PCIe bus, we know that memory is off-GPU + if (path.front() == mm.getPciAddressSpace()) + throw std::out_of_range("Memory block is outside of this GPU"); - } catch (const std::out_of_range&) { - logger->error("Trying to map non-GPU memory block"); - return false; - } + } catch (const std::out_of_range &) { + logger->error("Trying to map non-GPU memory block"); + return false; + } - logger->debug("retrieve complete device pointer from point of view of GPU"); + logger->debug("retrieve complete device pointer from point of view of GPU"); - // Retrieve complete device pointer from point of view of GPU - auto translation = mm.getTranslation(masterPciEAddrSpaceId, - mem.getAddrSpaceId()); - CUdeviceptr devptr = translation.getLocalAddr(0); + // Retrieve complete device pointer from point of view of GPU + auto translation = + mm.getTranslation(masterPciEAddrSpaceId, mem.getAddrSpaceId()); + CUdeviceptr devptr = translation.getLocalAddr(0); - int ret; + int ret; - // Required to set this flag before mapping - unsigned int enable = 1; - ret = cuPointerSetAttribute(&enable, CU_POINTER_ATTRIBUTE_SYNC_MEMOPS, devptr); - if (ret != CUDA_SUCCESS) { - logger->error("Cannot set pointer attributes on memory block {}: {}", - mem.getAddrSpaceId(), ret); - return false; - } + // Required to set this flag before mapping + unsigned int enable = 1; + ret = + cuPointerSetAttribute(&enable, CU_POINTER_ATTRIBUTE_SYNC_MEMOPS, devptr); + if (ret != CUDA_SUCCESS) { + logger->error("Cannot set pointer attributes on memory block {}: {}", + mem.getAddrSpaceId(), ret); + return false; + } - gdr_mh_t mh; - ret = gdr_pin_buffer(pImpl->gdr, devptr, mem.getSize(), 0, 0, &mh); - if (ret != 0) { - logger->error("Cannot pin memory block {} via gdrcopy: {}", - mem.getAddrSpaceId(), ret); - return false; - } + gdr_mh_t mh; + ret = gdr_pin_buffer(pImpl->gdr, devptr, mem.getSize(), 0, 0, &mh); + if (ret != 0) { + logger->error("Cannot pin memory block {} via gdrcopy: {}", + mem.getAddrSpaceId(), ret); + return false; + } - void* bar = nullptr; - ret = gdr_map(pImpl->gdr, mh, &bar, mem.getSize()); - if (ret != 0) { - logger->error("Cannot map memory block {} via gdrcopy: {}", - mem.getAddrSpaceId(), ret); - return false; - } + void *bar = nullptr; + ret = gdr_map(pImpl->gdr, mh, &bar, mem.getSize()); + if (ret != 0) { + logger->error("Cannot map memory block {} via gdrcopy: {}", + mem.getAddrSpaceId(), ret); + return false; + } - gdr_info_t info; - ret = gdr_get_info(pImpl->gdr, mh, &info); - if (ret != 0) { - logger->error("Cannot get info for mapping of memory block {}: {}", - mem.getAddrSpaceId(), ret); - return false; - } + gdr_info_t info; + ret = gdr_get_info(pImpl->gdr, mh, &info); + if (ret != 0) { + logger->error("Cannot get info for mapping of memory block {}: {}", + mem.getAddrSpaceId(), ret); + return false; + } - const uintptr_t offset = info.va - devptr; - const uintptr_t userPtr = reinterpret_cast(bar) + offset; + const uintptr_t offset = info.va - devptr; + const uintptr_t userPtr = reinterpret_cast(bar) + offset; - logger->debug("BAR ptr: {:p}", bar); - logger->debug("info.va: {:#x}", info.va); - logger->debug("info.mapped_size: {:#x}", info.mapped_size); - logger->debug("info.page_size: {:#x}", info.page_size); - logger->debug("offset: {:#x}", offset); - logger->debug("user pointer: {:#x}", userPtr); + logger->debug("BAR ptr: {:p}", bar); + logger->debug("info.va: {:#x}", info.va); + logger->debug("info.mapped_size: {:#x}", info.mapped_size); + logger->debug("info.page_size: {:#x}", info.page_size); + logger->debug("offset: {:#x}", offset); + logger->debug("user pointer: {:#x}", userPtr); - // Mapping to acceses memory block from process - mm.createMapping(userPtr, 0, info.mapped_size, "GDRcopy", - mm.getProcessAddressSpace(), mem.getAddrSpaceId()); + // Mapping to acceses memory block from process + mm.createMapping(userPtr, 0, info.mapped_size, "GDRcopy", + mm.getProcessAddressSpace(), mem.getAddrSpaceId()); - // Retrieve bus address - uint64_t addr[8]; - ret = gdr_map_dma(pImpl->gdr, mh, 3, 0, 0, addr, 8); + // Retrieve bus address + uint64_t addr[8]; + ret = gdr_map_dma(pImpl->gdr, mh, 3, 0, 0, addr, 8); - for (int i = 0; i < ret; i++) - logger->debug("DMA addr[{}]: {:#x}", i, addr[i]); + for (int i = 0; i < ret; i++) + logger->debug("DMA addr[{}]: {:#x}", i, addr[i]); - if (ret != 1) { - logger->error("Only one DMA address per block supported at the moment"); - return false; - } + if (ret != 1) { + logger->error("Only one DMA address per block supported at the moment"); + return false; + } - // Mapping to access memory block from peer devices via PCIe - mm.createMapping(addr[0], 0, mem.getSize(), "GDRcopyDMA", - mm.getPciAddressSpace(), mem.getAddrSpaceId()); + // Mapping to access memory block from peer devices via PCIe + mm.createMapping(addr[0], 0, mem.getSize(), "GDRcopyDMA", + mm.getPciAddressSpace(), mem.getAddrSpaceId()); - return true; + return true; } -bool -Gpu::makeAccessibleFromPCIeOrHostRam(const MemoryBlock &mem) -{ - // Check which kind of memory this is and where it resides - // There are two possibilities: - // - Host memory not managed by CUDA - // - IO memory somewhere on the PCIe bus +bool Gpu::makeAccessibleFromPCIeOrHostRam(const MemoryBlock &mem) { + // Check which kind of memory this is and where it resides + // There are two possibilities: + // - Host memory not managed by CUDA + // - IO memory somewhere on the PCIe bus - auto &mm = MemoryManager::get(); + auto &mm = MemoryManager::get(); - bool isIoMemory = false; - try { - auto path = mm.findPath(mm.getPciAddressSpace(), mem.getAddrSpaceId()); - isIoMemory = true; - } catch (const std::out_of_range&) { - // Not reachable via PCI -> not IO memory - } + bool isIoMemory = false; + try { + auto path = mm.findPath(mm.getPciAddressSpace(), mem.getAddrSpaceId()); + isIoMemory = true; + } catch (const std::out_of_range &) { + // Not reachable via PCI -> not IO memory + } - if (isIoMemory) { - logger->debug("Memory block {} is assumed to be IO memory", - mem.getAddrSpaceId()); + if (isIoMemory) { + logger->debug("Memory block {} is assumed to be IO memory", + mem.getAddrSpaceId()); - return registerIoMemory(mem); - } - else { - logger->debug("Memory block {} is assumed to be non-CUDA host memory", - mem.getAddrSpaceId()); + return registerIoMemory(mem); + } else { + logger->debug("Memory block {} is assumed to be non-CUDA host memory", + mem.getAddrSpaceId()); - return registerHostMemory(mem); - } + return registerHostMemory(mem); + } } -void Gpu::memcpySync(const MemoryBlock &src, const MemoryBlock &dst, size_t size) -{ - auto &mm = MemoryManager::get(); +void Gpu::memcpySync(const MemoryBlock &src, const MemoryBlock &dst, + size_t size) { + auto &mm = MemoryManager::get(); - auto src_translation = mm.getTranslation(masterPciEAddrSpaceId, - src.getAddrSpaceId()); - const void* src_buf = reinterpret_cast(src_translation.getLocalAddr(0)); + auto src_translation = + mm.getTranslation(masterPciEAddrSpaceId, src.getAddrSpaceId()); + const void *src_buf = + reinterpret_cast(src_translation.getLocalAddr(0)); - auto dst_translation = mm.getTranslation(masterPciEAddrSpaceId, - dst.getAddrSpaceId()); - void* dst_buf = reinterpret_cast(dst_translation.getLocalAddr(0)); + auto dst_translation = + mm.getTranslation(masterPciEAddrSpaceId, dst.getAddrSpaceId()); + void *dst_buf = reinterpret_cast(dst_translation.getLocalAddr(0)); - cudaSetDevice(gpuId); - cudaMemcpy(dst_buf, src_buf, size, cudaMemcpyDefault); + cudaSetDevice(gpuId); + cudaMemcpy(dst_buf, src_buf, size, cudaMemcpyDefault); } -void Gpu::memcpyKernel(const MemoryBlock &src, const MemoryBlock &dst, size_t size) -{ - auto &mm = MemoryManager::get(); +void Gpu::memcpyKernel(const MemoryBlock &src, const MemoryBlock &dst, + size_t size) { + auto &mm = MemoryManager::get(); - auto src_translation = mm.getTranslation(masterPciEAddrSpaceId, - src.getAddrSpaceId()); - auto src_buf = reinterpret_cast(src_translation.getLocalAddr(0)); + auto src_translation = + mm.getTranslation(masterPciEAddrSpaceId, src.getAddrSpaceId()); + auto src_buf = reinterpret_cast(src_translation.getLocalAddr(0)); - auto dst_translation = mm.getTranslation(masterPciEAddrSpaceId, - dst.getAddrSpaceId()); - auto dst_buf = reinterpret_cast(dst_translation.getLocalAddr(0)); + auto dst_translation = + mm.getTranslation(masterPciEAddrSpaceId, dst.getAddrSpaceId()); + auto dst_buf = reinterpret_cast(dst_translation.getLocalAddr(0)); - cudaSetDevice(gpuId); - kernel_memcpy<<<1, 1>>>(dst_buf, src_buf, size); - cudaDeviceSynchronize(); + cudaSetDevice(gpuId); + kernel_memcpy<<<1, 1>>>(dst_buf, src_buf, size); + cudaDeviceSynchronize(); } -MemoryTranslation -Gpu::translate(const MemoryBlock &dst) -{ - auto &mm = MemoryManager::get(); - return mm.getTranslation(masterPciEAddrSpaceId, dst.getAddrSpaceId()); +MemoryTranslation Gpu::translate(const MemoryBlock &dst) { + auto &mm = MemoryManager::get(); + return mm.getTranslation(masterPciEAddrSpaceId, dst.getAddrSpaceId()); } - std::unique_ptr -GpuAllocator::allocateBlock(size_t size) -{ - cudaSetDevice(gpu.gpuId); +GpuAllocator::allocateBlock(size_t size) { + cudaSetDevice(gpu.gpuId); - void* addr; - auto &mm = MemoryManager::get(); + void *addr; + auto &mm = MemoryManager::get(); - // Search for an existing chunk that has enough free memory - auto chunk = std::find_if(chunks.begin(), chunks.end(), [&](const auto &chunk) { - return chunk->getAvailableMemory() >= size; - }); + // Search for an existing chunk that has enough free memory + auto chunk = + std::find_if(chunks.begin(), chunks.end(), [&](const auto &chunk) { + return chunk->getAvailableMemory() >= size; + }); + if (chunk != chunks.end()) { + logger->debug("Found existing chunk that can host the requested block"); - if (chunk != chunks.end()) { - logger->debug("Found existing chunk that can host the requested block"); + return (*chunk)->allocateBlock(size); + } else { + // Allocate a new chunk - return (*chunk)->allocateBlock(size); - } - else { - // Allocate a new chunk + // Rounded-up multiple of GPU page size + const size_t chunkSize = size - (size & (GpuPageSize - 1)) + GpuPageSize; + logger->debug("Allocate new chunk of {:#x} bytes", chunkSize); - // Rounded-up multiple of GPU page size - const size_t chunkSize = size - (size & (GpuPageSize - 1)) + GpuPageSize; - logger->debug("Allocate new chunk of {:#x} bytes", chunkSize); + if (cudaSuccess != cudaMalloc(&addr, chunkSize)) { + logger->error("cudaMalloc(..., size={}) failed", chunkSize); + throw std::bad_alloc(); + } - if (cudaSuccess != cudaMalloc(&addr, chunkSize)) { - logger->error("cudaMalloc(..., size={}) failed", chunkSize); - throw std::bad_alloc(); - } + // Assemble name for this block + std::stringstream name; + name << std::showbase << std::hex << reinterpret_cast(addr); - // Assemble name for this block - std::stringstream name; - name << std::showbase << std::hex << reinterpret_cast(addr); + auto blockName = mm.getSlaveAddrSpaceName(getName(), name.str()); + auto blockAddrSpaceId = mm.getOrCreateAddressSpace(blockName); - auto blockName = mm.getSlaveAddrSpaceName(getName(), name.str()); - auto blockAddrSpaceId = mm.getOrCreateAddressSpace(blockName); + const auto localAddr = reinterpret_cast(addr); + std::unique_ptr mem( + new MemoryBlock(localAddr, chunkSize, blockAddrSpaceId), this->free); - const auto localAddr = reinterpret_cast(addr); - std::unique_ptr - mem(new MemoryBlock(localAddr, chunkSize, blockAddrSpaceId), this->free); + insertMemoryBlock(*mem); - insertMemoryBlock(*mem); + // Already make accessible to CPU + gpu.makeAccessibleToPCIeAndVA(*mem); - // Already make accessible to CPU - gpu.makeAccessibleToPCIeAndVA(*mem); + // Create a new allocator to manage the chunk and push to chunk list + chunks.push_front(std::make_unique(std::move(mem))); - // Create a new allocator to manage the chunk and push to chunk list - chunks.push_front(std::make_unique(std::move(mem))); - - // Call again, this time there's a large enough chunk - return allocateBlock(size); - } + // Call again, this time there's a large enough chunk + return allocateBlock(size); + } } +Gpu::Gpu(int gpuId) : pImpl{std::make_unique()}, gpuId(gpuId) { + logger = villas::logging.get(getName()); -Gpu::Gpu(int gpuId) : - pImpl{std::make_unique()}, - gpuId(gpuId) -{ - logger = villas::logging.get(getName()); - - pImpl->gdr = gdr_open(); - if (pImpl->gdr == nullptr) { - logger->warn("No GDRcopy support enabled, cannot open /dev/gdrdrv"); - } + pImpl->gdr = gdr_open(); + if (pImpl->gdr == nullptr) { + logger->warn("No GDRcopy support enabled, cannot open /dev/gdrdrv"); + } } -bool Gpu::init() -{ - auto &mm = MemoryManager::get(); +bool Gpu::init() { + auto &mm = MemoryManager::get(); - const auto gpuPciEAddrSpaceName = mm.getMasterAddrSpaceName(getName(), "pcie"); - masterPciEAddrSpaceId = mm.getOrCreateAddressSpace(gpuPciEAddrSpaceName); + const auto gpuPciEAddrSpaceName = + mm.getMasterAddrSpaceName(getName(), "pcie"); + masterPciEAddrSpaceId = mm.getOrCreateAddressSpace(gpuPciEAddrSpaceName); - allocator = std::make_unique(*this); + allocator = std::make_unique(*this); - cudaDeviceProp deviceProp; - cudaGetDeviceProperties(&deviceProp, gpuId); + cudaDeviceProp deviceProp; + cudaGetDeviceProperties(&deviceProp, gpuId); - pImpl->pdev.slot = { - deviceProp.pciDomainID, - deviceProp.pciBusID, - deviceProp.pciDeviceID, - 0}; + pImpl->pdev.slot = {deviceProp.pciDomainID, deviceProp.pciBusID, + deviceProp.pciDeviceID, 0}; - struct pci_region* pci_regions = nullptr; - const size_t pci_num_regions = pci_get_regions(&pImpl->pdev, &pci_regions); - for (size_t i = 0; i < pci_num_regions; i++) { - const size_t region_size = pci_regions[i].end - pci_regions[i].start + 1; - logger->info("BAR{}: bus addr={:#x} size={:#x}", - pci_regions[i].num, pci_regions[i].start, region_size); + struct pci_region *pci_regions = nullptr; + const size_t pci_num_regions = pci_get_regions(&pImpl->pdev, &pci_regions); + for (size_t i = 0; i < pci_num_regions; i++) { + const size_t region_size = pci_regions[i].end - pci_regions[i].start + 1; + logger->info("BAR{}: bus addr={:#x} size={:#x}", pci_regions[i].num, + pci_regions[i].start, region_size); - char name[] = "BARx"; - name[3] = '0' + pci_regions[i].num; + char name[] = "BARx"; + name[3] = '0' + pci_regions[i].num; - auto gpuBarXAddrSpaceName = mm.getSlaveAddrSpaceName(getName(), name); - auto gpuBarXAddrSpaceId = mm.getOrCreateAddressSpace(gpuBarXAddrSpaceName); + auto gpuBarXAddrSpaceName = mm.getSlaveAddrSpaceName(getName(), name); + auto gpuBarXAddrSpaceId = mm.getOrCreateAddressSpace(gpuBarXAddrSpaceName); - mm.createMapping(pci_regions[i].start, 0, region_size, - std::string("PCI-") + name, - mm.getPciAddressSpace(), gpuBarXAddrSpaceId); - } + mm.createMapping(pci_regions[i].start, 0, region_size, + std::string("PCI-") + name, mm.getPciAddressSpace(), + gpuBarXAddrSpaceId); + } - free(pci_regions); + free(pci_regions); - return true; + return true; } +std::list> GpuFactory::make() { + int deviceCount = 0; + cudaGetDeviceCount(&deviceCount); -std::list> -GpuFactory::make() -{ - int deviceCount = 0; - cudaGetDeviceCount(&deviceCount); + std::list> gpuList; - std::list> gpuList; + for (int gpuId = 0; gpuId < deviceCount; gpuId++) { + if (cudaSetDevice(gpuId) != cudaSuccess) { + logger->warn("Cannot activate GPU {}", gpuId); + continue; + } - for (int gpuId = 0; gpuId < deviceCount; gpuId++) { - if (cudaSetDevice(gpuId) != cudaSuccess) { - logger->warn("Cannot activate GPU {}", gpuId); - continue; - } + auto gpu = std::make_unique(gpuId); - auto gpu = std::make_unique(gpuId); + if (not gpu->init()) { + logger->warn("Cannot initialize GPU {}", gpuId); + continue; + } - if (not gpu->init()) { - logger->warn("Cannot initialize GPU {}", gpuId); - continue; - } + gpuList.emplace_back(std::move(gpu)); + } - gpuList.emplace_back(std::move(gpu)); - } + logger->info("Initialized {} GPUs", gpuList.size()); + for (auto &gpu : gpuList) { + logger->debug(" - {}", gpu->getName()); + } - logger->info("Initialized {} GPUs", gpuList.size()); - for (auto &gpu : gpuList) { - logger->debug(" - {}", gpu->getName()); - } - - return gpuList; + return gpuList; } diff --git a/fpga/include/villas/fpga/card.hpp b/fpga/include/villas/fpga/card.hpp index f58a4c681..58c7152d0 100644 --- a/fpga/include/villas/fpga/card.hpp +++ b/fpga/include/villas/fpga/card.hpp @@ -18,40 +18,40 @@ namespace villas { namespace fpga { -class Card -{ +class Card { public: - bool polling; + bool polling; - std::string name; // The name of the FPGA card - std::shared_ptr vfioContainer; - std::shared_ptr vfioDevice; + std::string name; // The name of the FPGA card + std::shared_ptr vfioContainer; + std::shared_ptr vfioDevice; - // Slave address space ID to access the PCIe address space from the - // FPGA - MemoryManager::AddressSpaceId addrSpaceIdDeviceToHost; + // Slave address space ID to access the PCIe address space from the + // FPGA + MemoryManager::AddressSpaceId addrSpaceIdDeviceToHost; - // Address space identifier of the master address space of this FPGA - // card. This will be used for address resolution of all IPs on this - // card. - MemoryManager::AddressSpaceId addrSpaceIdHostToDevice; + // Address space identifier of the master address space of this FPGA + // card. This will be used for address resolution of all IPs on this + // card. + MemoryManager::AddressSpaceId addrSpaceIdHostToDevice; - std::list> ips; + std::list> ips; - virtual ~Card(); + virtual ~Card(); - virtual bool mapMemoryBlock(const std::shared_ptr block); - virtual bool unmapMemoryBlock(const MemoryBlock &block); + virtual bool mapMemoryBlock(const std::shared_ptr block); + virtual bool unmapMemoryBlock(const MemoryBlock &block); - std::shared_ptr lookupIp(const std::string &name) const; - std::shared_ptr lookupIp(const Vlnv &vlnv) const; - std::shared_ptr lookupIp(const ip::IpIdentifier &id) const; + std::shared_ptr lookupIp(const std::string &name) const; + std::shared_ptr lookupIp(const Vlnv &vlnv) const; + std::shared_ptr lookupIp(const ip::IpIdentifier &id) const; protected: - // Keep a map of already mapped memory blocks - std::map> memoryBlocksMapped; + // Keep a map of already mapped memory blocks + std::map> + memoryBlocksMapped; - Logger logger; + Logger logger; }; } // namespace fpga diff --git a/fpga/include/villas/fpga/config.h b/fpga/include/villas/fpga/config.h index 5ee811e85..ae581d6f1 100644 --- a/fpga/include/villas/fpga/config.h +++ b/fpga/include/villas/fpga/config.h @@ -11,10 +11,10 @@ #pragma once // PCIe BAR number of VILLASfpga registers -#define FPGA_PCI_BAR 0 -#define FPGA_PCI_VID_XILINX 0x10ee -#define FPGA_PCI_PID_VFPGA 0x7022 +#define FPGA_PCI_BAR 0 +#define FPGA_PCI_VID_XILINX 0x10ee +#define FPGA_PCI_PID_VFPGA 0x7022 /* AXI Bus frequency for all components * except RTDS AXI Stream bridge which runs at RTDS_HZ (100 Mhz) */ -#define FPGA_AXI_HZ 125000000 // 125 MHz +#define FPGA_AXI_HZ 125000000 // 125 MHz diff --git a/fpga/include/villas/fpga/core.hpp b/fpga/include/villas/fpga/core.hpp index 6376baf64..acdb1428c 100644 --- a/fpga/include/villas/fpga/core.hpp +++ b/fpga/include/villas/fpga/core.hpp @@ -10,17 +10,17 @@ #pragma once -#include -#include -#include -#include #include -#include +#include +#include +#include +#include #include #include +#include +#include #include #include -#include namespace villas { namespace fpga { @@ -37,309 +37,220 @@ class InterruptController; class IpIdentifier { public: + IpIdentifier(const Vlnv &vlnv = Vlnv::getWildcard(), + const std::string &name = "") + : vlnv(vlnv), name(name) {} - IpIdentifier(const Vlnv &vlnv = Vlnv::getWildcard(), const std::string &name = "") : - vlnv(vlnv), - name(name) - { } + IpIdentifier(const std::string &vlnvString, const std::string &name = "") + : vlnv(vlnvString), name(name) {} - IpIdentifier(const std::string &vlnvString, const std::string &name = "") : - vlnv(vlnvString), - name(name) - { } + const std::string &getName() const { return name; } - const std::string& - getName() const - { - return name; - } + const Vlnv &getVlnv() const { return vlnv; } - const Vlnv& - getVlnv() const - { - return vlnv; - } + friend std::ostream &operator<<(std::ostream &stream, + const IpIdentifier &id) { + return stream << id.name << " vlnv=" << id.vlnv; + } - friend std::ostream& - operator<< (std::ostream &stream, const IpIdentifier &id) - { - return stream << id.name << " vlnv=" << id.vlnv; - } + bool operator==(const IpIdentifier &otherId) const { + const bool vlnvWildcard = otherId.getVlnv() == Vlnv::getWildcard(); + const bool nameWildcard = + this->getName().empty() or otherId.getName().empty(); - bool - operator==(const IpIdentifier &otherId) const { - const bool vlnvWildcard = otherId.getVlnv() == Vlnv::getWildcard(); - const bool nameWildcard = this->getName().empty() or otherId.getName().empty(); + const bool vlnvMatch = vlnvWildcard or this->getVlnv() == otherId.getVlnv(); + const bool nameMatch = nameWildcard or this->getName() == otherId.getName(); - const bool vlnvMatch = vlnvWildcard or this->getVlnv() == otherId.getVlnv(); - const bool nameMatch = nameWildcard or this->getName() == otherId.getName(); + return vlnvMatch and nameMatch; + } - return vlnvMatch and nameMatch; - } - - bool - operator!=(const IpIdentifier &otherId) const - { - return !(*this == otherId); - } + bool operator!=(const IpIdentifier &otherId) const { + return !(*this == otherId); + } private: - Vlnv vlnv; - std::string name; + Vlnv vlnv; + std::string name; }; class Core { - friend CoreFactory; + friend CoreFactory; public: - Core() : - card(nullptr) - { } + Core() : card(nullptr) {} - virtual - ~Core() = default; + virtual ~Core() = default; public: - // Generic management interface for IPs + // Generic management interface for IPs - // Runtime setup of IP, should access and initialize hardware - virtual - bool init() - { - return true; - } + // Runtime setup of IP, should access and initialize hardware + virtual bool init() { return true; } - // Runtime check of IP, should verify basic functionality - virtual - bool check() - { - return true; - } + // Runtime check of IP, should verify basic functionality + virtual bool check() { return true; } - // Generic disabling of IP, meaning may depend on IP - virtual - bool stop() - { - return true; - } + // Generic disabling of IP, meaning may depend on IP + virtual bool stop() { return true; } - // Reset the IP, it should behave like freshly initialized afterwards - virtual - bool reset() - { - return true; - } + // Reset the IP, it should behave like freshly initialized afterwards + virtual bool reset() { return true; } - // Print some debug information about the IP - virtual - void dump(); + // Print some debug information about the IP + virtual void dump(); protected: - // Key-type for accessing maps addressTranslations and slaveAddressSpaces - using MemoryBlockName = std::string; + // Key-type for accessing maps addressTranslations and slaveAddressSpaces + using MemoryBlockName = std::string; - // Each IP can declare via this function which memory blocks it requires - virtual - std::list getMemoryBlocks() const - { - return {}; - } + // Each IP can declare via this function which memory blocks it requires + virtual std::list getMemoryBlocks() const { return {}; } public: - const std::string& getInstanceName() const - { - return id.getName(); - } + const std::string &getInstanceName() const { return id.getName(); } - // Operators + // Operators - bool operator==(const Vlnv &otherVlnv) const - { - return id.getVlnv() == otherVlnv; - } + bool operator==(const Vlnv &otherVlnv) const { + return id.getVlnv() == otherVlnv; + } - bool operator!=(const Vlnv &otherVlnv) const - { - return id.getVlnv() != otherVlnv; - } + bool operator!=(const Vlnv &otherVlnv) const { + return id.getVlnv() != otherVlnv; + } - bool operator==(const IpIdentifier &otherId) const - { - return this->id == otherId; - } + bool operator==(const IpIdentifier &otherId) const { + return this->id == otherId; + } - bool operator!=(const IpIdentifier &otherId) const - { - return this->id != otherId; - } + bool operator!=(const IpIdentifier &otherId) const { + return this->id != otherId; + } - bool operator==(const std::string &otherName) const - { - return getInstanceName() == otherName; - } + bool operator==(const std::string &otherName) const { + return getInstanceName() == otherName; + } - bool operator!=(const std::string &otherName) const - { - return getInstanceName() != otherName; - } + bool operator!=(const std::string &otherName) const { + return getInstanceName() != otherName; + } - bool operator==(const Core &otherIp) const - { - return this->id == otherIp.id; - } + bool operator==(const Core &otherIp) const { return this->id == otherIp.id; } - bool operator!=(const Core &otherIp) const - { - return this->id != otherIp.id; - } + bool operator!=(const Core &otherIp) const { return this->id != otherIp.id; } - friend - std::ostream& operator<< (std::ostream &stream, const Core &ip) - { - return stream << ip.id; - } + friend std::ostream &operator<<(std::ostream &stream, const Core &ip) { + return stream << ip.id; + } protected: - uintptr_t getBaseAddr(const MemoryBlockName &block) const - { - return getLocalAddr(block, 0); - } + uintptr_t getBaseAddr(const MemoryBlockName &block) const { + return getLocalAddr(block, 0); + } - uintptr_t getLocalAddr(const MemoryBlockName &block, uintptr_t address) const; + uintptr_t getLocalAddr(const MemoryBlockName &block, uintptr_t address) const; - MemoryManager::AddressSpaceId getAddressSpaceId(const MemoryBlockName &block) const - { - return slaveAddressSpaces.at(block); - } + MemoryManager::AddressSpaceId + getAddressSpaceId(const MemoryBlockName &block) const { + return slaveAddressSpaces.at(block); + } - InterruptController* getInterruptController(const std::string &interruptName) const; + InterruptController * + getInterruptController(const std::string &interruptName) const; - MemoryManager::AddressSpaceId getMasterAddrSpaceByInterface(const std::string &masterInterfaceName) const - { - return busMasterInterfaces.at(masterInterfaceName); - } + MemoryManager::AddressSpaceId + getMasterAddrSpaceByInterface(const std::string &masterInterfaceName) const { + return busMasterInterfaces.at(masterInterfaceName); + } - template - T readMemory(const std::string &block, uintptr_t address) const - { - return *(reinterpret_cast(getLocalAddr(block, address))); - } + template + T readMemory(const std::string &block, uintptr_t address) const { + return *(reinterpret_cast(getLocalAddr(block, address))); + } - template - void writeMemory(const std::string &block, uintptr_t address, T value) - { - T* ptr = reinterpret_cast(getLocalAddr(block, address)); *ptr = value; - } + template + void writeMemory(const std::string &block, uintptr_t address, T value) { + T *ptr = reinterpret_cast(getLocalAddr(block, address)); + *ptr = value; + } protected: - struct IrqPort { - int num; - InterruptController* irqController; - std::string description; - }; + struct IrqPort { + int num; + InterruptController *irqController; + std::string description; + }; - // Specialized logger instance with the IPs name set as category - Logger logger; + // Specialized logger instance with the IPs name set as category + Logger logger; - // FPGA card this IP is instantiated on (populated by FpgaIpFactory) - Card* card; + // FPGA card this IP is instantiated on (populated by FpgaIpFactory) + Card *card; - // Identifier of this IP with its instance name and VLNV - IpIdentifier id; + // Identifier of this IP with its instance name and VLNV + IpIdentifier id; - // All interrupts of this IP with their associated interrupt controller - std::map irqs; + // All interrupts of this IP with their associated interrupt controller + std::map irqs; - // Cached translations from the process address space to each memory block - std::map addressTranslations; + // Cached translations from the process address space to each memory block + std::map addressTranslations; - // Lookup for IP's slave address spaces (= memory blocks) - std::map slaveAddressSpaces; + // Lookup for IP's slave address spaces (= memory blocks) + std::map slaveAddressSpaces; - // AXI bus master interfaces to access memory somewhere - std::map busMasterInterfaces; + // AXI bus master interfaces to access memory somewhere + std::map busMasterInterfaces; }; class CoreFactory : public plugin::Plugin { public: - using plugin::Plugin::Plugin; + using plugin::Plugin::Plugin; - // Returns a running and checked FPGA IP - static - std::list> make(Card* card, json_t *json_ips); + // Returns a running and checked FPGA IP + static std::list> make(Card *card, json_t *json_ips); - virtual - std::string getType() const - { - return "core"; - } + virtual std::string getType() const { return "core"; } protected: - enum PollingMode { - POLL, - IRQ, - }; + enum PollingMode { + POLL, + IRQ, + }; - Logger getLogger() - { - return villas::logging.get(getName()); - } + Logger getLogger() { return villas::logging.get(getName()); } - // Configure IP instance from JSON config - virtual - void parse(Core &, json_t *) - { } + // Configure IP instance from JSON config + virtual void parse(Core &, json_t *) {} - static - Logger getStaticLogger() - { - return villas::logging.get("core:factory"); - } + static Logger getStaticLogger() { + return villas::logging.get("core:factory"); + } private: - virtual - void configurePollingMode(Core &, PollingMode) - { } + virtual void configurePollingMode(Core &, PollingMode) {} - virtual - Vlnv getCompatibleVlnv() const = 0; + virtual Vlnv getCompatibleVlnv() const = 0; - // Create a concrete IP instance - virtual - Core* make() const = 0; + // Create a concrete IP instance + virtual Core *make() const = 0; - static - CoreFactory* lookup(const Vlnv &vlnv); + static CoreFactory *lookup(const Vlnv &vlnv); }; -template +template class CorePlugin : public CoreFactory { public: -virtual - std::string getName() const - { - return name; - } + virtual std::string getName() const { return name; } - virtual - std::string getDescription() const - { - return desc; - } + virtual std::string getDescription() const { return desc; } private: - virtual - Vlnv getCompatibleVlnv() const - { - return Vlnv(vlnv); - } + virtual Vlnv getCompatibleVlnv() const { return Vlnv(vlnv); } - // Create a concrete IP instance - Core* make() const - { - return new T; - }; + // Create a concrete IP instance + Core *make() const { return new T; }; }; } // namespace ip @@ -351,6 +262,5 @@ template <> class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; #endif diff --git a/fpga/include/villas/fpga/dma.h b/fpga/include/villas/fpga/dma.h index 608a98b70..ebd7ffcc0 100644 --- a/fpga/include/villas/fpga/dma.h +++ b/fpga/include/villas/fpga/dma.h @@ -11,7 +11,6 @@ extern "C" { #endif - #include typedef struct villasfpga_handle_t *villasfpga_handle; @@ -21,15 +20,18 @@ villasfpga_handle villasfpga_init(const char *configFile); void villasfpga_destroy(villasfpga_handle handle); -int villasfpga_alloc(villasfpga_handle handle, villasfpga_memory *mem, size_t size); +int villasfpga_alloc(villasfpga_handle handle, villasfpga_memory *mem, + size_t size); int villasfpga_register(villasfpga_handle handle, villasfpga_memory *mem); int villasfpga_free(villasfpga_memory mem); -void* villasfpga_get_ptr(villasfpga_memory mem); +void *villasfpga_get_ptr(villasfpga_memory mem); -int villasfpga_read(villasfpga_handle handle, villasfpga_memory mem, size_t size); +int villasfpga_read(villasfpga_handle handle, villasfpga_memory mem, + size_t size); int villasfpga_read_complete(villasfpga_handle handle, size_t *size); -int villasfpga_write(villasfpga_handle handle, villasfpga_memory mem, size_t size); +int villasfpga_write(villasfpga_handle handle, villasfpga_memory mem, + size_t size); int villasfpga_write_complete(villasfpga_handle handle, size_t *size); #ifdef __cplusplus diff --git a/fpga/include/villas/fpga/ips/aurora.hpp b/fpga/include/villas/fpga/ips/aurora.hpp index be0c1da96..7c969687d 100644 --- a/fpga/include/villas/fpga/ips/aurora.hpp +++ b/fpga/include/villas/fpga/ips/aurora.hpp @@ -15,39 +15,27 @@ namespace ip { class Aurora : public Node { public: - static constexpr const char* masterPort = "m_axis"; - static constexpr const char* slavePort = "s_axis"; + static constexpr const char *masterPort = "m_axis"; + static constexpr const char *slavePort = "s_axis"; - virtual - void dump() override; + virtual void dump() override; - std::list getMemoryBlocks() const - { - return { - registerMemory - }; - } + std::list getMemoryBlocks() const { return {registerMemory}; } - const StreamVertex& - getDefaultSlavePort() const - { - return getSlavePort(slavePort); - } + const StreamVertex &getDefaultSlavePort() const { + return getSlavePort(slavePort); + } - const StreamVertex& - getDefaultMasterPort() const - { - return getMasterPort(masterPort); - } + const StreamVertex &getDefaultMasterPort() const { + return getMasterPort(masterPort); + } - void - setLoopback(bool state); + void setLoopback(bool state); - void - resetFrameCounters(); + void resetFrameCounters(); private: - static constexpr const char registerMemory[] = "reg0"; + static constexpr const char registerMemory[] = "reg0"; }; } // namespace ip diff --git a/fpga/include/villas/fpga/ips/aurora_xilinx.hpp b/fpga/include/villas/fpga/ips/aurora_xilinx.hpp index f89f86be9..4da5628f0 100644 --- a/fpga/include/villas/fpga/ips/aurora_xilinx.hpp +++ b/fpga/include/villas/fpga/ips/aurora_xilinx.hpp @@ -15,20 +15,16 @@ namespace ip { class AuroraXilinx : public Node { public: - static constexpr const char* masterPort = "USER_DATA_M_AXI_RX"; - static constexpr const char* slavePort = "USER_DATA_S_AXI_TX"; + static constexpr const char *masterPort = "USER_DATA_M_AXI_RX"; + static constexpr const char *slavePort = "USER_DATA_S_AXI_TX"; - const StreamVertex& - getDefaultSlavePort() const - { - return getSlavePort(slavePort); - } + const StreamVertex &getDefaultSlavePort() const { + return getSlavePort(slavePort); + } - const StreamVertex& - getDefaultMasterPort() const - { - return getMasterPort(masterPort); - } + const StreamVertex &getDefaultMasterPort() const { + return getMasterPort(masterPort); + } }; } // namespace ip diff --git a/fpga/include/villas/fpga/ips/bram.hpp b/fpga/include/villas/fpga/ips/bram.hpp index ee856632b..5381f5afb 100644 --- a/fpga/include/villas/fpga/ips/bram.hpp +++ b/fpga/include/villas/fpga/ips/bram.hpp @@ -7,8 +7,8 @@ #pragma once -#include #include +#include namespace villas { namespace fpga { @@ -17,64 +17,39 @@ namespace ip { class BramFactory; class Bram : public Core { - friend class BramFactory; + friend class BramFactory; public: + virtual bool init() override; - virtual - bool init() override; - - LinearAllocator& getAllocator() - { - return *allocator; - } + LinearAllocator &getAllocator() { return *allocator; } private: - static constexpr - const char* memoryBlock = "Mem0"; + static constexpr const char *memoryBlock = "Mem0"; - std::list getMemoryBlocks() const - { - return { - memoryBlock - }; - } + std::list getMemoryBlocks() const { return {memoryBlock}; } - size_t size; - std::unique_ptr allocator; + size_t size; + std::unique_ptr allocator; }; class BramFactory : public CoreFactory { public: - virtual - std::string getName() const - { - return "bram"; - } + virtual std::string getName() const { return "bram"; } - virtual - std::string getDescription() const - { - return "Block RAM"; - } + virtual std::string getDescription() const { return "Block RAM"; } private: - virtual - Vlnv getCompatibleVlnv() const - { - return Vlnv("xilinx.com:ip:axi_bram_ctrl:"); - } + virtual Vlnv getCompatibleVlnv() const { + return Vlnv("xilinx.com:ip:axi_bram_ctrl:"); + } - // Create a concrete IP instance - Core* make() const - { - return new Bram; - }; + // Create a concrete IP instance + Core *make() const { return new Bram; }; protected: - virtual - void parse(Core &, json_t *) override; + virtual void parse(Core &, json_t *) override; }; } // namespace ip diff --git a/fpga/include/villas/fpga/ips/dma.hpp b/fpga/include/villas/fpga/ips/dma.hpp index 8621b8f85..e29cc093a 100644 --- a/fpga/include/villas/fpga/ips/dma.hpp +++ b/fpga/include/villas/fpga/ips/dma.hpp @@ -10,178 +10,156 @@ #pragma once #include -#include #include -#include -#include #include +#include +#include +#include namespace villas { namespace fpga { namespace ip { -class Dma : public Node -{ +class Dma : public Node { public: - friend class DmaFactory; + friend class DmaFactory; - virtual - ~Dma(); + virtual ~Dma(); - virtual - bool init() override; + virtual bool init() override; - bool reset() override; + bool reset() override; - // Memory-mapped to stream (MM2S) - bool write(const MemoryBlock &mem, size_t len); + // 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); + // Stream to memory-mapped (S2MM) + bool read(const MemoryBlock &mem, size_t len); - struct Completion { - Completion() : bytes(0), bds(0), interrupts(0) { } - size_t bytes; // Number of bytes transferred - size_t bds; // Number of buffer descriptors used (only for scatter-gather) - size_t interrupts; // Number of interrupts received since last call (only if interrupts enabled) - }; + struct Completion { + Completion() : bytes(0), bds(0), interrupts(0) {} + size_t bytes; // Number of bytes transferred + size_t bds; // Number of buffer descriptors used (only for scatter-gather) + size_t + interrupts; // Number of interrupts received since last call (only if interrupts enabled) + }; - Completion writeComplete() - { - return hasScatterGather() ? writeCompleteScatterGather() : writeCompleteSimple(); - } + Completion writeComplete() { + return hasScatterGather() ? writeCompleteScatterGather() + : writeCompleteSimple(); + } - Completion readComplete() - { - return hasScatterGather() ? readCompleteScatterGather() : readCompleteSimple(); - } + Completion readComplete() { + return hasScatterGather() ? readCompleteScatterGather() + : readCompleteSimple(); + } - bool memcpy(const MemoryBlock &src, const MemoryBlock &dst, size_t len); + bool memcpy(const MemoryBlock &src, const MemoryBlock &dst, size_t len); - void makeAccesibleFromVA(std::shared_ptr mem); - bool makeInaccesibleFromVA(const MemoryBlock &mem); + void makeAccesibleFromVA(std::shared_ptr mem); + bool makeInaccesibleFromVA(const MemoryBlock &mem); - inline - bool hasScatterGather() const - { - return xConfig.HasSg; - } + inline bool hasScatterGather() const { return xConfig.HasSg; } - const StreamVertex& getDefaultSlavePort() const - { - return getSlavePort(s2mmPort); - } + const StreamVertex &getDefaultSlavePort() const { + return getSlavePort(s2mmPort); + } - const StreamVertex& getDefaultMasterPort() const - { - return getMasterPort(mm2sPort); - } + const StreamVertex &getDefaultMasterPort() const { + return getMasterPort(mm2sPort); + } - static constexpr const char* s2mmPort = "S2MM"; - static constexpr const char* mm2sPort = "MM2S"; + static constexpr const char *s2mmPort = "S2MM"; + static constexpr const char *mm2sPort = "MM2S"; - bool isMemoryBlockAccesible(const MemoryBlock &mem, const std::string &interface); + bool isMemoryBlockAccesible(const MemoryBlock &mem, + const std::string &interface); + + virtual void dump() override; - virtual - void dump() override; private: - bool writeScatterGather(const void* buf, size_t len); - bool readScatterGather(void* buf, size_t len); - Completion writeCompleteScatterGather(); - Completion readCompleteScatterGather(); + bool writeScatterGather(const void *buf, size_t len); + bool readScatterGather(void *buf, size_t len); + Completion writeCompleteScatterGather(); + Completion readCompleteScatterGather(); - bool writeSimple(const void* buf, size_t len); - bool readSimple(void* buf, size_t len); - Completion writeCompleteSimple(); - Completion readCompleteSimple(); + bool writeSimple(const void *buf, size_t len); + bool readSimple(void *buf, size_t len); + Completion writeCompleteSimple(); + Completion readCompleteSimple(); - void setupScatterGather(); - void setupScatterGatherRingRx(); - void setupScatterGatherRingTx(); + void setupScatterGather(); + void setupScatterGatherRingRx(); + void setupScatterGatherRingTx(); - static constexpr char registerMemory[] = "Reg"; + static constexpr char registerMemory[] = "Reg"; - static constexpr char mm2sInterrupt[] = "mm2s_introut"; - static constexpr char mm2sInterface[] = "M_AXI_MM2S"; + static constexpr char mm2sInterrupt[] = "mm2s_introut"; + static constexpr char mm2sInterface[] = "M_AXI_MM2S"; - static constexpr char s2mmInterrupt[] = "s2mm_introut"; - static constexpr char s2mmInterface[] = "M_AXI_S2MM"; + static constexpr char s2mmInterrupt[] = "s2mm_introut"; + static constexpr char s2mmInterface[] = "M_AXI_S2MM"; - // Optional Scatter-Gather interface to access descriptors - static constexpr char sgInterface[] = "M_AXI_SG"; + // Optional Scatter-Gather interface to access descriptors + static constexpr char sgInterface[] = "M_AXI_SG"; - std::list getMemoryBlocks() const - { - return { - registerMemory - }; - } + std::list getMemoryBlocks() const { + return {registerMemory}; + } - XAxiDma xDma; - XAxiDma_Config xConfig; + XAxiDma xDma; + XAxiDma_Config xConfig; - std::mutex hwLock; + std::mutex hwLock; - bool configDone = false; - // use polling to wait for DMA completion or interrupts via efds - bool polling = false; - // Timeout after which the DMA controller issues in interrupt if no data has been received - // Delay is 125 x x (clock period of SG clock). SG clock is 100 MHz by default. - int delay = 0; - // Coalesce is the number of messages/BDs to wait for before issuing an interrupt - uint32_t writeCoalesce = 1; - uint32_t readCoalesce = 1; + bool configDone = false; + // use polling to wait for DMA completion or interrupts via efds + bool polling = false; + // Timeout after which the DMA controller issues in interrupt if no data has been received + // Delay is 125 x x (clock period of SG clock). SG clock is 100 MHz by default. + int delay = 0; + // Coalesce is the number of messages/BDs to wait for before issuing an interrupt + uint32_t writeCoalesce = 1; + uint32_t readCoalesce = 1; - // (maximum) size of a single message on the read channel in bytes. - // The message buffer/BD should have enough room for this many bytes. - size_t readMsgSize = 4; + // (maximum) size of a single message on the read channel in bytes. + // The message buffer/BD should have enough room for this many bytes. + size_t readMsgSize = 4; - // When using SG: ringBdSize is the maximum number of BDs usable in the ring - // Depending on alignment, the actual number of BDs usable can be smaller - static constexpr size_t requestedRingBdSize = 2048; - static constexpr size_t requestedRingBdSizeMemory = requestedRingBdSize * sizeof(XAxiDma_Bd); - uint32_t actualRingBdSize = XAxiDma_BdRingCntCalc(XAXIDMA_BD_MINIMUM_ALIGNMENT, requestedRingBdSizeMemory); - std::shared_ptr sgRingTx; - std::shared_ptr sgRingRx; + // When using SG: ringBdSize is the maximum number of BDs usable in the ring + // Depending on alignment, the actual number of BDs usable can be smaller + static constexpr size_t requestedRingBdSize = 2048; + static constexpr size_t requestedRingBdSizeMemory = + requestedRingBdSize * sizeof(XAxiDma_Bd); + uint32_t actualRingBdSize = XAxiDma_BdRingCntCalc( + XAXIDMA_BD_MINIMUM_ALIGNMENT, requestedRingBdSizeMemory); + std::shared_ptr sgRingTx; + std::shared_ptr sgRingRx; }; class DmaFactory : NodeFactory { public: - virtual - std::string getName() const - { - return "dma"; - } + virtual std::string getName() const { return "dma"; } - virtual - std::string getDescription() const - { - return "Xilinx's AXI4 Direct Memory Access Controller"; - } + virtual std::string getDescription() const { + return "Xilinx's AXI4 Direct Memory Access Controller"; + } private: - virtual - Vlnv getCompatibleVlnv() const - { - return Vlnv("xilinx.com:ip:axi_dma:"); - } + virtual Vlnv getCompatibleVlnv() const { + return Vlnv("xilinx.com:ip:axi_dma:"); + } - // Create a concrete IP instance - Core* make() const - { - return new Dma; - }; + // Create a concrete IP instance + Core *make() const { return new Dma; }; protected: - virtual - void parse(Core& ip, json_t* json) override; + virtual void parse(Core &ip, json_t *json) override; - virtual - void configurePollingMode(Core& ip, PollingMode mode) override - { - dynamic_cast(ip).polling = (mode == POLL); - } + virtual void configurePollingMode(Core &ip, PollingMode mode) override { + dynamic_cast(ip).polling = (mode == POLL); + } }; } // namespace ip @@ -190,6 +168,5 @@ protected: #ifndef FMT_LEGACY_OSTREAM_FORMATTER template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; #endif diff --git a/fpga/include/villas/fpga/ips/emc.hpp b/fpga/include/villas/fpga/ips/emc.hpp index 3c3172a10..0c93f4094 100644 --- a/fpga/include/villas/fpga/ips/emc.hpp +++ b/fpga/include/villas/fpga/ips/emc.hpp @@ -17,27 +17,21 @@ namespace ip { class EMC : public Core { public: + virtual bool init() override; - virtual - bool init() override; + bool flash(uint32_t offset, const std::string &filename); + bool flash(uint32_t offset, uint32_t length, uint8_t *data); - bool flash(uint32_t offset, const std::string &filename); - bool flash(uint32_t offset, uint32_t length, uint8_t *data); - - bool read(uint32_t offset, uint32_t length, uint8_t *data); + bool read(uint32_t offset, uint32_t length, uint8_t *data); private: + XFlash xflash; - XFlash xflash; + static constexpr char registerMemory[] = "Reg"; - static constexpr char registerMemory[] = "Reg"; - - std::list getMemoryBlocks() const - { - return { - registerMemory - }; - } + std::list getMemoryBlocks() const { + return {registerMemory}; + } }; } // namespace ip diff --git a/fpga/include/villas/fpga/ips/fifo.hpp b/fpga/include/villas/fpga/ips/fifo.hpp index 4f4e22736..e28c0ef02 100644 --- a/fpga/include/villas/fpga/ips/fifo.hpp +++ b/fpga/include/villas/fpga/ips/fifo.hpp @@ -8,7 +8,6 @@ * SPDX-License-Identifier: Apache-2.0 */ - #pragma once #include @@ -21,35 +20,29 @@ namespace ip { class Fifo : public Node { public: - friend class FifoFactory; + friend class FifoFactory; - virtual - bool init() override; + virtual bool init() override; - virtual - bool stop() override; + virtual bool stop() override; - size_t write(const void* buf, size_t len); - size_t read(void* buf, size_t len); + size_t write(const void *buf, size_t len); + size_t read(void *buf, size_t len); private: - static constexpr char registerMemory[] = "Mem0"; - static constexpr char axi4Memory[] = "Mem1"; - static constexpr char irqName[] = "interrupt"; + static constexpr char registerMemory[] = "Mem0"; + static constexpr char axi4Memory[] = "Mem1"; + static constexpr char irqName[] = "interrupt"; - std::list getMemoryBlocks() const - { - return { - registerMemory, - axi4Memory - }; - } + std::list getMemoryBlocks() const { + return {registerMemory, axi4Memory}; + } - XLlFifo xFifo; + XLlFifo xFifo; }; class FifoData : public Node { - friend class FifoDataFactory; + friend class FifoDataFactory; }; } // namespace ip diff --git a/fpga/include/villas/fpga/ips/gpio.hpp b/fpga/include/villas/fpga/ips/gpio.hpp index f2f607fd9..c4b85b5ea 100644 --- a/fpga/include/villas/fpga/ips/gpio.hpp +++ b/fpga/include/villas/fpga/ips/gpio.hpp @@ -16,20 +16,14 @@ namespace ip { class Gpio : public Core { public: - - virtual - bool init() override; + virtual bool init() override; private: + static constexpr char registerMemory[] = "Reg"; - static constexpr char registerMemory[] = "Reg"; - - std::list getMemoryBlocks() const - { - return { - registerMemory - }; - } + std::list getMemoryBlocks() const { + return {registerMemory}; + } }; } // namespace ip diff --git a/fpga/include/villas/fpga/ips/gpu2rtds.hpp b/fpga/include/villas/fpga/ips/gpu2rtds.hpp index 20fa63387..a278d3ff7 100644 --- a/fpga/include/villas/fpga/ips/gpu2rtds.hpp +++ b/fpga/include/villas/fpga/ips/gpu2rtds.hpp @@ -7,9 +7,9 @@ #pragma once -#include -#include #include +#include +#include #include #include @@ -18,59 +18,56 @@ namespace villas { namespace fpga { namespace ip { -class Gpu2Rtds : public Node, public Hls -{ +class Gpu2Rtds : public Node, public Hls { public: - friend class Gpu2RtdsFactory; + friend class Gpu2RtdsFactory; - virtual - bool init() override; + virtual bool init() override; - void dump(spdlog::level::level_enum logLevel = spdlog::level::info); - bool startOnce(size_t frameSize); + void dump(spdlog::level::level_enum logLevel = spdlog::level::info); + bool startOnce(size_t frameSize); - size_t getMaxFrameSize(); + size_t getMaxFrameSize(); - const StreamVertex& - getDefaultMasterPort() const - { - return getMasterPort(rtdsOutputStreamPort); - } + const StreamVertex &getDefaultMasterPort() const { + return getMasterPort(rtdsOutputStreamPort); + } - MemoryBlock - getRegisterMemory() const - { - return MemoryBlock(0, 1 << 10, getAddressSpaceId(registerMemory)); - } + MemoryBlock getRegisterMemory() const { + return MemoryBlock(0, 1 << 10, getAddressSpaceId(registerMemory)); + } private: - bool updateStatus(); + bool updateStatus(); public: - static constexpr const char* rtdsOutputStreamPort = "rtds_output"; + static constexpr const char *rtdsOutputStreamPort = "rtds_output"; - struct StatusControlRegister { uint32_t - status_ap_vld : 1, - _res : 31; - }; + struct StatusControlRegister { + uint32_t status_ap_vld : 1, _res : 31; + }; - using StatusRegister = axilite_reg_status_t; + using StatusRegister = axilite_reg_status_t; - static constexpr uintptr_t registerStatusOffset = XGPU2RTDS_CTRL_ADDR_STATUS_DATA; - static constexpr uintptr_t registerStatusCtrlOffset = XGPU2RTDS_CTRL_ADDR_STATUS_CTRL; - static constexpr uintptr_t registerFrameSizeOffset = XGPU2RTDS_CTRL_ADDR_FRAME_SIZE_DATA; - static constexpr uintptr_t registerFrameOffset = XGPU2RTDS_CTRL_ADDR_FRAME_BASE; - static constexpr uintptr_t registerFrameLength = XGPU2RTDS_CTRL_DEPTH_FRAME; + static constexpr uintptr_t registerStatusOffset = + XGPU2RTDS_CTRL_ADDR_STATUS_DATA; + static constexpr uintptr_t registerStatusCtrlOffset = + XGPU2RTDS_CTRL_ADDR_STATUS_CTRL; + static constexpr uintptr_t registerFrameSizeOffset = + XGPU2RTDS_CTRL_ADDR_FRAME_SIZE_DATA; + static constexpr uintptr_t registerFrameOffset = + XGPU2RTDS_CTRL_ADDR_FRAME_BASE; + static constexpr uintptr_t registerFrameLength = XGPU2RTDS_CTRL_DEPTH_FRAME; public: - StatusRegister* registerStatus; - StatusControlRegister* registerStatusCtrl; - uint32_t* registerFrameSize; - uint32_t* registerFrames; + StatusRegister *registerStatus; + StatusControlRegister *registerStatusCtrl; + uint32_t *registerFrameSize; + uint32_t *registerFrames; - size_t maxFrameSize; + size_t maxFrameSize; - bool started; + bool started; }; } // namespace ip diff --git a/fpga/include/villas/fpga/ips/hls.hpp b/fpga/include/villas/fpga/ips/hls.hpp index 4315dff17..e62874b38 100644 --- a/fpga/include/villas/fpga/ips/hls.hpp +++ b/fpga/include/villas/fpga/ips/hls.hpp @@ -7,154 +7,125 @@ #pragma once -#include #include +#include namespace villas { namespace fpga { namespace ip { -class Hls : public virtual Core -{ +class Hls : public virtual Core { public: - virtual - bool init() override - { - auto ®isters = addressTranslations.at(registerMemory); + virtual bool init() override { + auto ®isters = addressTranslations.at(registerMemory); - controlRegister = reinterpret_cast(registers.getLocalAddr(registerControlAddr)); - globalIntRegister = reinterpret_cast(registers.getLocalAddr(registerGlobalIntEnableAddr)); - ipIntEnableRegister = reinterpret_cast(registers.getLocalAddr(registerIntEnableAddr)); - ipIntStatusRegister = reinterpret_cast(registers.getLocalAddr(registerIntStatusAddr)); + controlRegister = reinterpret_cast( + registers.getLocalAddr(registerControlAddr)); + globalIntRegister = reinterpret_cast( + registers.getLocalAddr(registerGlobalIntEnableAddr)); + ipIntEnableRegister = reinterpret_cast( + registers.getLocalAddr(registerIntEnableAddr)); + ipIntStatusRegister = reinterpret_cast( + registers.getLocalAddr(registerIntStatusAddr)); - setAutoRestart(false); - setGlobalInterrupt(false); + setAutoRestart(false); + setGlobalInterrupt(false); - return true; - } + return true; + } - bool start() - { - controlRegister->ap_start = true; - running = true; + bool start() { + controlRegister->ap_start = true; + running = true; - return true; - } + return true; + } - virtual bool isFinished() - { - updateRunningStatus(); + virtual bool isFinished() { + updateRunningStatus(); - return !running; - } + return !running; + } - bool isRunning() - { - updateRunningStatus(); + bool isRunning() { + updateRunningStatus(); - return running; - } + return running; + } - void setAutoRestart(bool enabled) const - { - controlRegister->auto_restart = enabled; - } + void setAutoRestart(bool enabled) const { + controlRegister->auto_restart = enabled; + } - void setGlobalInterrupt(bool enabled) const - { - globalIntRegister->globalInterruptEnable = enabled; - } + void setGlobalInterrupt(bool enabled) const { + globalIntRegister->globalInterruptEnable = enabled; + } - void setReadyInterrupt(bool enabled) const - { - ipIntEnableRegister->ap_ready = enabled; - } + void setReadyInterrupt(bool enabled) const { + ipIntEnableRegister->ap_ready = enabled; + } - void setDoneInterrupt(bool enabled) const - { - ipIntEnableRegister->ap_done = enabled; - } + void setDoneInterrupt(bool enabled) const { + ipIntEnableRegister->ap_done = enabled; + } - bool isIdleBit() const - { - return controlRegister->ap_idle; - } + bool isIdleBit() const { return controlRegister->ap_idle; } - bool isReadyBit() const - { - return controlRegister->ap_ready; - } + bool isReadyBit() const { return controlRegister->ap_ready; } - // Warning: the corresponding bit is cleared on read of the register, so if - // not used correctly, this function may never return true. Only use this - // function if you really know what you are doing! - bool isDoneBit() const - { - return controlRegister->ap_done; - } + // Warning: the corresponding bit is cleared on read of the register, so if + // not used correctly, this function may never return true. Only use this + // function if you really know what you are doing! + bool isDoneBit() const { return controlRegister->ap_done; } - bool isAutoRestartBit() const - { - return controlRegister->auto_restart; - } + bool isAutoRestartBit() const { return controlRegister->auto_restart; } private: - void updateRunningStatus() - { - if (running and isIdleBit()) - running = false; - } + void updateRunningStatus() { + if (running and isIdleBit()) + running = false; + } protected: - // Memory block handling + // Memory block handling - static constexpr const char* registerMemory = "Reg"; + static constexpr const char *registerMemory = "Reg"; - virtual std::list getMemoryBlocks() const - { - return { - registerMemory - }; - } + virtual std::list getMemoryBlocks() const { + return {registerMemory}; + } public: - // Register definitions + // Register definitions - static constexpr uintptr_t registerControlAddr = 0x00; - static constexpr uintptr_t registerGlobalIntEnableAddr = 0x04; - static constexpr uintptr_t registerIntEnableAddr = 0x08; - static constexpr uintptr_t registerIntStatusAddr = 0x0c; + static constexpr uintptr_t registerControlAddr = 0x00; + static constexpr uintptr_t registerGlobalIntEnableAddr = 0x04; + static constexpr uintptr_t registerIntEnableAddr = 0x08; + static constexpr uintptr_t registerIntStatusAddr = 0x0c; - union ControlRegister { - uint32_t value; - struct { uint32_t - ap_start : 1, - ap_done : 1, - ap_idle : 1, - ap_ready : 1, - _res1 : 3, - auto_restart : 1, - _res2 : 24; - }; - }; + union ControlRegister { + uint32_t value; + struct { + uint32_t ap_start : 1, ap_done : 1, ap_idle : 1, ap_ready : 1, _res1 : 3, + auto_restart : 1, _res2 : 24; + }; + }; - struct GlobalIntRegister { uint32_t - globalInterruptEnable : 1, - _res : 31; - }; + struct GlobalIntRegister { + uint32_t globalInterruptEnable : 1, _res : 31; + }; + + struct IpIntRegister { + uint32_t ap_done : 1, ap_ready : 1, _res : 30; + }; - struct IpIntRegister { uint32_t - ap_done : 1, - ap_ready : 1, - _res : 30; - }; protected: - ControlRegister* controlRegister; - GlobalIntRegister* globalIntRegister; - IpIntRegister* ipIntEnableRegister; - IpIntRegister* ipIntStatusRegister; + ControlRegister *controlRegister; + GlobalIntRegister *globalIntRegister; + IpIntRegister *ipIntEnableRegister; + IpIntRegister *ipIntStatusRegister; - bool running; + bool running; }; } // namespace ip diff --git a/fpga/include/villas/fpga/ips/i2c.hpp b/fpga/include/villas/fpga/ips/i2c.hpp index b76be99ab..73c9fc693 100644 --- a/fpga/include/villas/fpga/ips/i2c.hpp +++ b/fpga/include/villas/fpga/ips/i2c.hpp @@ -101,29 +101,27 @@ private: void driverWriteBlocking(u8 *dataPtr, size_t size); void driverReadBlocking(u8 *dataPtr, size_t max_read); }; - class I2cFactory : NodeFactory { +class I2cFactory : NodeFactory { - public: - virtual std::string getName() const { return "i2c"; } +public: + virtual std::string getName() const { return "i2c"; } - virtual std::string getDescription() const { - return "Xilinx's AXI4 iic IP"; - } + virtual std::string getDescription() const { return "Xilinx's AXI4 iic IP"; } - private: - virtual Vlnv getCompatibleVlnv() const { - return Vlnv("xilinx.com:ip:axi_iic:"); - } +private: + virtual Vlnv getCompatibleVlnv() const { + return Vlnv("xilinx.com:ip:axi_iic:"); + } - // Create a concrete IP instance - Core *make() const { return new I2c; }; + // Create a concrete IP instance + Core *make() const { return new I2c; }; - protected: - virtual void parse(Core &ip, json_t *json) override; - virtual void configurePollingMode(Core &ip, PollingMode mode) override { - dynamic_cast(ip).polling = (mode == POLL); - } - }; +protected: + virtual void parse(Core &ip, json_t *json) override; + virtual void configurePollingMode(Core &ip, PollingMode mode) override { + dynamic_cast(ip).polling = (mode == POLL); + } +}; } // namespace ip } // namespace fpga } // namespace villas diff --git a/fpga/include/villas/fpga/ips/intc.hpp b/fpga/include/villas/fpga/ips/intc.hpp index 3a61f5e6c..d558f9a82 100644 --- a/fpga/include/villas/fpga/ips/intc.hpp +++ b/fpga/include/villas/fpga/ips/intc.hpp @@ -31,33 +31,29 @@ public: return enableInterrupt(1 << irq.num, polling); } -bool disableInterrupt(IrqMaskType mask); -bool disableInterrupt(IrqPort irq) { return disableInterrupt(1 << irq.num); } + bool disableInterrupt(IrqMaskType mask); + bool disableInterrupt(IrqPort irq) { return disableInterrupt(1 << irq.num); } -ssize_t waitForInterrupt(int irq); -ssize_t waitForInterrupt(IrqPort irq) { return waitForInterrupt(irq.num); } + ssize_t waitForInterrupt(int irq); + ssize_t waitForInterrupt(IrqPort irq) { return waitForInterrupt(irq.num); } private: + static constexpr char registerMemory[] = "reg0"; - static constexpr char registerMemory[] = "reg0"; + std::list getMemoryBlocks() const { + return {registerMemory}; + } - std::list getMemoryBlocks() const - { - return { - registerMemory - }; - } + struct Interrupt { + int eventFd; // Event file descriptor + int number; // Interrupt number from /proc/interrupts + bool polling; // Polled or not + }; - struct Interrupt { - int eventFd; // Event file descriptor - int number; // Interrupt number from /proc/interrupts - bool polling; // Polled or not - }; - - int num_irqs; // Number of available MSI vectors - int efds[maxIrqs]; - int nos[maxIrqs]; - bool polling[maxIrqs]; + int num_irqs; // Number of available MSI vectors + int efds[maxIrqs]; + int nos[maxIrqs]; + bool polling[maxIrqs]; }; } // namespace ip diff --git a/fpga/include/villas/fpga/ips/pcie.hpp b/fpga/include/villas/fpga/ips/pcie.hpp index c40acec88..94c091825 100644 --- a/fpga/include/villas/fpga/ips/pcie.hpp +++ b/fpga/include/villas/fpga/ips/pcie.hpp @@ -20,60 +20,47 @@ namespace ip { class AxiPciExpressBridge : public Core { public: - friend class AxiPciExpressBridgeFactory; + friend class AxiPciExpressBridgeFactory; - virtual - bool init() override; + virtual bool init() override; private: - static constexpr char axiInterface[] = "M_AXI"; - static constexpr char pcieMemory[] = "BAR0"; + static constexpr char axiInterface[] = "M_AXI"; + static constexpr char pcieMemory[] = "BAR0"; - struct AxiBar { - uintptr_t base; - size_t size; - uintptr_t translation; - }; + struct AxiBar { + uintptr_t base; + size_t size; + uintptr_t translation; + }; - struct PciBar { - uintptr_t translation; - }; + struct PciBar { + uintptr_t translation; + }; - std::map axiToPcieTranslations; - std::map pcieToAxiTranslations; + std::map axiToPcieTranslations; + std::map pcieToAxiTranslations; }; class AxiPciExpressBridgeFactory : CoreFactory { public: - virtual - std::string getName() const - { - return "pcie"; - } + virtual std::string getName() const { return "pcie"; } - virtual - std::string getDescription() const - { - return "Xilinx's AXI-PCIe Bridge"; - } + virtual std::string getDescription() const { + return "Xilinx's AXI-PCIe Bridge"; + } private: - virtual - Vlnv getCompatibleVlnv() const - { - return Vlnv("xilinx.com:ip:axi_pcie:"); - } + virtual Vlnv getCompatibleVlnv() const { + return Vlnv("xilinx.com:ip:axi_pcie:"); + } - // Create a concrete IP instance - Core* make() const - { - return new AxiPciExpressBridge; - }; + // Create a concrete IP instance + Core *make() const { return new AxiPciExpressBridge; }; protected: - virtual - void parse(Core &, json_t *) override; + virtual void parse(Core &, json_t *) override; }; } // namespace ip diff --git a/fpga/include/villas/fpga/ips/rtds.hpp b/fpga/include/villas/fpga/ips/rtds.hpp index 8027c3be8..5168c0025 100644 --- a/fpga/include/villas/fpga/ips/rtds.hpp +++ b/fpga/include/villas/fpga/ips/rtds.hpp @@ -15,38 +15,28 @@ namespace ip { class RtdsGtfpga : public Node { public: - static constexpr const char* masterPort = "m_axis"; - static constexpr const char* slavePort = "s_axis"; + static constexpr const char *masterPort = "m_axis"; + static constexpr const char *slavePort = "s_axis"; - virtual - void dump() override; + virtual void dump() override; - double getDt(); + double getDt(); - std::list getMemoryBlocks() const - { - return { - registerMemory - }; - } + std::list getMemoryBlocks() const { return {registerMemory}; } - const StreamVertex& - getDefaultSlavePort() const - { - return getSlavePort(slavePort); - } + const StreamVertex &getDefaultSlavePort() const { + return getSlavePort(slavePort); + } - const StreamVertex& - getDefaultMasterPort() const - { - return getMasterPort(masterPort); - } + const StreamVertex &getDefaultMasterPort() const { + return getMasterPort(masterPort); + } private: - static constexpr const char registerMemory[] = "reg0"; - static constexpr const char* irqTs = "irq_ts"; - static constexpr const char* irqOverflow = "irq_overflow"; - static constexpr const char* irqCase = "irq_case"; + static constexpr const char registerMemory[] = "reg0"; + static constexpr const char *irqTs = "irq_ts"; + static constexpr const char *irqOverflow = "irq_overflow"; + static constexpr const char *irqCase = "irq_case"; }; } // namespace ip diff --git a/fpga/include/villas/fpga/ips/rtds2gpu.hpp b/fpga/include/villas/fpga/ips/rtds2gpu.hpp index 71c5497b5..508be3b7f 100644 --- a/fpga/include/villas/fpga/ips/rtds2gpu.hpp +++ b/fpga/include/villas/fpga/ips/rtds2gpu.hpp @@ -7,88 +7,69 @@ #pragma once -#include -#include #include +#include +#include -#include "rtds2gpu/xrtds2gpu.h" #include "rtds2gpu/register_types.hpp" +#include "rtds2gpu/xrtds2gpu.h" namespace villas { namespace fpga { namespace ip { union ControlRegister { - uint32_t value; - struct { uint32_t - ap_start : 1, - ap_done : 1, - ap_idle : 1, - ap_ready : 1, - _res1 : 3, - auto_restart : 1, - _res2 : 24; - }; + uint32_t value; + struct { + uint32_t ap_start : 1, ap_done : 1, ap_idle : 1, ap_ready : 1, _res1 : 3, + auto_restart : 1, _res2 : 24; + }; }; -class Rtds2Gpu : public Node, public Hls -{ +class Rtds2Gpu : public Node, public Hls { public: - friend class Rtds2GpuFactory; + friend class Rtds2GpuFactory; - virtual - bool init() override; + virtual bool init() override; - void dump(spdlog::level::level_enum logLevel = spdlog::level::info); + void dump(spdlog::level::level_enum logLevel = spdlog::level::info); - virtual - void dump() override - { - dump(spdlog::level::info); - } + virtual void dump() override { dump(spdlog::level::info); } - bool startOnce(const MemoryBlock &mem, size_t frameSize, size_t dataOffset, size_t doorbellOffset); + bool startOnce(const MemoryBlock &mem, size_t frameSize, size_t dataOffset, + size_t doorbellOffset); - size_t getMaxFrameSize(); + size_t getMaxFrameSize(); - void dumpDoorbell(uint32_t doorbellRegister) const; + void dumpDoorbell(uint32_t doorbellRegister) const; - bool doorbellIsValid(const uint32_t &doorbellRegister) const - { - return reinterpret_cast(doorbellRegister).is_valid; - } + bool doorbellIsValid(const uint32_t &doorbellRegister) const { + return reinterpret_cast(doorbellRegister).is_valid; + } - void doorbellReset(uint32_t &doorbellRegister) const - { - doorbellRegister = 0; - } + void doorbellReset(uint32_t &doorbellRegister) const { doorbellRegister = 0; } - std::list getMemoryBlocks() const - { - return { - registerMemory - }; - } + std::list getMemoryBlocks() const { + return {registerMemory}; + } - const StreamVertex& - getDefaultSlavePort() const - { - return getSlavePort(rtdsInputStreamPort); - } + const StreamVertex &getDefaultSlavePort() const { + return getSlavePort(rtdsInputStreamPort); + } private: - bool updateStatus(); + bool updateStatus(); private: - static constexpr const char* axiInterface = "m_axi_axi_mm"; - static constexpr const char* rtdsInputStreamPort = "rtds_input"; + static constexpr const char *axiInterface = "m_axi_axi_mm"; + static constexpr const char *rtdsInputStreamPort = "rtds_input"; - XRtds2gpu xInstance; + XRtds2gpu xInstance; - axilite_reg_status_t status; - size_t maxFrameSize; + axilite_reg_status_t status; + size_t maxFrameSize; - bool started; + bool started; }; } // namespace ip diff --git a/fpga/include/villas/fpga/ips/rtds2gpu/register_types.hpp b/fpga/include/villas/fpga/ips/rtds2gpu/register_types.hpp index 600b59287..b19fbbb94 100644 --- a/fpga/include/villas/fpga/ips/rtds2gpu/register_types.hpp +++ b/fpga/include/villas/fpga/ips/rtds2gpu/register_types.hpp @@ -7,55 +7,47 @@ #pragma once -#include #include #include +#include union axilite_reg_status_t { - uint32_t value; - struct { - uint32_t - last_seq_nr : 16, - last_count : 6, - max_frame_size : 6, - invalid_frame_size : 1, - frame_too_short : 1, - frame_too_long : 1, - is_running : 1; - }; + uint32_t value; + struct { + uint32_t last_seq_nr : 16, last_count : 6, max_frame_size : 6, + invalid_frame_size : 1, frame_too_short : 1, frame_too_long : 1, + is_running : 1; + }; }; union reg_doorbell_t { - uint32_t value; - struct { - uint32_t - seq_nr : 16, - count : 6, - is_valid : 1; - }; + uint32_t value; + struct { + uint32_t seq_nr : 16, count : 6, is_valid : 1; + }; - constexpr reg_doorbell_t() : value(0) {} + constexpr reg_doorbell_t() : value(0) {} }; -template -struct Rtds2GpuMemoryBuffer { - // This type is only for memory interpretation, it makes no sense to create - // an instance so it's forbidden - Rtds2GpuMemoryBuffer() = delete; +template struct Rtds2GpuMemoryBuffer { + // This type is only for memory interpretation, it makes no sense to create + // an instance so it's forbidden + Rtds2GpuMemoryBuffer() = delete; - // T can be a more complex type that wraps multiple values - static constexpr size_t rawValueCount = N * (sizeof(T) / 4); + // T can be a more complex type that wraps multiple values + static constexpr size_t rawValueCount = N * (sizeof(T) / 4); - // As of C++14, offsetof() is not working for non-standard layout types (i.e. - // composed of non-POD members). This might work in C++17 though. - // More info: https://gist.github.com/graphitemaster/494f21190bb2c63c5516 - //static constexpr size_t doorbellOffset = offsetof(Rtds2GpuMemoryBuffer, doorbell); - //static constexpr size_t dataOffset = offsetof(Rtds2GpuMemoryBuffer, data); + // As of C++14, offsetof() is not working for non-standard layout types (i.e. + // composed of non-POD members). This might work in C++17 though. + // More info: https://gist.github.com/graphitemaster/494f21190bb2c63c5516 + //static constexpr size_t doorbellOffset = offsetof(Rtds2GpuMemoryBuffer, doorbell); + //static constexpr size_t dataOffset = offsetof(Rtds2GpuMemoryBuffer, data); - // HACK: This might break horribly, let's just hope C++17 will be there soon - static constexpr size_t dataOffset = 0; - static constexpr size_t doorbellOffset = N * sizeof(Rtds2GpuMemoryBuffer::data); + // HACK: This might break horribly, let's just hope C++17 will be there soon + static constexpr size_t dataOffset = 0; + static constexpr size_t doorbellOffset = + N * sizeof(Rtds2GpuMemoryBuffer::data); - T data[N]; - reg_doorbell_t doorbell; + T data[N]; + reg_doorbell_t doorbell; }; diff --git a/fpga/include/villas/fpga/ips/rtds2gpu/xgpu2rtds_hw.h b/fpga/include/villas/fpga/ips/rtds2gpu/xgpu2rtds_hw.h index 9c26b3677..68e7eeceb 100644 --- a/fpga/include/villas/fpga/ips/rtds2gpu/xgpu2rtds_hw.h +++ b/fpga/include/villas/fpga/ips/rtds2gpu/xgpu2rtds_hw.h @@ -37,17 +37,16 @@ // Word n : bit [31:0] - frame[n] // (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake) -#define XGPU2RTDS_CTRL_ADDR_AP_CTRL 0x00 -#define XGPU2RTDS_CTRL_ADDR_GIE 0x04 -#define XGPU2RTDS_CTRL_ADDR_IER 0x08 -#define XGPU2RTDS_CTRL_ADDR_ISR 0x0c +#define XGPU2RTDS_CTRL_ADDR_AP_CTRL 0x00 +#define XGPU2RTDS_CTRL_ADDR_GIE 0x04 +#define XGPU2RTDS_CTRL_ADDR_IER 0x08 +#define XGPU2RTDS_CTRL_ADDR_ISR 0x0c #define XGPU2RTDS_CTRL_ADDR_FRAME_SIZE_DATA 0x10 #define XGPU2RTDS_CTRL_BITS_FRAME_SIZE_DATA 32 -#define XGPU2RTDS_CTRL_ADDR_STATUS_DATA 0x80 -#define XGPU2RTDS_CTRL_BITS_STATUS_DATA 32 -#define XGPU2RTDS_CTRL_ADDR_STATUS_CTRL 0x84 -#define XGPU2RTDS_CTRL_ADDR_FRAME_BASE 0x40 -#define XGPU2RTDS_CTRL_ADDR_FRAME_HIGH 0x7f -#define XGPU2RTDS_CTRL_WIDTH_FRAME 32 -#define XGPU2RTDS_CTRL_DEPTH_FRAME 16 - +#define XGPU2RTDS_CTRL_ADDR_STATUS_DATA 0x80 +#define XGPU2RTDS_CTRL_BITS_STATUS_DATA 32 +#define XGPU2RTDS_CTRL_ADDR_STATUS_CTRL 0x84 +#define XGPU2RTDS_CTRL_ADDR_FRAME_BASE 0x40 +#define XGPU2RTDS_CTRL_ADDR_FRAME_HIGH 0x7f +#define XGPU2RTDS_CTRL_WIDTH_FRAME 32 +#define XGPU2RTDS_CTRL_DEPTH_FRAME 16 diff --git a/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu.h b/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu.h index fc0a4d8c4..d1de5c0eb 100644 --- a/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu.h +++ b/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu.h @@ -14,21 +14,21 @@ extern "C" { /***************************** Include Files *********************************/ #ifndef __linux__ -#include "xil_types.h" #include "xil_assert.h" -#include "xstatus.h" #include "xil_io.h" +#include "xil_types.h" +#include "xstatus.h" #else -#include #include #include #include +#include +#include #include #include #include #include #include -#include #endif #include "xrtds2gpu_hw.h" @@ -39,44 +39,45 @@ typedef uint16_t u16; typedef uint32_t u32; #else typedef struct { - u16 DeviceId; - u32 Ctrl_BaseAddress; + u16 DeviceId; + u32 Ctrl_BaseAddress; } XRtds2gpu_Config; #endif typedef struct { - u32 Ctrl_BaseAddress; - u32 IsReady; + 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)) +#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 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_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 +#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); +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_Initialize(XRtds2gpu *InstancePtr, const char *InstanceName); int XRtds2gpu_Release(XRtds2gpu *InstancePtr); #endif diff --git a/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu_hw.h b/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu_hw.h index f361bc465..c68967821 100644 --- a/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu_hw.h +++ b/fpga/include/villas/fpga/ips/rtds2gpu/xrtds2gpu_hw.h @@ -43,19 +43,18 @@ // others - 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_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_FRAME_SIZE_DATA 0x28 -#define XRTDS2GPU_CTRL_BITS_FRAME_SIZE_DATA 32 -#define XRTDS2GPU_CTRL_ADDR_STATUS_DATA 0x30 -#define XRTDS2GPU_CTRL_BITS_STATUS_DATA 32 -#define XRTDS2GPU_CTRL_ADDR_STATUS_CTRL 0x34 - +#define XRTDS2GPU_CTRL_ADDR_FRAME_SIZE_DATA 0x28 +#define XRTDS2GPU_CTRL_BITS_FRAME_SIZE_DATA 32 +#define XRTDS2GPU_CTRL_ADDR_STATUS_DATA 0x30 +#define XRTDS2GPU_CTRL_BITS_STATUS_DATA 32 +#define XRTDS2GPU_CTRL_ADDR_STATUS_CTRL 0x34 diff --git a/fpga/include/villas/fpga/ips/timer.hpp b/fpga/include/villas/fpga/ips/timer.hpp index 00cb5ccc2..ae81eeabf 100644 --- a/fpga/include/villas/fpga/ips/timer.hpp +++ b/fpga/include/villas/fpga/ips/timer.hpp @@ -21,47 +21,30 @@ namespace fpga { namespace ip { class Timer : public Core { - friend class TimerFactory; + friend class TimerFactory; + public: + virtual bool init() override; - virtual - bool init() override; + bool start(uint32_t ticks); + bool wait(); + uint32_t remaining(); - bool start(uint32_t ticks); - bool wait(); - uint32_t remaining(); + inline bool isRunning() { return remaining() != 0; } - inline - bool isRunning() - { - return remaining() != 0; - } + inline bool isFinished() { return remaining() == 0; } - inline - bool isFinished() - { - return remaining() == 0; - } - - static constexpr - uint32_t getFrequency() - { - return FPGA_AXI_HZ; - } + static constexpr uint32_t getFrequency() { return FPGA_AXI_HZ; } private: + std::list getMemoryBlocks() const { + return {registerMemory}; + } - std::list getMemoryBlocks() const - { - return { - registerMemory - }; - } + static constexpr char irqName[] = "generateout0"; + static constexpr char registerMemory[] = "Reg"; - static constexpr char irqName[] = "generateout0"; - static constexpr char registerMemory[] = "Reg"; - - XTmrCtr xTmr; + XTmrCtr xTmr; }; } // namespace ip diff --git a/fpga/include/villas/fpga/node.hpp b/fpga/include/villas/fpga/node.hpp index 0a75c22ac..8bc420752 100644 --- a/fpga/include/villas/fpga/node.hpp +++ b/fpga/include/villas/fpga/node.hpp @@ -10,10 +10,10 @@ #pragma once +#include +#include #include #include -#include -#include #include #include #include @@ -24,172 +24,135 @@ namespace ip { class StreamVertex : public graph::Vertex { public: - StreamVertex(const std::string &node, const std::string &port, bool isMaster) : - graph::Vertex(), - nodeName(node), - portName(port), - isMaster(isMaster) - { } + StreamVertex(const std::string &node, const std::string &port, bool isMaster) + : graph::Vertex(), nodeName(node), portName(port), isMaster(isMaster) {} - std::string getName() const - { - return nodeName + "/" + portName + "(" + (isMaster ? "M" : "S") + ")"; - } + std::string getName() const { + return nodeName + "/" + portName + "(" + (isMaster ? "M" : "S") + ")"; + } - friend - std::ostream& operator<< (std::ostream &stream, const StreamVertex &vertex) - { - return stream << vertex.getIdentifier() << ": " << vertex.getName(); - } + friend std::ostream &operator<<(std::ostream &stream, + const StreamVertex &vertex) { + return stream << vertex.getIdentifier() << ": " << vertex.getName(); + } public: - std::string nodeName; - std::string portName; - bool isMaster; + std::string nodeName; + std::string portName; + bool isMaster; }; class StreamGraph : public graph::DirectedGraph { public: - StreamGraph() : - graph::DirectedGraph("stream:graph") - { } + StreamGraph() : graph::DirectedGraph("stream:graph") {} - std::shared_ptr getOrCreateStreamVertex(const std::string &node, - const std::string &port, - bool isMaster) - { - for (auto &vertexEntry : vertices) { - auto &vertex = vertexEntry.second; - if (vertex->nodeName == node and vertex->portName == port and vertex->isMaster == isMaster) - return vertex; - } + std::shared_ptr getOrCreateStreamVertex(const std::string &node, + const std::string &port, + bool isMaster) { + for (auto &vertexEntry : vertices) { + auto &vertex = vertexEntry.second; + if (vertex->nodeName == node and vertex->portName == port and + vertex->isMaster == isMaster) + return vertex; + } - // Vertex not found, create new one - auto vertex = std::make_shared(node, port, isMaster); - addVertex(vertex); + // Vertex not found, create new one + auto vertex = std::make_shared(node, port, isMaster); + addVertex(vertex); - return vertex; - } + return vertex; + } }; class Node : public virtual Core { public: + using Ptr = std::shared_ptr; - using Ptr = std::shared_ptr; + friend class NodeFactory; - friend class NodeFactory; + const StreamVertex &getMasterPort(const std::string &name) const { + return *portsMaster.at(name); + } - const StreamVertex& getMasterPort(const std::string &name) const - { - return *portsMaster.at(name); - } - - const std::map> &getMasterPorts() const - { + const std::map> & + getMasterPorts() const { return portsMaster; } - const StreamVertex& getSlavePort(const std::string &name) const - { - return *portsSlave.at(name); - } + const StreamVertex &getSlavePort(const std::string &name) const { + return *portsSlave.at(name); + } - const std::map> &getSlavePorts() const - { + const std::map> & + getSlavePorts() const { return portsSlave; } - bool connect(const StreamVertex &from, const StreamVertex &to); - bool connect(const StreamVertex &from, const StreamVertex &to, bool reverse) - { - bool ret; + bool connect(const StreamVertex &from, const StreamVertex &to); + bool connect(const StreamVertex &from, const StreamVertex &to, bool reverse) { + bool ret; - ret = connect(from, to); + ret = connect(from, to); - if (reverse) - ret &= connect(to, from); + if (reverse) + ret &= connect(to, from); - return ret; - } + return ret; + } - // Easy-usage assuming that the slave IP to connect to only has one slave - // port and implements the getDefaultSlavePort() function - bool connect(const Node &slaveNode, bool reverse = false) - { - return this->connect(this->getDefaultMasterPort(), slaveNode.getDefaultSlavePort(), reverse); - } + // Easy-usage assuming that the slave IP to connect to only has one slave + // port and implements the getDefaultSlavePort() function + bool connect(const Node &slaveNode, bool reverse = false) { + return this->connect(this->getDefaultMasterPort(), + slaveNode.getDefaultSlavePort(), reverse); + } - // Used by easy-usage connect, will throw if not implemented by derived node - virtual - const StreamVertex& getDefaultSlavePort() const; + // Used by easy-usage connect, will throw if not implemented by derived node + virtual const StreamVertex &getDefaultSlavePort() const; - // Used by easy-usage connect, will throw if not implemented by derived node - virtual - const StreamVertex& getDefaultMasterPort() const; + // Used by easy-usage connect, will throw if not implemented by derived node + virtual const StreamVertex &getDefaultMasterPort() const; - static - const StreamGraph& getGraph() - { - return streamGraph; - } + static const StreamGraph &getGraph() { return streamGraph; } - bool loopbackPossible() const; - bool connectLoopback(); + bool loopbackPossible() const; + bool connectLoopback(); protected: - virtual - bool connectInternal(const std::string &slavePort, - const std::string &masterPort); + virtual bool connectInternal(const std::string &slavePort, + const std::string &masterPort); private: - std::pair getLoopbackPorts() const; + std::pair getLoopbackPorts() const; protected: - std::map> portsMaster; - std::map> portsSlave; + std::map> portsMaster; + std::map> portsSlave; - static - StreamGraph streamGraph; + static StreamGraph streamGraph; }; class NodeFactory : public CoreFactory { public: - using CoreFactory::CoreFactory; + using CoreFactory::CoreFactory; - virtual - void parse(Core &, json_t *); + virtual void parse(Core &, json_t *); }; - -template +template class NodePlugin : public NodeFactory { public: -virtual - std::string getName() const - { - return name; - } + virtual std::string getName() const { return name; } - virtual - std::string getDescription() const - { - return desc; - } + virtual std::string getDescription() const { return desc; } private: - // Get a VLNV identifier for which this IP / Node type can be used. - virtual - Vlnv getCompatibleVlnv() const - { - return Vlnv(vlnv); - } + // Get a VLNV identifier for which this IP / Node type can be used. + virtual Vlnv getCompatibleVlnv() const { return Vlnv(vlnv); } - // Create a concrete IP instance - Core* make() const - { - return new T; - } + // Create a concrete IP instance + Core *make() const { return new T; } }; } // namespace ip @@ -201,6 +164,5 @@ template <> class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; #endif diff --git a/fpga/include/villas/fpga/pcie_card.hpp b/fpga/include/villas/fpga/pcie_card.hpp index 1f3afa151..76fa6f5ff 100644 --- a/fpga/include/villas/fpga/pcie_card.hpp +++ b/fpga/include/villas/fpga/pcie_card.hpp @@ -10,14 +10,14 @@ #pragma once +#include +#include #include #include #include -#include -#include -#include #include +#include #include #include @@ -35,39 +35,30 @@ class PCIeCardFactory; class PCIeCard : public Card { public: + ~PCIeCard(); - ~PCIeCard(); + bool init(); - bool init(); + bool stop() { return true; } - bool stop() - { - return true; - } + bool check() { return true; } - bool check() - { - return true; - } + bool reset() { + // TODO: Try via sysfs? + // echo 1 > /sys/bus/pci/devices/0000\:88\:00.0/reset + return true; + } - bool reset() - { - // TODO: Try via sysfs? - // echo 1 > /sys/bus/pci/devices/0000\:88\:00.0/reset - return true; - } + void dump() {} - void dump() - { } +public: // TODO: make this private + bool doReset; // Reset VILLASfpga during startup? + int affinity; // Affinity for MSI interrupts -public: // TODO: make this private - bool doReset; // Reset VILLASfpga during startup? - int affinity; // Affinity for MSI interrupts + std::shared_ptr pdev; // PCI device handle - std::shared_ptr pdev; // PCI device handle - - protected: - Logger getLogger() const { return villas::logging.get(name); } +protected: + Logger getLogger() const { return villas::logging.get(name); } }; class PCIeCardFactory : public plugin::Plugin { diff --git a/fpga/include/villas/fpga/utils.hpp b/fpga/include/villas/fpga/utils.hpp index 9fe9c1586..42f3afbb5 100644 --- a/fpga/include/villas/fpga/utils.hpp +++ b/fpga/include/villas/fpga/utils.hpp @@ -14,8 +14,8 @@ namespace villas { namespace fpga { -std::shared_ptr -setupFpgaCard(const std::string &configFile, const std::string &fpgaName); +std::shared_ptr setupFpgaCard(const std::string &configFile, + const std::string &fpgaName); std::shared_ptr createCard(json_t *config, const std::filesystem::path &searchPath, @@ -66,82 +66,77 @@ protected: int dstAsInt; }; - class BufferedSampleFormatter { - public: - virtual void format(float value) = 0; - virtual void output(std::ostream &out) { - out << buf.data() << std::flush; - clearBuf(); +class BufferedSampleFormatter { +public: + virtual void format(float value) = 0; + virtual void output(std::ostream &out) { + out << buf.data() << std::flush; + clearBuf(); + } + virtual void clearBuf() { + for (size_t i = 0; i < bufSamples && buf[i * bufSampleSize] != '\0'; i++) { + buf[i * bufSampleSize] = '\0'; } - virtual void clearBuf() { - for (size_t i = 0; i < bufSamples && buf[i * bufSampleSize] != '\0'; - i++) { - buf[i * bufSampleSize] = '\0'; - } - currentBufLoc = 0; + currentBufLoc = 0; + } + +protected: + std::vector buf; + const size_t bufSamples; + const size_t bufSampleSize; + size_t currentBufLoc; + + BufferedSampleFormatter(const size_t bufSamples, const size_t bufSampleSize) + : buf(bufSamples * bufSampleSize + 1), // Leave room for a final `\0' + bufSamples(bufSamples), bufSampleSize(bufSampleSize), + currentBufLoc(0){}; + BufferedSampleFormatter() = delete; + BufferedSampleFormatter(const BufferedSampleFormatter &) = delete; + virtual char *nextBufPos() { return &buf[(currentBufLoc++) * bufSampleSize]; } +}; + +class BufferedSampleFormatterShort : public BufferedSampleFormatter { +public: + BufferedSampleFormatterShort(size_t bufSizeInSamples) + : BufferedSampleFormatter(bufSizeInSamples, formatStringSize){}; + + virtual void format(float value) override { + size_t chars; + if ((chars = std::snprintf(nextBufPos(), formatStringSize + 1, formatString, + value)) > (int)formatStringSize) { + throw RuntimeError("Output buffer too small. Expected " + + std::to_string(formatStringSize) + + " characters, got " + std::to_string(chars)); } + } - protected: - std::vector buf; - const size_t bufSamples; - const size_t bufSampleSize; - size_t currentBufLoc; +protected: + static constexpr char formatString[] = "%013.6f\n"; + static constexpr size_t formatStringSize = 14; +}; - BufferedSampleFormatter(const size_t bufSamples, const size_t bufSampleSize) - : buf(bufSamples * bufSampleSize + 1), // Leave room for a final `\0' - bufSamples(bufSamples), bufSampleSize(bufSampleSize), - currentBufLoc(0){}; - BufferedSampleFormatter() = delete; - BufferedSampleFormatter(const BufferedSampleFormatter &) = delete; - virtual char *nextBufPos() { - return &buf[(currentBufLoc++) * bufSampleSize]; +class BufferedSampleFormatterLong : public BufferedSampleFormatter { +public: + BufferedSampleFormatterLong(size_t bufSizeInSamples) + : BufferedSampleFormatter(bufSizeInSamples, formatStringSize), + sampleCnt(0){}; + + virtual void format(float value) override { + if (std::snprintf(nextBufPos(), formatStringSize + 1, formatString, + sampleCnt, value) > (int)formatStringSize) { + throw RuntimeError("Output buffer too small"); } - }; + sampleCnt = (sampleCnt + 1) % 100000; + } - class BufferedSampleFormatterShort : public BufferedSampleFormatter { - public: - BufferedSampleFormatterShort(size_t bufSizeInSamples) - : BufferedSampleFormatter(bufSizeInSamples, formatStringSize){}; +protected: + static constexpr char formatString[] = "%05zd: %013.6f\n"; + static constexpr size_t formatStringSize = 22; + size_t sampleCnt; +}; - virtual void format(float value) override { - size_t chars; - if ((chars = std::snprintf(nextBufPos(), formatStringSize + 1, - formatString, value)) > - (int)formatStringSize) { - throw RuntimeError("Output buffer too small. Expected " + - std::to_string(formatStringSize) + - " characters, got " + std::to_string(chars)); - } - } - - protected: - static constexpr char formatString[] = "%013.6f\n"; - static constexpr size_t formatStringSize = 14; - }; - - class BufferedSampleFormatterLong : public BufferedSampleFormatter { - public: - BufferedSampleFormatterLong(size_t bufSizeInSamples) - : BufferedSampleFormatter(bufSizeInSamples, formatStringSize), - sampleCnt(0){}; - - virtual void format(float value) override { - if (std::snprintf(nextBufPos(), formatStringSize + 1, formatString, - sampleCnt, value) > (int)formatStringSize) { - throw RuntimeError("Output buffer too small"); - } - sampleCnt = (sampleCnt + 1) % 100000; - } - - protected: - static constexpr char formatString[] = "%05zd: %013.6f\n"; - static constexpr size_t formatStringSize = 22; - size_t sampleCnt; - }; - - std::unique_ptr - getBufferedSampleFormatter(const std::string &format, - size_t bufSizeInSamples); +std::unique_ptr +getBufferedSampleFormatter(const std::string &format, size_t bufSizeInSamples); } // namespace fpga } // namespace villas diff --git a/fpga/include/villas/fpga/vlnv.hpp b/fpga/include/villas/fpga/vlnv.hpp index 7b7be2b49..693903cad 100644 --- a/fpga/include/villas/fpga/vlnv.hpp +++ b/fpga/include/villas/fpga/vlnv.hpp @@ -7,10 +7,10 @@ #pragma once -#include -#include -#include #include +#include +#include +#include #include namespace villas { @@ -18,56 +18,34 @@ namespace fpga { class Vlnv { public: - static constexpr char delimiter = ':'; + static constexpr char delimiter = ':'; - Vlnv() : - vendor(""), - library(""), - name(""), - version("") - { } + Vlnv() : vendor(""), library(""), name(""), version("") {} - Vlnv(const std::string &s) - { - parseFromString(s); - } + Vlnv(const std::string &s) { parseFromString(s); } - static Vlnv - getWildcard() - { - return Vlnv(); - } + static Vlnv getWildcard() { return Vlnv(); } - std::string - toString() const; + std::string toString() const; - bool - operator==(const Vlnv &other) const; + bool operator==(const Vlnv &other) const; - bool - operator!=(const Vlnv &other) const - { - return !(*this == other); - } + bool operator!=(const Vlnv &other) const { return !(*this == other); } - friend std::ostream& - operator<< (std::ostream &stream, const Vlnv &vlnv) - { - return stream - << (vlnv.vendor.empty() ? "*" : vlnv.vendor) << ":" - << (vlnv.library.empty() ? "*" : vlnv.library) << ":" - << (vlnv.name.empty() ? "*" : vlnv.name) << ":" - << (vlnv.version.empty() ? "*" : vlnv.version); - } + friend std::ostream &operator<<(std::ostream &stream, const Vlnv &vlnv) { + return stream << (vlnv.vendor.empty() ? "*" : vlnv.vendor) << ":" + << (vlnv.library.empty() ? "*" : vlnv.library) << ":" + << (vlnv.name.empty() ? "*" : vlnv.name) << ":" + << (vlnv.version.empty() ? "*" : vlnv.version); + } private: - void - parseFromString(std::string vlnv); + void parseFromString(std::string vlnv); - std::string vendor; - std::string library; - std::string name; - std::string version; + std::string vendor; + std::string library; + std::string name; + std::string version; }; } // namespace fpga @@ -75,6 +53,5 @@ private: #ifndef FMT_LEGACY_OSTREAM_FORMATTER template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; #endif diff --git a/fpga/lib/card.cpp b/fpga/lib/card.cpp index 549d9ffed..1048b41b4 100644 --- a/fpga/lib/card.cpp +++ b/fpga/lib/card.cpp @@ -13,9 +13,8 @@ using namespace villas; using namespace villas::fpga; -Card::~Card() -{ - for (auto ip = ips.rbegin(); ip != ips.rend(); ++ip){ +Card::~Card() { + for (auto ip = ips.rbegin(); ip != ips.rend(); ++ip) { (*ip)->stop(); } // Ensure IP destructors are called before memory is unmapped @@ -34,100 +33,95 @@ Card::~Card() logger->debug("Unmap block {} at IOVA {:#x} of size {:#x}", mappedMemoryBlock.first, iova, size); vfioContainer->memoryUnmap(iova, size); - } + } } -std::shared_ptr Card::lookupIp(const std::string &name) const -{ - for(auto &ip : ips) { - if(*ip == name) { - return ip; - } - } +std::shared_ptr Card::lookupIp(const std::string &name) const { + for (auto &ip : ips) { + if (*ip == name) { + return ip; + } + } - return nullptr; + return nullptr; } -std::shared_ptr Card::lookupIp(const Vlnv &vlnv) const -{ - for(auto &ip : ips) { - if(*ip == vlnv) { - return ip; - } - } +std::shared_ptr Card::lookupIp(const Vlnv &vlnv) const { + for (auto &ip : ips) { + if (*ip == vlnv) { + return ip; + } + } - return nullptr; + return nullptr; } -std::shared_ptr Card::lookupIp(const ip::IpIdentifier &id) const -{ - for (auto &ip : ips) { - if (*ip == id) { - return ip; - } - } +std::shared_ptr Card::lookupIp(const ip::IpIdentifier &id) const { + for (auto &ip : ips) { + if (*ip == id) { + return ip; + } + } - return nullptr; + return nullptr; } -bool Card::unmapMemoryBlock(const MemoryBlock& block) -{ - if (memoryBlocksMapped.find(block.getAddrSpaceId()) == memoryBlocksMapped.end()) { - throw std::runtime_error("Block " + std::to_string(block.getAddrSpaceId()) + " is not mapped but was requested to be unmapped."); - } +bool Card::unmapMemoryBlock(const MemoryBlock &block) { + if (memoryBlocksMapped.find(block.getAddrSpaceId()) == + memoryBlocksMapped.end()) { + throw std::runtime_error( + "Block " + std::to_string(block.getAddrSpaceId()) + + " is not mapped but was requested to be unmapped."); + } - auto &mm = MemoryManager::get(); + auto &mm = MemoryManager::get(); - auto translation = mm.getTranslation(addrSpaceIdDeviceToHost, block.getAddrSpaceId()); + auto translation = + mm.getTranslation(addrSpaceIdDeviceToHost, block.getAddrSpaceId()); - const uintptr_t iova = translation.getLocalAddr(0); - const size_t size = translation.getSize(); + const uintptr_t iova = translation.getLocalAddr(0); + const size_t size = translation.getSize(); - logger->debug("Unmap block {} at IOVA {:#x} of size {:#x}", - block.getAddrSpaceId(), iova, size); - vfioContainer->memoryUnmap(iova, size); + logger->debug("Unmap block {} at IOVA {:#x} of size {:#x}", + block.getAddrSpaceId(), iova, size); + vfioContainer->memoryUnmap(iova, size); - memoryBlocksMapped.erase(block.getAddrSpaceId()); + memoryBlocksMapped.erase(block.getAddrSpaceId()); - return true; + return true; } +bool Card::mapMemoryBlock(const std::shared_ptr block) { + if (not vfioContainer->isIommuEnabled()) { + logger->warn("VFIO mapping not supported without IOMMU"); + return false; + } -bool Card::mapMemoryBlock(const std::shared_ptr block) -{ - if (not vfioContainer->isIommuEnabled()) { - logger->warn("VFIO mapping not supported without IOMMU"); - return false; - } + auto &mm = MemoryManager::get(); + const auto &addrSpaceId = block->getAddrSpaceId(); - auto &mm = MemoryManager::get(); - const auto &addrSpaceId = block->getAddrSpaceId(); + if (memoryBlocksMapped.find(addrSpaceId) != memoryBlocksMapped.end()) + // Block already mapped + return true; + else + logger->debug("Create VFIO mapping for {}", addrSpaceId); - if (memoryBlocksMapped.find(addrSpaceId) != memoryBlocksMapped.end()) - // Block already mapped - return true; - else - logger->debug("Create VFIO mapping for {}", addrSpaceId); + auto translationFromProcess = mm.getTranslationFromProcess(addrSpaceId); + uintptr_t processBaseAddr = translationFromProcess.getLocalAddr(0); + uintptr_t iovaAddr = + vfioContainer->memoryMap(processBaseAddr, UINTPTR_MAX, block->getSize()); - auto translationFromProcess = mm.getTranslationFromProcess(addrSpaceId); - uintptr_t processBaseAddr = translationFromProcess.getLocalAddr(0); - uintptr_t iovaAddr = vfioContainer->memoryMap(processBaseAddr, - UINTPTR_MAX, - block->getSize()); + if (iovaAddr == UINTPTR_MAX) { + logger->error("Cannot map memory at {:#x} of size {:#x}", processBaseAddr, + block->getSize()); + return false; + } - if (iovaAddr == UINTPTR_MAX) { - logger->error("Cannot map memory at {:#x} of size {:#x}", - processBaseAddr, block->getSize()); - return false; - } + mm.createMapping(iovaAddr, 0, block->getSize(), "VFIO-D2H", + this->addrSpaceIdDeviceToHost, addrSpaceId); - mm.createMapping(iovaAddr, 0, block->getSize(), - "VFIO-D2H", - this->addrSpaceIdDeviceToHost, - addrSpaceId); + // Remember that this block has already been mapped for later + memoryBlocksMapped.insert({addrSpaceId, block}); - // Remember that this block has already been mapped for later - memoryBlocksMapped.insert({addrSpaceId, block}); - - return true; + return true; } diff --git a/fpga/lib/dma.cpp b/fpga/lib/dma.cpp index cf50712da..5938d5b4b 100644 --- a/fpga/lib/dma.cpp +++ b/fpga/lib/dma.cpp @@ -9,18 +9,18 @@ #include #include -#include #include +#include #include #include #include -#include #include -#include +#include #include #include +#include using namespace villas; @@ -28,15 +28,14 @@ static std::shared_ptr pciDevices; static auto logger = villas::logging.get("villasfpga_dma"); struct villasfpga_handle_t { - std::shared_ptr card; - std::shared_ptr dma; + std::shared_ptr card; + std::shared_ptr dma; }; struct villasfpga_memory_t { - std::shared_ptr block; + std::shared_ptr block; }; -villasfpga_handle villasfpga_init(const char *configFile) -{ +villasfpga_handle villasfpga_init(const char *configFile) { std::string fpgaName = "vc707"; std::string connectStr = "3<->pipe"; std::string outputFormat = "short"; @@ -84,100 +83,93 @@ villasfpga_handle villasfpga_init(const char *configFile) } } -void villasfpga_destroy(villasfpga_handle handle) -{ - delete handle; +void villasfpga_destroy(villasfpga_handle handle) { delete handle; } + +int villasfpga_alloc(villasfpga_handle handle, villasfpga_memory *mem, + size_t size) { + try { + auto &alloc = villas::HostRam::getAllocator(); + *mem = new villasfpga_memory_t; + (*mem)->block = alloc.allocateBlock(size); + return villasfpga_register(handle, mem); + } catch (const RuntimeError &e) { + logger->error("Failed to allocate memory: {}", e.what()); + return -1; + } +} +int villasfpga_register(villasfpga_handle handle, villasfpga_memory *mem) { + try { + handle->dma->makeAccesibleFromVA((*mem)->block); + return 0; + } catch (const RuntimeError &e) { + logger->error("Failed to register memory: {}", e.what()); + return -1; + } +} +int villasfpga_free(villasfpga_memory mem) { + try { + delete mem; + return 0; + } catch (const RuntimeError &e) { + logger->error("Failed to free memory: {}", e.what()); + return -1; + } } -int villasfpga_alloc(villasfpga_handle handle, villasfpga_memory *mem, size_t size) -{ - try { - auto &alloc = villas::HostRam::getAllocator(); - *mem = new villasfpga_memory_t; - (*mem)->block = alloc.allocateBlock(size); - return villasfpga_register(handle, mem); - } catch (const RuntimeError &e) { - logger->error("Failed to allocate memory: {}", e.what()); - return -1; - } -} -int villasfpga_register(villasfpga_handle handle, villasfpga_memory *mem) -{ - try { - handle->dma->makeAccesibleFromVA((*mem)->block); - return 0; - } catch (const RuntimeError &e) { - logger->error("Failed to register memory: {}", e.what()); - return -1; - } -} -int villasfpga_free(villasfpga_memory mem) -{ - try { - delete mem; - return 0; - } catch (const RuntimeError &e) { - logger->error("Failed to free memory: {}", e.what()); - return -1; - } +int villasfpga_read(villasfpga_handle handle, villasfpga_memory mem, + size_t size) { + try { + if (!handle->dma->read(*mem->block, size)) { + logger->error("Failed to read from device"); + return -1; + } + return 0; + } catch (const RuntimeError &e) { + logger->error("Failed to read memory: {}", e.what()); + return -1; + } } -int villasfpga_read(villasfpga_handle handle, villasfpga_memory mem, size_t size) -{ - try { - if (!handle->dma->read(*mem->block, size)) { - logger->error("Failed to read from device"); - return -1; - } - return 0; - } catch (const RuntimeError &e) { - logger->error("Failed to read memory: {}", e.what()); - return -1; - } +int villasfpga_read_complete(villasfpga_handle handle, size_t *size) { + try { + auto readComp = handle->dma->readComplete(); + logger->debug("Read {} bytes", readComp.bytes); + *size = readComp.bytes; + return 0; + } catch (const RuntimeError &e) { + logger->error("Failed to read memory: {}", e.what()); + return -1; + } } -int villasfpga_read_complete(villasfpga_handle handle, size_t *size) -{ - try { - auto readComp = handle->dma->readComplete(); - logger->debug("Read {} bytes", readComp.bytes); - *size = readComp.bytes; - return 0; - } catch (const RuntimeError &e) { - logger->error("Failed to read memory: {}", e.what()); - return -1; - } +int villasfpga_write(villasfpga_handle handle, villasfpga_memory mem, + size_t size) { + try { + if (!handle->dma->write(*mem->block, size)) { + logger->error("Failed to write to device"); + return -1; + } + return 0; + } catch (const RuntimeError &e) { + logger->error("Failed to write memory: {}", e.what()); + return -1; + } } -int villasfpga_write(villasfpga_handle handle, villasfpga_memory mem, size_t size) -{ - try { - if (!handle->dma->write(*mem->block, size)) { - logger->error("Failed to write to device"); - return -1; - } - return 0; - } catch (const RuntimeError &e) { - logger->error("Failed to write memory: {}", e.what()); - return -1; - } +int villasfpga_write_complete(villasfpga_handle handle, size_t *size) { + try { + auto writeComp = handle->dma->writeComplete(); + logger->debug("Wrote {} bytes", writeComp.bytes); + *size = writeComp.bytes; + return 0; + } catch (const RuntimeError &e) { + logger->error("Failed to write memory: {}", e.what()); + return -1; + } } -int villasfpga_write_complete(villasfpga_handle handle, size_t *size) -{ - try { - auto writeComp = handle->dma->writeComplete(); - logger->debug("Wrote {} bytes", writeComp.bytes); - *size = writeComp.bytes; - return 0; - } catch (const RuntimeError &e) { - logger->error("Failed to write memory: {}", e.what()); - return -1; - } +void *villasfpga_get_ptr(villasfpga_memory mem) { + return (void *)MemoryManager::get() + .getTranslationFromProcess(mem->block->getAddrSpaceId()) + .getLocalAddr(0); } - -void* villasfpga_get_ptr(villasfpga_memory mem) -{ - return (void*)MemoryManager::get().getTranslationFromProcess(mem->block->getAddrSpaceId()).getLocalAddr(0); -} - diff --git a/fpga/lib/ips/aurora.cpp b/fpga/lib/ips/aurora.cpp index fc540af2b..40a2f68b0 100644 --- a/fpga/lib/ips/aurora.cpp +++ b/fpga/lib/ips/aurora.cpp @@ -12,91 +12,106 @@ #include // Register offsets -#define AURORA_AXIS_SR_OFFSET 0x00 // Status Register (read-only) -#define AURORA_AXIS_CR_OFFSET 0x04 // Control Register (read/write) -#define AURORA_AXIS_CNTR_IN_HIGH_OFFSET 0x0C // Higher 32-bits of incoming frame counter -#define AURORA_AXIS_CNTR_IN_LOW_OFFSET 0x08 // Lower 32-bits of incoming frame counter -#define AURORA_AXIS_CNTR_OUT_HIGH_OFFSET 0x18 // Higher 32-bits of outgoing frame counter -#define AURORA_AXIS_CNTR_OUT_LOW_OFFSET 0x1C // Lower 32-bits of outgoing frame counter +#define AURORA_AXIS_SR_OFFSET 0x00 // Status Register (read-only) +#define AURORA_AXIS_CR_OFFSET 0x04 // Control Register (read/write) +#define AURORA_AXIS_CNTR_IN_HIGH_OFFSET \ + 0x0C // Higher 32-bits of incoming frame counter +#define AURORA_AXIS_CNTR_IN_LOW_OFFSET \ + 0x08 // Lower 32-bits of incoming frame counter +#define AURORA_AXIS_CNTR_OUT_HIGH_OFFSET \ + 0x18 // Higher 32-bits of outgoing frame counter +#define AURORA_AXIS_CNTR_OUT_LOW_OFFSET \ + 0x1C // Lower 32-bits of outgoing frame counter // Status register bits -#define AURORA_AXIS_SR_CHAN_UP (1 << 0) // 1-bit, asserted when channel initialisation is complete and is ready for data transfer -#define AURORA_AXIS_SR_LANE_UP (1 << 1) // 1-bit, asserted for each lane upon successful lane initialisation -#define AURORA_AXIS_SR_HARD_ERR (1 << 2) // 1-bit hard rror status -#define AURORA_AXIS_SR_SOFT_ERR (1 << 3) // 1-bit soft error status -#define AURORA_AXIS_SR_FRAME_ERR (1 << 4) // 1-bit frame error status +#define AURORA_AXIS_SR_CHAN_UP \ + (1 \ + << 0) // 1-bit, asserted when channel initialisation is complete and is ready for data transfer +#define AURORA_AXIS_SR_LANE_UP \ + (1 << 1) // 1-bit, asserted for each lane upon successful lane initialisation +#define AURORA_AXIS_SR_HARD_ERR (1 << 2) // 1-bit hard rror status +#define AURORA_AXIS_SR_SOFT_ERR (1 << 3) // 1-bit soft error status +#define AURORA_AXIS_SR_FRAME_ERR (1 << 4) // 1-bit frame error status // Control register bits // 1-bit, assert to put Aurora IP in loopback mode. -#define AURORA_AXIS_CR_LOOPBACK (1 << 0) +#define AURORA_AXIS_CR_LOOPBACK (1 << 0) // 1-bit, assert to reset counters, incoming and outgoing frame counters. -#define AURORA_AXIS_CR_RST_CTRS (1 << 1) +#define AURORA_AXIS_CR_RST_CTRS (1 << 1) // 1-bit, assert to turn off any sequence number handling by Aurora IP // Sequence number must be handled in software then. -#define AURORA_AXIS_CR_SEQ_MODE (1 << 2) +#define AURORA_AXIS_CR_SEQ_MODE (1 << 2) /* 1-bit, assert to strip the received frame of the trailing sequence * number. Sequence number mode must be set to handled by Aurora IP, * otherwise this bit is ignored. */ -#define AURORA_AXIS_CR_SEQ_STRIP (1 << 3) +#define AURORA_AXIS_CR_SEQ_STRIP (1 << 3) /* 1-bit, assert to use the same sequence number in the outgoing * NovaCor-bound frames as the sequence number received from the * incoming frames from NovaCor. Sequence number mode must be set to * handled by Aurora IP, otherwise this bit is ignored.*/ -#define AURORA_AXIS_CR_SEQ_ECHO (1 << 4) +#define AURORA_AXIS_CR_SEQ_ECHO (1 << 4) using namespace villas::fpga::ip; -void Aurora::dump() -{ - // Check Aurora AXI4 registers - const uint32_t sr = readMemory(registerMemory, AURORA_AXIS_SR_OFFSET); +void Aurora::dump() { + // Check Aurora AXI4 registers + const uint32_t sr = + readMemory(registerMemory, AURORA_AXIS_SR_OFFSET); - logger->info("Aurora-NovaCor AXI-Stream interface details:"); - logger->info("Aurora status: {:#x}", sr); - logger->info(" Channel up: {}", sr & AURORA_AXIS_SR_CHAN_UP ? CLR_GRN("yes") : CLR_RED("no")); - logger->info(" Lane up: {}", sr & AURORA_AXIS_SR_LANE_UP ? CLR_GRN("yes") : CLR_RED("no")); - logger->info(" Hard error: {}", sr & AURORA_AXIS_SR_HARD_ERR ? CLR_RED("yes") : CLR_GRN("no")); - logger->info(" Soft error: {}", sr & AURORA_AXIS_SR_SOFT_ERR ? CLR_RED("yes") : CLR_GRN("no")); - logger->info(" Frame error: {}", sr & AURORA_AXIS_SR_FRAME_ERR ? CLR_RED("yes") : CLR_GRN("no")); + logger->info("Aurora-NovaCor AXI-Stream interface details:"); + logger->info("Aurora status: {:#x}", sr); + logger->info(" Channel up: {}", + sr & AURORA_AXIS_SR_CHAN_UP ? CLR_GRN("yes") : CLR_RED("no")); + logger->info(" Lane up: {}", + sr & AURORA_AXIS_SR_LANE_UP ? CLR_GRN("yes") : CLR_RED("no")); + logger->info(" Hard error: {}", + sr & AURORA_AXIS_SR_HARD_ERR ? CLR_RED("yes") : CLR_GRN("no")); + logger->info(" Soft error: {}", + sr & AURORA_AXIS_SR_SOFT_ERR ? CLR_RED("yes") : CLR_GRN("no")); + logger->info(" Frame error: {}", + sr & AURORA_AXIS_SR_FRAME_ERR ? CLR_RED("yes") : CLR_GRN("no")); - const uint64_t inCntLow = readMemory(registerMemory, AURORA_AXIS_CNTR_IN_LOW_OFFSET); - const uint64_t inCntHigh = readMemory(registerMemory, AURORA_AXIS_CNTR_IN_HIGH_OFFSET); - const uint64_t inCnt = (inCntHigh << 32) | inCntLow; + const uint64_t inCntLow = + readMemory(registerMemory, AURORA_AXIS_CNTR_IN_LOW_OFFSET); + const uint64_t inCntHigh = + readMemory(registerMemory, AURORA_AXIS_CNTR_IN_HIGH_OFFSET); + const uint64_t inCnt = (inCntHigh << 32) | inCntLow; - const uint64_t outCntLow = readMemory(registerMemory, AURORA_AXIS_CNTR_OUT_LOW_OFFSET); - const uint64_t outCntHigh = readMemory(registerMemory, AURORA_AXIS_CNTR_OUT_HIGH_OFFSET); - const uint64_t outCnt = (outCntHigh << 32) | outCntLow; + const uint64_t outCntLow = + readMemory(registerMemory, AURORA_AXIS_CNTR_OUT_LOW_OFFSET); + const uint64_t outCntHigh = + readMemory(registerMemory, AURORA_AXIS_CNTR_OUT_HIGH_OFFSET); + const uint64_t outCnt = (outCntHigh << 32) | outCntLow; - logger->info("Aurora frames received: {}", inCnt); - logger->info("Aurora frames sent: {}", outCnt); + logger->info("Aurora frames received: {}", inCnt); + logger->info("Aurora frames sent: {}", outCnt); } -void Aurora::setLoopback(bool state) -{ - auto cr = readMemory(registerMemory, AURORA_AXIS_CR_OFFSET); +void Aurora::setLoopback(bool state) { + auto cr = readMemory(registerMemory, AURORA_AXIS_CR_OFFSET); - if (state) - cr |= AURORA_AXIS_CR_LOOPBACK; - else - cr &= ~AURORA_AXIS_CR_LOOPBACK; + if (state) + cr |= AURORA_AXIS_CR_LOOPBACK; + else + cr &= ~AURORA_AXIS_CR_LOOPBACK; - writeMemory(registerMemory, AURORA_AXIS_CR_OFFSET, cr); + writeMemory(registerMemory, AURORA_AXIS_CR_OFFSET, cr); } -void Aurora::resetFrameCounters() -{ - auto cr = readMemory(registerMemory, AURORA_AXIS_CR_OFFSET); +void Aurora::resetFrameCounters() { + auto cr = readMemory(registerMemory, AURORA_AXIS_CR_OFFSET); - cr |= AURORA_AXIS_CR_RST_CTRS; + cr |= AURORA_AXIS_CR_RST_CTRS; - writeMemory(registerMemory, AURORA_AXIS_CR_OFFSET, cr); + writeMemory(registerMemory, AURORA_AXIS_CR_OFFSET, cr); } static char n[] = "aurora"; -static char d[] = "Aurora 8B/10B and additional support modules, like an AXI4-Lite register interface."; +static char d[] = "Aurora 8B/10B and additional support modules, like an " + "AXI4-Lite register interface."; static char v[] = "acs.eonerc.rwth-aachen.de:user:aurora_axis:"; static NodePlugin f; diff --git a/fpga/lib/ips/bram.cpp b/fpga/lib/ips/bram.cpp index 0c711dcf9..4f2032542 100644 --- a/fpga/lib/ips/bram.cpp +++ b/fpga/lib/ips/bram.cpp @@ -11,26 +11,22 @@ using namespace villas; using namespace villas::fpga::ip; -void BramFactory::parse(Core &ip, json_t* cfg) -{ - CoreFactory::parse(ip, cfg); +void BramFactory::parse(Core &ip, json_t *cfg) { + CoreFactory::parse(ip, cfg); - auto &bram = dynamic_cast(ip); + auto &bram = dynamic_cast(ip); - json_error_t err; - int ret = json_unpack_ex(cfg, &err, 0, "{ s: i }", - "size", &bram.size - ); - if (ret != 0) - throw ConfigError(cfg, err, "", "Cannot parse BRAM config"); + json_error_t err; + int ret = json_unpack_ex(cfg, &err, 0, "{ s: i }", "size", &bram.size); + if (ret != 0) + throw ConfigError(cfg, err, "", "Cannot parse BRAM config"); } -bool Bram::init() -{ - allocator = std::make_unique - (getAddressSpaceId(memoryBlock), this->size, 0); +bool Bram::init() { + allocator = std::make_unique(getAddressSpaceId(memoryBlock), + this->size, 0); - return true; + return true; } static BramFactory f; diff --git a/fpga/lib/ips/emc.cpp b/fpga/lib/ips/emc.cpp index e91dc311e..2d41803b9 100644 --- a/fpga/lib/ips/emc.cpp +++ b/fpga/lib/ips/emc.cpp @@ -7,140 +7,136 @@ #include -#include #include +#include using namespace villas::fpga::ip; -bool EMC::init() -{ - int ret; - const uintptr_t base = getBaseAddr(registerMemory); +bool EMC::init() { + int ret; + const uintptr_t base = getBaseAddr(registerMemory); - const int busWidth = 2; + const int busWidth = 2; #if defined(XPAR_XFL_DEVICE_FAMILY_INTEL) && XFL_TO_ASYNCMODE - // Set Flash to Async mode. - if (busWidth == 1) { - WRITE_FLASH_8(base + ASYNC_ADDR, 0x60); - WRITE_FLASH_8(base + ASYNC_ADDR, 0x03); - } - else if (busWidth == 2) { - WRITE_FLASH_16(base + ASYNC_ADDR, INTEL_CMD_CONFIG_REG_SETUP); - WRITE_FLASH_16(base + ASYNC_ADDR, INTEL_CMD_CONFIG_REG_CONFIRM); - } + // Set Flash to Async mode. + if (busWidth == 1) { + WRITE_FLASH_8(base + ASYNC_ADDR, 0x60); + WRITE_FLASH_8(base + ASYNC_ADDR, 0x03); + } else if (busWidth == 2) { + WRITE_FLASH_16(base + ASYNC_ADDR, INTEL_CMD_CONFIG_REG_SETUP); + WRITE_FLASH_16(base + ASYNC_ADDR, INTEL_CMD_CONFIG_REG_CONFIRM); + } #endif - ret = XFlash_Initialize(&xflash, base, busWidth, 0); - if (ret != XST_SUCCESS) - return false; + ret = XFlash_Initialize(&xflash, base, busWidth, 0); + if (ret != XST_SUCCESS) + return false; - return XFlash_IsReady(&xflash); + return XFlash_IsReady(&xflash); } -bool EMC::read(uint32_t offset, uint32_t length, uint8_t *data) -{ - int ret; +bool EMC::read(uint32_t offset, uint32_t length, uint8_t *data) { + int ret; - /* Reset the Flash Device. This clears the ret registers and puts + /* Reset the Flash Device. This clears the ret registers and puts * the device in Read mode. */ - ret = XFlash_Reset(&xflash); - if (ret != XST_SUCCESS) - return false; + ret = XFlash_Reset(&xflash); + if (ret != XST_SUCCESS) + return false; - // Perform the read operation. - ret = XFlash_Read(&xflash, offset, length, data); - if (ret != XST_SUCCESS) - return false; + // Perform the read operation. + ret = XFlash_Read(&xflash, offset, length, data); + if (ret != XST_SUCCESS) + return false; - return false; + return false; } // objcopy -I ihex -O binary somefile.mcs somefile.bin -bool EMC::flash(uint32_t offset, const std::string &filename) -{ - bool result; - uint32_t length; - uint8_t *buffer; +bool EMC::flash(uint32_t offset, const std::string &filename) { + bool result; + uint32_t length; + uint8_t *buffer; - std::ifstream is(filename, std::ios::binary); + std::ifstream is(filename, std::ios::binary); - // Get length of file: - is.seekg(0, std::ios::end); - length = is.tellg(); + // Get length of file: + is.seekg(0, std::ios::end); + length = is.tellg(); - is.seekg (0, std::ios::beg); - // Allocate memory: + is.seekg(0, std::ios::beg); + // Allocate memory: - buffer = new uint8_t[length]; - is.read(reinterpret_cast(buffer), length); - is.close(); + buffer = new uint8_t[length]; + is.read(reinterpret_cast(buffer), length); + is.close(); - result = flash(offset, length, buffer); + result = flash(offset, length, buffer); - delete[] buffer; + delete[] buffer; - return result; + return result; } // Based on xilflash_readwrite_example.c -bool EMC::flash(uint32_t offset, uint32_t length, uint8_t *data) -{ - int ret = XST_FAILURE; - uint32_t start = offset; +bool EMC::flash(uint32_t offset, uint32_t length, uint8_t *data) { + int ret = XST_FAILURE; + uint32_t start = offset; - /* Reset the Flash Device. This clears the ret registers and puts + /* Reset the Flash Device. This clears the ret registers and puts * the device in Read mode. */ - ret = XFlash_Reset(&xflash); - if (ret != XST_SUCCESS){ - return false; - } + ret = XFlash_Reset(&xflash); + if (ret != XST_SUCCESS) { + return false; + } - /* Perform an unlock operation before the erase operation for the Intel + /* Perform an unlock operation before the erase operation for the Intel * Flash. The erase operation will result in an error if the block is * locked. */ - if ((xflash.CommandSet == XFL_CMDSET_INTEL_STANDARD) || - (xflash.CommandSet == XFL_CMDSET_INTEL_EXTENDED) || - (xflash.CommandSet == XFL_CMDSET_INTEL_G18)) { - ret = XFlash_Unlock(&xflash, offset, 0); - if(ret != XST_SUCCESS){ - return false; - } - } + if ((xflash.CommandSet == XFL_CMDSET_INTEL_STANDARD) || + (xflash.CommandSet == XFL_CMDSET_INTEL_EXTENDED) || + (xflash.CommandSet == XFL_CMDSET_INTEL_G18)) { + ret = XFlash_Unlock(&xflash, offset, 0); + if (ret != XST_SUCCESS) { + return false; + } + } - // Perform the Erase operation. - ret = XFlash_Erase(&xflash, start, length); - if (ret != XST_SUCCESS){; - return false; - } + // Perform the Erase operation. + ret = XFlash_Erase(&xflash, start, length); + if (ret != XST_SUCCESS) { + ; + return false; + } - // Perform the Write operation. - ret = XFlash_Write(&xflash, start, length, data); - if (ret != XST_SUCCESS){ - return false; - } + // Perform the Write operation. + ret = XFlash_Write(&xflash, start, length, data); + if (ret != XST_SUCCESS) { + return false; + } - // Perform the read operation. - uint8_t *verify_data = new uint8_t[length]; - ret = XFlash_Read(&xflash, start, length, verify_data); - if(ret != XST_SUCCESS) { - delete[] verify_data; - return false; - } + // Perform the read operation. + uint8_t *verify_data = new uint8_t[length]; + ret = XFlash_Read(&xflash, start, length, verify_data); + if (ret != XST_SUCCESS) { + delete[] verify_data; + return false; + } - // Compare the data read against the data Written. - for (unsigned i = 0; i < length; i++) { - if (verify_data[i] != data[i]){ - delete[] verify_data; - return false; - } - } + // Compare the data read against the data Written. + for (unsigned i = 0; i < length; i++) { + if (verify_data[i] != data[i]) { + delete[] verify_data; + return false; + } + } - delete[] verify_data; + delete[] verify_data; - return true; + return true; } static char n[] = "emc"; diff --git a/fpga/lib/ips/fifo.cpp b/fpga/lib/ips/fifo.cpp index e845da60d..fcc95bcdc 100644 --- a/fpga/lib/ips/fifo.cpp +++ b/fpga/lib/ips/fifo.cpp @@ -10,84 +10,81 @@ #include -#include #include +#include #include #include using namespace villas::fpga::ip; -bool Fifo::init() -{ - XLlFifo_Config fifo_cfg; +bool Fifo::init() { + XLlFifo_Config fifo_cfg; - try { - // If this throws an exception, then there's no AXI4 data interface - fifo_cfg.Axi4BaseAddress = getBaseAddr(axi4Memory); - fifo_cfg.Datainterface = 1; - } catch (const std::out_of_range&) { - fifo_cfg.Datainterface = 0; - } + try { + // If this throws an exception, then there's no AXI4 data interface + fifo_cfg.Axi4BaseAddress = getBaseAddr(axi4Memory); + fifo_cfg.Datainterface = 1; + } catch (const std::out_of_range &) { + fifo_cfg.Datainterface = 0; + } - if (XLlFifo_CfgInitialize(&xFifo, &fifo_cfg, getBaseAddr(registerMemory)) != XST_SUCCESS) - return false; + if (XLlFifo_CfgInitialize(&xFifo, &fifo_cfg, getBaseAddr(registerMemory)) != + XST_SUCCESS) + return false; - if (irqs.find(irqName) == irqs.end()) { - logger->error("IRQ '{}' not found but required", irqName); - return false; - } + if (irqs.find(irqName) == irqs.end()) { + logger->error("IRQ '{}' not found but required", irqName); + return false; + } - // Receive complete IRQ - XLlFifo_IntEnable(&xFifo, XLLF_INT_RC_MASK); - irqs[irqName].irqController->enableInterrupt(irqs[irqName], false); + // Receive complete IRQ + XLlFifo_IntEnable(&xFifo, XLLF_INT_RC_MASK); + irqs[irqName].irqController->enableInterrupt(irqs[irqName], false); - return true; + return true; } -bool Fifo::stop() -{ - // Receive complete IRQ - XLlFifo_IntDisable(&xFifo, XLLF_INT_RC_MASK); - irqs[irqName].irqController->disableInterrupt(irqs[irqName]); +bool Fifo::stop() { + // Receive complete IRQ + XLlFifo_IntDisable(&xFifo, XLLF_INT_RC_MASK); + irqs[irqName].irqController->disableInterrupt(irqs[irqName]); - return true; + return true; } -size_t Fifo::write(const void *buf, size_t len) -{ +size_t Fifo::write(const void *buf, size_t len) { - uint32_t tdfv; + uint32_t tdfv; - tdfv = XLlFifo_TxVacancy(&xFifo); - if (tdfv < len) - return -1; + tdfv = XLlFifo_TxVacancy(&xFifo); + if (tdfv < len) + return -1; - // Buf has to be re-casted because Xilinx driver doesn't use const - XLlFifo_Write(&xFifo, (void*) buf, len); - XLlFifo_TxSetLen(&xFifo, len); + // Buf has to be re-casted because Xilinx driver doesn't use const + XLlFifo_Write(&xFifo, (void *)buf, len); + XLlFifo_TxSetLen(&xFifo, len); - return len; + return len; } -size_t Fifo::read(void *buf, size_t len) -{ - size_t nextlen = 0; - size_t rxlen; +size_t Fifo::read(void *buf, size_t len) { + size_t nextlen = 0; + size_t rxlen; - while (!XLlFifo_IsRxDone(&xFifo)) - irqs[irqName].irqController->waitForInterrupt(irqs[irqName]); + while (!XLlFifo_IsRxDone(&xFifo)) + irqs[irqName].irqController->waitForInterrupt(irqs[irqName]); - XLlFifo_IntClear(&xFifo, XLLF_INT_RC_MASK); + XLlFifo_IntClear(&xFifo, XLLF_INT_RC_MASK); - // Get length of next frame - rxlen = XLlFifo_RxGetLen(&xFifo); - nextlen = std::min(rxlen, len); + // Get length of next frame + rxlen = XLlFifo_RxGetLen(&xFifo); + nextlen = std::min(rxlen, len); - // Read from FIFO - XLlFifo_Read(&xFifo, buf, nextlen); + // Read from FIFO + XLlFifo_Read(&xFifo, buf, nextlen); - return nextlen; + return nextlen; } static char n1[] = "fifo"; diff --git a/fpga/lib/ips/gpio.cpp b/fpga/lib/ips/gpio.cpp index 3b4fa581a..b3abb42bf 100644 --- a/fpga/lib/ips/gpio.cpp +++ b/fpga/lib/ips/gpio.cpp @@ -11,12 +11,10 @@ using namespace villas::fpga::ip; -bool -Gpio::init() -{ - //const uintptr_t base = getBaseAddr(registerMemory); +bool Gpio::init() { + //const uintptr_t base = getBaseAddr(registerMemory); - return true; + return true; } static char n[] = "gpio"; diff --git a/fpga/lib/ips/intc.cpp b/fpga/lib/ips/intc.cpp index ec2ab1079..70b80f7df 100644 --- a/fpga/lib/ips/intc.cpp +++ b/fpga/lib/ips/intc.cpp @@ -5,8 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include #include @@ -25,97 +25,96 @@ bool InterruptController::stop() { return card->vfioDevice->pciMsiDeinit(this->efds) > 0; } -bool -InterruptController::init() -{ - const uintptr_t base = getBaseAddr(registerMemory); +bool InterruptController::init() { + const uintptr_t base = getBaseAddr(registerMemory); - num_irqs = card->vfioDevice->pciMsiInit(efds); - if (num_irqs < 0) - return false; + num_irqs = card->vfioDevice->pciMsiInit(efds); + if (num_irqs < 0) + return false; - if (not card->vfioDevice->pciMsiFind(nos)) { - return false; - } + if (not card->vfioDevice->pciMsiFind(nos)) { + return false; + } - // For each IRQ - for (int i = 0; i < num_irqs; i++) { + // For each IRQ + for (int i = 0; i < num_irqs; i++) { - // Try pinning to core - PCIeCard* pciecard = dynamic_cast(card); - int ret = kernel::setIRQAffinity(nos[i], pciecard->affinity, nullptr); + // Try pinning to core + PCIeCard *pciecard = dynamic_cast(card); + int ret = kernel::setIRQAffinity(nos[i], pciecard->affinity, nullptr); - switch(ret) { - case 0: - // Everything is fine - break; - case EACCES: - logger->warn("No permission to change affinity of VFIO-MSI interrupt, " - "performance may be degraded!"); - break; - default: - logger->error("Failed to change affinity of VFIO-MSI interrupt"); - return false; - } + switch (ret) { + case 0: + // Everything is fine + break; + case EACCES: + logger->warn("No permission to change affinity of VFIO-MSI interrupt, " + "performance may be degraded!"); + break; + default: + logger->error("Failed to change affinity of VFIO-MSI interrupt"); + return false; + } - // Setup vector - XIntc_Out32(base + XIN_IVAR_OFFSET + i * 4, i); - } + // Setup vector + XIntc_Out32(base + XIN_IVAR_OFFSET + i * 4, i); + } - XIntc_Out32(base + XIN_IMR_OFFSET, 0x00000000); // Use manual acknowlegement for all IRQs - XIntc_Out32(base + XIN_IAR_OFFSET, 0xFFFFFFFF); // Acknowlege all pending IRQs manually - XIntc_Out32(base + XIN_IMR_OFFSET, 0xFFFFFFFF); // Use fast acknowlegement for all IRQs - XIntc_Out32(base + XIN_IER_OFFSET, 0x00000000); // Disable all IRQs by default - XIntc_Out32(base + XIN_MER_OFFSET, XIN_INT_HARDWARE_ENABLE_MASK | XIN_INT_MASTER_ENABLE_MASK); + XIntc_Out32(base + XIN_IMR_OFFSET, + 0x00000000); // Use manual acknowlegement for all IRQs + XIntc_Out32(base + XIN_IAR_OFFSET, + 0xFFFFFFFF); // Acknowlege all pending IRQs manually + XIntc_Out32(base + XIN_IMR_OFFSET, + 0xFFFFFFFF); // Use fast acknowlegement for all IRQs + XIntc_Out32(base + XIN_IER_OFFSET, 0x00000000); // Disable all IRQs by default + XIntc_Out32(base + XIN_MER_OFFSET, + XIN_INT_HARDWARE_ENABLE_MASK | XIN_INT_MASTER_ENABLE_MASK); - logger->debug("enabled interrupts"); + logger->debug("enabled interrupts"); - return true; + return true; } -bool -InterruptController::enableInterrupt(InterruptController::IrqMaskType mask, bool polling) -{ - const uintptr_t base = getBaseAddr(registerMemory); +bool InterruptController::enableInterrupt(InterruptController::IrqMaskType mask, + bool polling) { + const uintptr_t base = getBaseAddr(registerMemory); - // Current state of INTC - const uint32_t ier = XIntc_In32(base + XIN_IER_OFFSET); - const uint32_t imr = XIntc_In32(base + XIN_IMR_OFFSET); + // Current state of INTC + const uint32_t ier = XIntc_In32(base + XIN_IER_OFFSET); + const uint32_t imr = XIntc_In32(base + XIN_IMR_OFFSET); - // Clear pending IRQs - XIntc_Out32(base + XIN_IAR_OFFSET, mask); + // Clear pending IRQs + XIntc_Out32(base + XIN_IAR_OFFSET, mask); - for (int i = 0; i < num_irqs; i++) { - if (mask & (1 << i)) - this->polling[i] = polling; - } + for (int i = 0; i < num_irqs; i++) { + if (mask & (1 << i)) + this->polling[i] = polling; + } - if (polling) { - XIntc_Out32(base + XIN_IMR_OFFSET, imr & ~mask); - XIntc_Out32(base + XIN_IER_OFFSET, ier & ~mask); - } - else { - XIntc_Out32(base + XIN_IER_OFFSET, ier | mask); - XIntc_Out32(base + XIN_IMR_OFFSET, imr | mask); - } + if (polling) { + XIntc_Out32(base + XIN_IMR_OFFSET, imr & ~mask); + XIntc_Out32(base + XIN_IER_OFFSET, ier & ~mask); + } else { + XIntc_Out32(base + XIN_IER_OFFSET, ier | mask); + XIntc_Out32(base + XIN_IMR_OFFSET, imr | mask); + } - logger->debug("New ier = {:x}", XIntc_In32(base + XIN_IER_OFFSET)); - logger->debug("New imr = {:x}", XIntc_In32(base + XIN_IMR_OFFSET)); - logger->debug("New isr = {:x}", XIntc_In32(base + XIN_ISR_OFFSET)); - logger->debug("Interupts enabled: mask={:x} polling={:d}", mask, polling); + logger->debug("New ier = {:x}", XIntc_In32(base + XIN_IER_OFFSET)); + logger->debug("New imr = {:x}", XIntc_In32(base + XIN_IMR_OFFSET)); + logger->debug("New isr = {:x}", XIntc_In32(base + XIN_ISR_OFFSET)); + logger->debug("Interupts enabled: mask={:x} polling={:d}", mask, polling); - return true; + return true; } -bool -InterruptController::disableInterrupt(InterruptController::IrqMaskType mask) -{ - const uintptr_t base = getBaseAddr(registerMemory); - uint32_t ier = XIntc_In32(base + XIN_IER_OFFSET); +bool InterruptController::disableInterrupt( + InterruptController::IrqMaskType mask) { + const uintptr_t base = getBaseAddr(registerMemory); + uint32_t ier = XIntc_In32(base + XIN_IER_OFFSET); - XIntc_Out32(base + XIN_IER_OFFSET, ier & ~mask); + XIntc_Out32(base + XIN_IER_OFFSET, ier & ~mask); - return true; + return true; } ssize_t InterruptController::waitForInterrupt(int irq) { diff --git a/fpga/lib/ips/pcie.cpp b/fpga/lib/ips/pcie.cpp index c7861db53..c6b12025d 100644 --- a/fpga/lib/ips/pcie.cpp +++ b/fpga/lib/ips/pcie.cpp @@ -5,8 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include #include @@ -17,134 +17,125 @@ using namespace villas::fpga::ip; -bool -AxiPciExpressBridge::init() -{ - auto &mm = MemoryManager::get(); +bool AxiPciExpressBridge::init() { + auto &mm = MemoryManager::get(); - // Throw an exception if the is no bus master interface and thus no - // address space we can use for translation -> error - card->addrSpaceIdHostToDevice = busMasterInterfaces.at(axiInterface); + // Throw an exception if the is no bus master interface and thus no + // address space we can use for translation -> error + card->addrSpaceIdHostToDevice = busMasterInterfaces.at(axiInterface); - // Map PCIe BAR0 via VFIO - const void* bar0_mapped = card->vfioDevice->regionMap(VFIO_PCI_BAR0_REGION_INDEX); - if (bar0_mapped == MAP_FAILED) { - logger->error("Failed to mmap() BAR0"); - return false; - } + // Map PCIe BAR0 via VFIO + const void *bar0_mapped = + card->vfioDevice->regionMap(VFIO_PCI_BAR0_REGION_INDEX); + if (bar0_mapped == MAP_FAILED) { + logger->error("Failed to mmap() BAR0"); + return false; + } - // Determine size of BAR0 region - const size_t bar0_size = card->vfioDevice->regionGetSize(VFIO_PCI_BAR0_REGION_INDEX); + // Determine size of BAR0 region + const size_t bar0_size = + card->vfioDevice->regionGetSize(VFIO_PCI_BAR0_REGION_INDEX); - // Create a mapping from process address space to the FPGA card via vfio - mm.createMapping(reinterpret_cast(bar0_mapped), - 0, bar0_size, "vfio-h2d", - mm.getProcessAddressSpace(), - card->addrSpaceIdHostToDevice); + // Create a mapping from process address space to the FPGA card via vfio + mm.createMapping(reinterpret_cast(bar0_mapped), 0, bar0_size, + "vfio-h2d", mm.getProcessAddressSpace(), + card->addrSpaceIdHostToDevice); - // Make PCIe (IOVA) address space available to FPGA via BAR0 + // Make PCIe (IOVA) address space available to FPGA via BAR0 - // IPs that can access this address space will know it via their memory view - const auto addrSpaceNameDeviceToHost = - mm.getSlaveAddrSpaceName(getInstanceName(), pcieMemory); + // IPs that can access this address space will know it via their memory view + const auto addrSpaceNameDeviceToHost = + mm.getSlaveAddrSpaceName(getInstanceName(), pcieMemory); - // Save ID in card so we can create mappings later when needed (e.g. when - // allocating DMA memory in host RAM) - card->addrSpaceIdDeviceToHost = - mm.getOrCreateAddressSpace(addrSpaceNameDeviceToHost); + // Save ID in card so we can create mappings later when needed (e.g. when + // allocating DMA memory in host RAM) + card->addrSpaceIdDeviceToHost = + mm.getOrCreateAddressSpace(addrSpaceNameDeviceToHost); - auto pciAddrSpaceId = mm.getPciAddressSpace(); + auto pciAddrSpaceId = mm.getPciAddressSpace(); - auto regions = dynamic_cast(card)->pdev->getRegions(); + auto regions = dynamic_cast(card)->pdev->getRegions(); - int i = 0; - for (auto region : regions) { - const size_t region_size = region.end - region.start + 1; + int i = 0; + for (auto region : regions) { + const size_t region_size = region.end - region.start + 1; - char barName[] = "BARx"; - barName[3] = '0' + region.num; - auto pciBar = pcieToAxiTranslations.at(barName); + char barName[] = "BARx"; + barName[3] = '0' + region.num; + auto pciBar = pcieToAxiTranslations.at(barName); - logger->info("PCI-BAR{}: bus addr={:#x} size={:#x}", - region.num, region.start, region_size); - logger->info("PCI-BAR{}: AXI translation offset {:#x}", - i, pciBar.translation); + logger->info("PCI-BAR{}: bus addr={:#x} size={:#x}", region.num, + region.start, region_size); + logger->info("PCI-BAR{}: AXI translation offset {:#x}", i, + pciBar.translation); - mm.createMapping(region.start, pciBar.translation, region_size, - std::string("PCI-") + barName, - pciAddrSpaceId, card->addrSpaceIdHostToDevice); - } + mm.createMapping(region.start, pciBar.translation, region_size, + std::string("PCI-") + barName, pciAddrSpaceId, + card->addrSpaceIdHostToDevice); + } - for (auto& [barName, axiBar] : axiToPcieTranslations) { - logger->info("AXI-{}: bus addr={:#x} size={:#x}", - barName, axiBar.base, axiBar.size); - logger->info("AXI-{}: PCI translation offset: {:#x}", - barName, axiBar.translation); + for (auto &[barName, axiBar] : axiToPcieTranslations) { + logger->info("AXI-{}: bus addr={:#x} size={:#x}", barName, axiBar.base, + axiBar.size); + logger->info("AXI-{}: PCI translation offset: {:#x}", barName, + axiBar.translation); - auto barXAddrSpaceName = mm.getSlaveAddrSpaceName(getInstanceName(), barName); - auto barXAddrSpaceId = mm.getOrCreateAddressSpace(barXAddrSpaceName); + auto barXAddrSpaceName = + mm.getSlaveAddrSpaceName(getInstanceName(), barName); + auto barXAddrSpaceId = mm.getOrCreateAddressSpace(barXAddrSpaceName); - // Base is already incorporated into mapping of each IP by Vivado, so - // the mapping src has to be 0 - mm.createMapping(0, axiBar.translation, axiBar.size, - std::string("AXI-") + barName, - barXAddrSpaceId, pciAddrSpaceId); + // Base is already incorporated into mapping of each IP by Vivado, so + // the mapping src has to be 0 + mm.createMapping(0, axiBar.translation, axiBar.size, + std::string("AXI-") + barName, barXAddrSpaceId, + pciAddrSpaceId); - i++; - } + i++; + } - return true; + return true; } -void -AxiPciExpressBridgeFactory::parse(Core &ip, json_t *cfg) -{ - CoreFactory::parse(ip, cfg); +void AxiPciExpressBridgeFactory::parse(Core &ip, json_t *cfg) { + CoreFactory::parse(ip, cfg); - auto logger = getLogger(); - auto &pcie = dynamic_cast(ip); + auto logger = getLogger(); + auto &pcie = dynamic_cast(ip); - for (auto barType : std::list{ - "axi_bars", - "pcie_bars" - }) { - json_t *json_bars = json_object_get(cfg, barType.c_str()); - if (not json_is_object(json_bars)) - throw ConfigError(cfg, "", "Missing BAR config: {}", barType); + for (auto barType : std::list{"axi_bars", "pcie_bars"}) { + json_t *json_bars = json_object_get(cfg, barType.c_str()); + if (not json_is_object(json_bars)) + throw ConfigError(cfg, "", "Missing BAR config: {}", barType); - json_t* json_bar; - const char* bar_name; - json_object_foreach(json_bars, bar_name, json_bar) { - unsigned int translation; + json_t *json_bar; + const char *bar_name; + json_object_foreach(json_bars, bar_name, json_bar) { + unsigned int translation; - json_error_t err; - int ret = json_unpack_ex(json_bar, &err, 0, "{ s: i }", - "translation", &translation - ); - if (ret != 0) - throw ConfigError(json_bar, err, "", "Cannot parse {}/{}", barType, bar_name); + json_error_t err; + int ret = json_unpack_ex(json_bar, &err, 0, "{ s: i }", "translation", + &translation); + if (ret != 0) + throw ConfigError(json_bar, err, "", "Cannot parse {}/{}", barType, + bar_name); - if (barType == "axi_bars") { - json_int_t base, high, size; - int ret = json_unpack_ex(json_bar, &err, 0, "{ s: I, s: I, s: I }", - "baseaddr", &base, - "highaddr", &high, - "size", &size - ); - if (ret != 0) - throw ConfigError(json_bar, err, "", "Cannot parse {}/{}", barType, bar_name); + if (barType == "axi_bars") { + json_int_t base, high, size; + int ret = + json_unpack_ex(json_bar, &err, 0, "{ s: I, s: I, s: I }", + "baseaddr", &base, "highaddr", &high, "size", &size); + if (ret != 0) + throw ConfigError(json_bar, err, "", "Cannot parse {}/{}", barType, + bar_name); - pcie.axiToPcieTranslations[bar_name] = { - .base = static_cast(base), - .size = static_cast(size), - .translation = translation - }; - } else - pcie.pcieToAxiTranslations[bar_name] = { - .translation = translation - }; - } - } + pcie.axiToPcieTranslations[bar_name] = { + .base = static_cast(base), + .size = static_cast(size), + .translation = translation}; + } else + pcie.pcieToAxiTranslations[bar_name] = {.translation = translation}; + } + } } static AxiPciExpressBridgeFactory p; diff --git a/fpga/lib/ips/rtds.cpp b/fpga/lib/ips/rtds.cpp index 944d9d79c..78f266572 100644 --- a/fpga/lib/ips/rtds.cpp +++ b/fpga/lib/ips/rtds.cpp @@ -11,63 +11,86 @@ #include -#define RTDS_HZ 100000000 // 100 MHz +#define RTDS_HZ 100000000 // 100 MHz -#define RTDS_AXIS_MAX_TX 64 // The amount of values which is supported by the VIILASfpga card -#define RTDS_AXIS_MAX_RX 64 // The amount of values which is supported by the VIILASfpga card +#define RTDS_AXIS_MAX_TX \ + 64 // The amount of values which is supported by the VIILASfpga card +#define RTDS_AXIS_MAX_RX \ + 64 // The amount of values which is supported by the VIILASfpga card // Register offsets -#define RTDS_AXIS_SR_OFFSET 0x00 // Status Register (read-only). See RTDS_AXIS_SR_* constant. -#define RTDS_AXIS_CR_OFFSET 0x04 // Control Register (read/write) -#define RTDS_AXIS_TSCNT_LOW_OFFSET 0x08 // Lower 32 bits of timestep counter (read-only). -#define RTDS_AXIS_TSCNT_HIGH_OFFSET 0x0C // Higher 32 bits of timestep counter (read-only). -#define RTDS_AXIS_TS_PERIOD_OFFSET 0x10 // Period in clock cycles of previous timestep (read-only). -#define RTDS_AXIS_COALESC_OFFSET 0x14 // IRQ Coalescing register (read/write). -#define RTDS_AXIS_VERSION_OFFSET 0x18 // 16 bit version field passed back to the rack for version reporting (visible from “status” command, read/write). -#define RTDS_AXIS_MRATE 0x1C // Multi-rate register +#define RTDS_AXIS_SR_OFFSET \ + 0x00 // Status Register (read-only). See RTDS_AXIS_SR_* constant. +#define RTDS_AXIS_CR_OFFSET 0x04 // Control Register (read/write) +#define RTDS_AXIS_TSCNT_LOW_OFFSET \ + 0x08 // Lower 32 bits of timestep counter (read-only). +#define RTDS_AXIS_TSCNT_HIGH_OFFSET \ + 0x0C // Higher 32 bits of timestep counter (read-only). +#define RTDS_AXIS_TS_PERIOD_OFFSET \ + 0x10 // Period in clock cycles of previous timestep (read-only). +#define RTDS_AXIS_COALESC_OFFSET 0x14 // IRQ Coalescing register (read/write). +#define RTDS_AXIS_VERSION_OFFSET \ + 0x18 // 16 bit version field passed back to the rack for version reporting (visible from “status” command, read/write). +#define RTDS_AXIS_MRATE 0x1C // Multi-rate register // Status register bits -#define RTDS_AXIS_SR_CARDDETECTED (1 << 0) // ‘1’ when RTDS software has detected and configured card. -#define RTDS_AXIS_SR_LINKUP (1 << 1) // ‘1’ when RTDS communication link has been negotiated. -#define RTDS_AXIS_SR_TX_FULL (1 << 2) // Tx buffer is full, writes that happen when UserTxFull=’1’ will be dropped (Throttling / buffering is performed by hardware). -#define RTDS_AXIS_SR_TX_INPROGRESS (1 << 3) // Indicates when data is being put on link. -#define RTDS_AXIS_SR_CASE_RUNNING (1 << 4) // There is currently a simulation running. +#define RTDS_AXIS_SR_CARDDETECTED \ + (1 << 0) // ‘1’ when RTDS software has detected and configured card. +#define RTDS_AXIS_SR_LINKUP \ + (1 << 1) // ‘1’ when RTDS communication link has been negotiated. +#define RTDS_AXIS_SR_TX_FULL \ + (1 \ + << 2) // Tx buffer is full, writes that happen when UserTxFull=’1’ will be dropped (Throttling / buffering is performed by hardware). +#define RTDS_AXIS_SR_TX_INPROGRESS \ + (1 << 3) // Indicates when data is being put on link. +#define RTDS_AXIS_SR_CASE_RUNNING \ + (1 << 4) // There is currently a simulation running. // Control register bits -#define RTDS_AXIS_CR_DISABLE_LINK 0 // Disable SFP TX when set +#define RTDS_AXIS_CR_DISABLE_LINK 0 // Disable SFP TX when set using namespace villas::fpga::ip; -void RtdsGtfpga::dump() -{ - // Check RTDS_Axis registers - const uint32_t sr = readMemory(registerMemory, RTDS_AXIS_SR_OFFSET); +void RtdsGtfpga::dump() { + // Check RTDS_Axis registers + const uint32_t sr = readMemory(registerMemory, RTDS_AXIS_SR_OFFSET); - logger->info("RTDS AXI Stream interface details:"); - logger->info("RTDS status: {:#x}", sr); - logger->info(" Card detected: {}", sr & RTDS_AXIS_SR_CARDDETECTED ? CLR_GRN("yes") : CLR_RED("no")); - logger->info(" Link up: {}", sr & RTDS_AXIS_SR_LINKUP ? CLR_GRN("yes") : CLR_RED("no")); - logger->info(" TX queue full: {}", sr & RTDS_AXIS_SR_TX_FULL ? CLR_RED("yes") : CLR_GRN("no")); - logger->info(" TX in progress: {}", sr & RTDS_AXIS_SR_TX_INPROGRESS ? CLR_YEL("yes") : "no"); - logger->info(" Case running: {}", sr & RTDS_AXIS_SR_CASE_RUNNING ? CLR_GRN("yes") : CLR_RED("no")); + logger->info("RTDS AXI Stream interface details:"); + logger->info("RTDS status: {:#x}", sr); + logger->info(" Card detected: {}", + sr & RTDS_AXIS_SR_CARDDETECTED ? CLR_GRN("yes") : CLR_RED("no")); + logger->info(" Link up: {}", + sr & RTDS_AXIS_SR_LINKUP ? CLR_GRN("yes") : CLR_RED("no")); + logger->info(" TX queue full: {}", + sr & RTDS_AXIS_SR_TX_FULL ? CLR_RED("yes") : CLR_GRN("no")); + logger->info(" TX in progress: {}", + sr & RTDS_AXIS_SR_TX_INPROGRESS ? CLR_YEL("yes") : "no"); + logger->info(" Case running: {}", + sr & RTDS_AXIS_SR_CASE_RUNNING ? CLR_GRN("yes") : CLR_RED("no")); - logger->info("RTDS control: {:#x}", readMemory(registerMemory, RTDS_AXIS_CR_OFFSET)); - logger->info("RTDS IRQ coalesc: {}", readMemory(registerMemory, RTDS_AXIS_COALESC_OFFSET)); - logger->info("RTDS IRQ version: {:#x}", readMemory(registerMemory, RTDS_AXIS_VERSION_OFFSET)); - logger->info("RTDS IRQ multi-rate: {}", readMemory(registerMemory, RTDS_AXIS_MRATE)); + logger->info("RTDS control: {:#x}", + readMemory(registerMemory, RTDS_AXIS_CR_OFFSET)); + logger->info("RTDS IRQ coalesc: {}", + readMemory(registerMemory, RTDS_AXIS_COALESC_OFFSET)); + logger->info("RTDS IRQ version: {:#x}", + readMemory(registerMemory, RTDS_AXIS_VERSION_OFFSET)); + logger->info("RTDS IRQ multi-rate: {}", + readMemory(registerMemory, RTDS_AXIS_MRATE)); - const uint64_t timestepLow = readMemory(registerMemory, RTDS_AXIS_TSCNT_LOW_OFFSET); - const uint64_t timestepHigh = readMemory(registerMemory, RTDS_AXIS_TSCNT_HIGH_OFFSET); - const uint64_t timestep = (timestepHigh << 32) | timestepLow; + const uint64_t timestepLow = + readMemory(registerMemory, RTDS_AXIS_TSCNT_LOW_OFFSET); + const uint64_t timestepHigh = + readMemory(registerMemory, RTDS_AXIS_TSCNT_HIGH_OFFSET); + const uint64_t timestep = (timestepHigh << 32) | timestepLow; - logger->info("RTDS timestep counter: {}", timestep); - logger->info("RTDS timestep period: {:.3f} us", getDt() * 1e6); + logger->info("RTDS timestep counter: {}", timestep); + logger->info("RTDS timestep period: {:.3f} us", getDt() * 1e6); } -double RtdsGtfpga::getDt() -{ - const auto dt = readMemory(registerMemory, RTDS_AXIS_TS_PERIOD_OFFSET); - return (dt == 0xFFFF) ? 0.0 : (double) dt / RTDS_HZ; +double RtdsGtfpga::getDt() { + const auto dt = + readMemory(registerMemory, RTDS_AXIS_TS_PERIOD_OFFSET); + return (dt == 0xFFFF) ? 0.0 : (double)dt / RTDS_HZ; } static char n[] = "rtds_gtfpga"; diff --git a/fpga/lib/ips/rtds2gpu/gpu2rtds.cpp b/fpga/lib/ips/rtds2gpu/gpu2rtds.cpp index ad6a42a6c..ad0845854 100644 --- a/fpga/lib/ips/rtds2gpu/gpu2rtds.cpp +++ b/fpga/lib/ips/rtds2gpu/gpu2rtds.cpp @@ -5,57 +5,62 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include +#include #include #include -#include using namespace villas::fpga::ip; -bool Gpu2Rtds::init() -{ - Hls::init(); +bool Gpu2Rtds::init() { + Hls::init(); - auto ®isters = addressTranslations.at(registerMemory); + auto ®isters = addressTranslations.at(registerMemory); - registerStatus = reinterpret_cast(registers.getLocalAddr(registerStatusOffset)); - registerStatusCtrl = reinterpret_cast(registers.getLocalAddr(registerStatusCtrlOffset)); - registerFrameSize = reinterpret_cast(registers.getLocalAddr(registerFrameSizeOffset)); - registerFrames = reinterpret_cast(registers.getLocalAddr(registerFrameOffset)); + registerStatus = reinterpret_cast( + registers.getLocalAddr(registerStatusOffset)); + registerStatusCtrl = reinterpret_cast( + registers.getLocalAddr(registerStatusCtrlOffset)); + registerFrameSize = reinterpret_cast( + registers.getLocalAddr(registerFrameSizeOffset)); + registerFrames = + reinterpret_cast(registers.getLocalAddr(registerFrameOffset)); - maxFrameSize = getMaxFrameSize(); - logger->info("Max. frame size supported: {}", maxFrameSize); + maxFrameSize = getMaxFrameSize(); + logger->info("Max. frame size supported: {}", maxFrameSize); - return true; + return true; } -bool -Gpu2Rtds::startOnce(size_t frameSize) -{ - *registerFrameSize = frameSize; +bool Gpu2Rtds::startOnce(size_t frameSize) { + *registerFrameSize = frameSize; - start(); + start(); - return true; + return true; } -void Gpu2Rtds::dump(spdlog::level::level_enum logLevel) -{ - const auto frame_size = *registerFrameSize; - auto status = *registerStatus; +void Gpu2Rtds::dump(spdlog::level::level_enum logLevel) { + const auto frame_size = *registerFrameSize; + auto status = *registerStatus; - logger->log(logLevel, "Gpu2Rtds registers:"); - logger->log(logLevel, " Frame size (words): {:#x}", frame_size); - logger->log(logLevel, " Status: {:#x}", status.value); - logger->log(logLevel, " Running: {}", (status.is_running ? "yes" : "no")); - logger->log(logLevel, " Frame too short: {}", (status.frame_too_short ? "yes" : "no")); - logger->log(logLevel, " Frame too long: {}", (status.frame_too_long ? "yes" : "no")); - logger->log(logLevel, " Frame size invalid: {}", (status.invalid_frame_size ? "yes" : "no")); - logger->log(logLevel, " Last count: {}", (int) status.last_count); - logger->log(logLevel, " Last seq. number: {}", (int) status.last_seq_nr); - logger->log(logLevel, " Max. frame size: {}", (int) status.max_frame_size); + logger->log(logLevel, "Gpu2Rtds registers:"); + logger->log(logLevel, " Frame size (words): {:#x}", frame_size); + logger->log(logLevel, " Status: {:#x}", status.value); + logger->log(logLevel, " Running: {}", + (status.is_running ? "yes" : "no")); + logger->log(logLevel, " Frame too short: {}", + (status.frame_too_short ? "yes" : "no")); + logger->log(logLevel, " Frame too long: {}", + (status.frame_too_long ? "yes" : "no")); + logger->log(logLevel, " Frame size invalid: {}", + (status.invalid_frame_size ? "yes" : "no")); + logger->log(logLevel, " Last count: {}", (int)status.last_count); + logger->log(logLevel, " Last seq. number: {}", (int)status.last_seq_nr); + logger->log(logLevel, " Max. frame size: {}", + (int)status.max_frame_size); } //bool Gpu2Rtds::startOnce(const MemoryBlock &mem, size_t frameSize, size_t dataOffset, size_t doorbellOffset) @@ -99,24 +104,24 @@ void Gpu2Rtds::dump(spdlog::level::level_enum logLevel) // return true; //} -size_t -Gpu2Rtds::getMaxFrameSize() -{ - *registerFrameSize = 0; +size_t Gpu2Rtds::getMaxFrameSize() { + *registerFrameSize = 0; - start(); - while (not isFinished()); + start(); + while (not isFinished()) + ; - while (not registerStatusCtrl->status_ap_vld); + while (not registerStatusCtrl->status_ap_vld) + ; - axilite_reg_status_t status = *registerStatus; + axilite_reg_status_t status = *registerStatus; -// logger->debug("(*registerStatus).max_frame_size: {}", (*registerStatus).max_frame_size); -// logger->debug("status.max_frame_size: {}", status.max_frame_size); + // logger->debug("(*registerStatus).max_frame_size: {}", (*registerStatus).max_frame_size); + // logger->debug("status.max_frame_size: {}", status.max_frame_size); -// assert(status.max_frame_size == (*registerStatus).max_frame_size); + // assert(status.max_frame_size == (*registerStatus).max_frame_size); - return status.max_frame_size; + return status.max_frame_size; } //void diff --git a/fpga/lib/ips/rtds2gpu/rtds2gpu.cpp b/fpga/lib/ips/rtds2gpu/rtds2gpu.cpp index 4c6acab20..7efb9c150 100644 --- a/fpga/lib/ips/rtds2gpu/rtds2gpu.cpp +++ b/fpga/lib/ips/rtds2gpu/rtds2gpu.cpp @@ -5,113 +5,116 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include +#include #include #include -#include using namespace villas::fpga::ip; -bool Rtds2Gpu::init() -{ - Hls::init(); +bool Rtds2Gpu::init() { + Hls::init(); - xInstance.IsReady = XIL_COMPONENT_IS_READY; - xInstance.Ctrl_BaseAddress = getBaseAddr(registerMemory); + xInstance.IsReady = XIL_COMPONENT_IS_READY; + xInstance.Ctrl_BaseAddress = getBaseAddr(registerMemory); - status.value = 0; - started = false; + status.value = 0; + started = false; -// maxFrameSize = getMaxFrameSize(); - maxFrameSize = 16; - logger->info("Max. frame size supported: {}", maxFrameSize); + // maxFrameSize = getMaxFrameSize(); + maxFrameSize = 16; + logger->info("Max. frame size supported: {}", maxFrameSize); - return true; + return true; } -void Rtds2Gpu::dump(spdlog::level::level_enum logLevel) -{ - 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); +void Rtds2Gpu::dump(spdlog::level::level_enum logLevel) { + 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); - logger->log(logLevel, "Rtds2Gpu registers (IP base {:#x}):", xInstance.Ctrl_BaseAddress); - logger->log(logLevel, " Base address (bytes): {:#x}", baseaddr); - logger->log(logLevel, " Doorbell offset (bytes): {:#x}", doorbell_offset); - logger->log(logLevel, " Data offset (bytes): {:#x}", data_offset); - logger->log(logLevel, " Frame size (words): {:#x}", frame_size); - logger->log(logLevel, " Status: {:#x}", status.value); - logger->log(logLevel, " Running: {}", (status.is_running ? "yes" : "no")); - logger->log(logLevel, " Frame too short: {}", (status.frame_too_short ? "yes" : "no")); - logger->log(logLevel, " Frame too long: {}", (status.frame_too_long ? "yes" : "no")); - logger->log(logLevel, " Frame size invalid: {}", (status.invalid_frame_size ? "yes" : "no")); - logger->log(logLevel, " Last count: {}", (int) status.last_count); - logger->log(logLevel, " Last seq. number: {}", (int) status.last_seq_nr); - logger->log(logLevel, " Max. frame size: {}", (int) status.max_frame_size); + logger->log(logLevel, "Rtds2Gpu registers (IP base {:#x}):", + xInstance.Ctrl_BaseAddress); + logger->log(logLevel, " Base address (bytes): {:#x}", baseaddr); + logger->log(logLevel, " Doorbell offset (bytes): {:#x}", doorbell_offset); + logger->log(logLevel, " Data offset (bytes): {:#x}", data_offset); + logger->log(logLevel, " Frame size (words): {:#x}", frame_size); + logger->log(logLevel, " Status: {:#x}", status.value); + logger->log(logLevel, " Running: {}", + (status.is_running ? "yes" : "no")); + logger->log(logLevel, " Frame too short: {}", + (status.frame_too_short ? "yes" : "no")); + logger->log(logLevel, " Frame too long: {}", + (status.frame_too_long ? "yes" : "no")); + logger->log(logLevel, " Frame size invalid: {}", + (status.invalid_frame_size ? "yes" : "no")); + logger->log(logLevel, " Last count: {}", (int)status.last_count); + logger->log(logLevel, " Last seq. number: {}", (int)status.last_seq_nr); + logger->log(logLevel, " Max. frame size: {}", + (int)status.max_frame_size); } -bool Rtds2Gpu::startOnce(const MemoryBlock &mem, size_t frameSize, size_t dataOffset, size_t doorbellOffset) -{ - auto &mm = MemoryManager::get(); +bool Rtds2Gpu::startOnce(const MemoryBlock &mem, size_t frameSize, + size_t dataOffset, size_t doorbellOffset) { + auto &mm = MemoryManager::get(); - if (frameSize > maxFrameSize) { - logger->error("Requested frame size of {} exceeds max. frame size of {}", - frameSize, maxFrameSize); - return false; - } + if (frameSize > maxFrameSize) { + logger->error("Requested frame size of {} exceeds max. frame size of {}", + frameSize, maxFrameSize); + return false; + } - auto translationFromIp = mm.getTranslation( - getMasterAddrSpaceByInterface(axiInterface), - mem.getAddrSpaceId()); + auto translationFromIp = mm.getTranslation( + getMasterAddrSpaceByInterface(axiInterface), mem.getAddrSpaceId()); - // Set address of memory block in HLS IP - XRtds2gpu_Set_baseaddr(&xInstance, translationFromIp.getLocalAddr(0)); + // Set address of memory block in HLS IP + XRtds2gpu_Set_baseaddr(&xInstance, translationFromIp.getLocalAddr(0)); - XRtds2gpu_Set_doorbell_offset(&xInstance, doorbellOffset); - XRtds2gpu_Set_data_offset(&xInstance, dataOffset); - XRtds2gpu_Set_frame_size(&xInstance, frameSize); + XRtds2gpu_Set_doorbell_offset(&xInstance, doorbellOffset); + XRtds2gpu_Set_data_offset(&xInstance, dataOffset); + 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()); + // 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 - return start(); + // Start IP + return start(); } -bool Rtds2Gpu::updateStatus() -{ - if (not XRtds2gpu_Get_status_vld(&xInstance)) - return false; +bool Rtds2Gpu::updateStatus() { + if (not XRtds2gpu_Get_status_vld(&xInstance)) + return false; - status.value = XRtds2gpu_Get_status(&xInstance); + status.value = XRtds2gpu_Get_status(&xInstance); - return true; + return true; } -size_t Rtds2Gpu::getMaxFrameSize() -{ - XRtds2gpu_Set_frame_size(&xInstance, 0); +size_t Rtds2Gpu::getMaxFrameSize() { + XRtds2gpu_Set_frame_size(&xInstance, 0); - start(); - while (not isFinished()); - updateStatus(); + start(); + while (not isFinished()) + ; + updateStatus(); - return status.max_frame_size; + return status.max_frame_size; } -void Rtds2Gpu::dumpDoorbell(uint32_t doorbellRegister) const -{ - auto &doorbell = reinterpret_cast(doorbellRegister); +void Rtds2Gpu::dumpDoorbell(uint32_t doorbellRegister) const { + auto &doorbell = reinterpret_cast(doorbellRegister); - logger->info("Doorbell register: {:#08x}", doorbell.value); - logger->info(" Valid: {}", doorbell.is_valid ? "yes" : "no"); - logger->info(" Count: {}", (int) doorbell.count); - logger->info(" Seq. number: {}", (int) doorbell.seq_nr); + logger->info("Doorbell register: {:#08x}", doorbell.value); + logger->info(" Valid: {}", doorbell.is_valid ? "yes" : "no"); + logger->info(" Count: {}", (int)doorbell.count); + logger->info(" Seq. number: {}", (int)doorbell.seq_nr); } static char n[] = "Rtds2Gpu"; diff --git a/fpga/lib/ips/rtds2gpu/xrtds2gpu.c b/fpga/lib/ips/rtds2gpu/xrtds2gpu.c index fe4dbeb32..475c15b30 100644 --- a/fpga/lib/ips/rtds2gpu/xrtds2gpu.c +++ b/fpga/lib/ips/rtds2gpu/xrtds2gpu.c @@ -10,212 +10,237 @@ /************************** Function Implementation *************************/ #ifndef __linux__ -int XRtds2gpu_CfgInitialize(XRtds2gpu *InstancePtr, XRtds2gpu_Config *ConfigPtr) { - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(ConfigPtr != NULL); +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; + InstancePtr->Ctrl_BaseAddress = ConfigPtr->Ctrl_BaseAddress; + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; - return XST_SUCCESS; + return XST_SUCCESS; } #endif void XRtds2gpu_Start(XRtds2gpu *InstancePtr) { - u32 Data; + u32 Data; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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); + 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; + u32 Data; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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; + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, + XRTDS2GPU_CTRL_ADDR_AP_CTRL); + return (Data >> 1) & 0x1; } u32 XRtds2gpu_IsIdle(XRtds2gpu *InstancePtr) { - u32 Data; + u32 Data; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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; + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, + XRTDS2GPU_CTRL_ADDR_AP_CTRL); + return (Data >> 2) & 0x1; } u32 XRtds2gpu_IsReady(XRtds2gpu *InstancePtr) { - u32 Data; + u32 Data; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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); + 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); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_AP_CTRL, 0x80); + 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); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_AP_CTRL, 0); + 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); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_BASEADDR_DATA, Data); + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, + XRTDS2GPU_CTRL_ADDR_BASEADDR_DATA, Data); } u32 XRtds2gpu_Get_baseaddr(XRtds2gpu *InstancePtr) { - u32 Data; + u32 Data; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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; + 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); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_DATA_OFFSET_DATA, Data); + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, + XRTDS2GPU_CTRL_ADDR_DATA_OFFSET_DATA, Data); } u32 XRtds2gpu_Get_data_offset(XRtds2gpu *InstancePtr) { - u32 Data; + u32 Data; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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; + 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); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_DOORBELL_OFFSET_DATA, Data); + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, + XRTDS2GPU_CTRL_ADDR_DOORBELL_OFFSET_DATA, Data); } u32 XRtds2gpu_Get_doorbell_offset(XRtds2gpu *InstancePtr) { - u32 Data; + u32 Data; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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; + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, + XRTDS2GPU_CTRL_ADDR_DOORBELL_OFFSET_DATA); + return Data; } void XRtds2gpu_Set_frame_size(XRtds2gpu *InstancePtr, u32 Data) { - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_FRAME_SIZE_DATA, Data); + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, + XRTDS2GPU_CTRL_ADDR_FRAME_SIZE_DATA, Data); } u32 XRtds2gpu_Get_frame_size(XRtds2gpu *InstancePtr) { - u32 Data; + u32 Data; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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; + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, + XRTDS2GPU_CTRL_ADDR_FRAME_SIZE_DATA); + return Data; } u32 XRtds2gpu_Get_status(XRtds2gpu *InstancePtr) { - u32 Data; + u32 Data; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_STATUS_DATA); - return Data; + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, + XRTDS2GPU_CTRL_ADDR_STATUS_DATA); + return Data; } u32 XRtds2gpu_Get_status_vld(XRtds2gpu *InstancePtr) { - u32 Data; + u32 Data; - Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_STATUS_CTRL); - return Data & 0x1; + Data = XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, + XRTDS2GPU_CTRL_ADDR_STATUS_CTRL); + return Data & 0x1; } void XRtds2gpu_InterruptGlobalEnable(XRtds2gpu *InstancePtr) { - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_GIE, 1); + 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); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_GIE, 0); + XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_GIE, 0); } void XRtds2gpu_InterruptEnable(XRtds2gpu *InstancePtr, u32 Mask) { - u32 Register; + u32 Register; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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); + 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; + u32 Register; - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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)); + 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); + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - XRtds2gpu_WriteReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_ISR, Mask); + 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); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - return XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_IER); + 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); + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); - return XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, XRTDS2GPU_CTRL_ADDR_ISR); + return XRtds2gpu_ReadReg(InstancePtr->Ctrl_BaseAddress, + XRTDS2GPU_CTRL_ADDR_ISR); } - diff --git a/fpga/lib/ips/switch.cpp b/fpga/lib/ips/switch.cpp index 7a6031fb6..6f8e232ab 100644 --- a/fpga/lib/ips/switch.cpp +++ b/fpga/lib/ips/switch.cpp @@ -18,33 +18,33 @@ namespace villas { namespace fpga { namespace ip { -bool AxiStreamSwitch::init() -{ - if (XAxisScr_CfgInitialize(&xSwitch, &xConfig, getBaseAddr(registerMemory)) != XST_SUCCESS) { - logger->error("Cannot initialize switch"); - return false; - } +bool AxiStreamSwitch::init() { + if (XAxisScr_CfgInitialize(&xSwitch, &xConfig, getBaseAddr(registerMemory)) != + XST_SUCCESS) { + logger->error("Cannot initialize switch"); + return false; + } - // Disable all masters - XAxisScr_RegUpdateDisable(&xSwitch); - XAxisScr_MiPortDisableAll(&xSwitch); - XAxisScr_RegUpdateEnable(&xSwitch); + // Disable all masters + XAxisScr_RegUpdateDisable(&xSwitch); + XAxisScr_MiPortDisableAll(&xSwitch); + XAxisScr_RegUpdateEnable(&xSwitch); - for (auto& [masterName, masterPort] : portsMaster) { + for (auto &[masterName, masterPort] : portsMaster) { - // Initialize internal mapping - portMapping[masterName] = PORT_DISABLED; + // Initialize internal mapping + portMapping[masterName] = PORT_DISABLED; - // Each slave port may be internally routed to a master port - for (auto& [slaveName, slavePort] : portsSlave) { - (void) slaveName; + // Each slave port may be internally routed to a master port + for (auto &[slaveName, slavePort] : portsSlave) { + (void)slaveName; - streamGraph.addDefaultEdge(slavePort->getIdentifier(), - masterPort->getIdentifier()); - } - } + streamGraph.addDefaultEdge(slavePort->getIdentifier(), + masterPort->getIdentifier()); + } + } - return true; + return true; } void AxiStreamSwitch::printConfig() const { @@ -73,89 +73,83 @@ void AxiStreamSwitch::printConfig() const { } bool AxiStreamSwitch::connectInternal(const std::string &portSlave, - const std::string &portMaster) -{ - // Check if slave port exists - try { - getSlavePort(portSlave); - } catch (const std::out_of_range&) { - logger->error("Switch doesn't have a slave port named '{}'", portSlave); - return false; - } + const std::string &portMaster) { + // Check if slave port exists + try { + getSlavePort(portSlave); + } catch (const std::out_of_range &) { + logger->error("Switch doesn't have a slave port named '{}'", portSlave); + return false; + } - // Check if master port exists - try { - getMasterPort(portMaster); - } catch (const std::out_of_range&) { - logger->error("Switch doesn't have a master port named '{}'", portMaster); - return false; - } + // Check if master port exists + try { + getMasterPort(portMaster); + } catch (const std::out_of_range &) { + logger->error("Switch doesn't have a master port named '{}'", portMaster); + return false; + } - if (portSlave.substr(0, 1) != "S" or - portMaster.substr(0, 1) != "M") { - logger->error("sanity check failed: master {} slave {}", - portMaster, portSlave); - return false; - } + if (portSlave.substr(0, 1) != "S" or portMaster.substr(0, 1) != "M") { + logger->error("sanity check failed: master {} slave {}", portMaster, + portSlave); + return false; + } - if (portMapping[portMaster] == portSlave) { - logger->debug("Ports already connected (slave {} to master {}", - portSlave, portMaster); - return true; - } + if (portMapping[portMaster] == portSlave) { + logger->debug("Ports already connected (slave {} to master {}", portSlave, + portMaster); + return true; + } - for (auto [master, slave] : portMapping) { - if (slave == portSlave) { - logger->warn("Slave {} has already been connected to master {}. " - "Disabling master {}.", - slave, master, master); + for (auto [master, slave] : portMapping) { + if (slave == portSlave) { + logger->warn("Slave {} has already been connected to master {}. " + "Disabling master {}.", + slave, master, master); - XAxisScr_RegUpdateDisable(&xSwitch); - XAxisScr_MiPortDisable(&xSwitch, portNameToNum(master)); - XAxisScr_RegUpdateEnable(&xSwitch); + XAxisScr_RegUpdateDisable(&xSwitch); + XAxisScr_MiPortDisable(&xSwitch, portNameToNum(master)); + XAxisScr_RegUpdateEnable(&xSwitch); - portMapping[master] = PORT_DISABLED; - } - } + portMapping[master] = PORT_DISABLED; + } + } - // Reconfigure switch - XAxisScr_RegUpdateDisable(&xSwitch); - XAxisScr_MiPortEnable(&xSwitch, portNameToNum(portMaster), portNameToNum(portSlave)); - XAxisScr_RegUpdateEnable(&xSwitch); + // Reconfigure switch + XAxisScr_RegUpdateDisable(&xSwitch); + XAxisScr_MiPortEnable(&xSwitch, portNameToNum(portMaster), + portNameToNum(portSlave)); + XAxisScr_RegUpdateEnable(&xSwitch); - portMapping[portMaster] = portSlave; + portMapping[portMaster] = portSlave; - logger->debug("Connect slave {} to master {}", portSlave, portMaster); + logger->debug("Connect slave {} to master {}", portSlave, portMaster); - return true; + return true; } -int AxiStreamSwitch::portNameToNum(const std::string &portName) -{ - const std::string number = portName.substr(1, 2); - return std::stoi(number); +int AxiStreamSwitch::portNameToNum(const std::string &portName) { + const std::string number = portName.substr(1, 2); + return std::stoi(number); } -void AxiStreamSwitchFactory::parse(Core &ip, json_t *cfg) -{ - NodeFactory::parse(ip, cfg); +void AxiStreamSwitchFactory::parse(Core &ip, json_t *cfg) { + NodeFactory::parse(ip, cfg); - auto logger = getLogger(); + auto logger = getLogger(); - auto &axiSwitch = dynamic_cast(ip); + auto &axiSwitch = dynamic_cast(ip); - int num_si, num_mi; - json_error_t err; - auto ret = json_unpack_ex(cfg, &err, 0, "{ s: { s: i, s: i } }", - "parameters", - "num_si", &num_si, - "num_mi", &num_mi - ); - if (ret != 0) - throw ConfigError(cfg, err, "", "Cannot parse switch config"); + int num_si, num_mi; + json_error_t err; + auto ret = json_unpack_ex(cfg, &err, 0, "{ s: { s: i, s: i } }", "parameters", + "num_si", &num_si, "num_mi", &num_mi); + if (ret != 0) + throw ConfigError(cfg, err, "", "Cannot parse switch config"); - axiSwitch.xConfig.MaxNumMI = num_mi; - axiSwitch.xConfig.MaxNumSI = num_si; + axiSwitch.xConfig.MaxNumMI = num_mi; + axiSwitch.xConfig.MaxNumSI = num_si; } static AxiStreamSwitchFactory f; diff --git a/fpga/lib/ips/timer.cpp b/fpga/lib/ips/timer.cpp index bbccc92d7..0af2e73a5 100644 --- a/fpga/lib/ips/timer.cpp +++ b/fpga/lib/ips/timer.cpp @@ -12,53 +12,47 @@ #include -#include #include +#include using namespace villas::fpga::ip; -bool Timer::init() -{ - XTmrCtr_Config xtmr_cfg; - xtmr_cfg.SysClockFreqHz = getFrequency(); +bool Timer::init() { + XTmrCtr_Config xtmr_cfg; + xtmr_cfg.SysClockFreqHz = getFrequency(); - XTmrCtr_CfgInitialize(&xTmr, &xtmr_cfg, getBaseAddr(registerMemory)); - XTmrCtr_InitHw(&xTmr); + XTmrCtr_CfgInitialize(&xTmr, &xtmr_cfg, getBaseAddr(registerMemory)); + XTmrCtr_InitHw(&xTmr); - if (irqs.find(irqName) == irqs.end()) { - logger->error("IRQ '{}' not found but required", irqName); - return false; - } + if (irqs.find(irqName) == irqs.end()) { + logger->error("IRQ '{}' not found but required", irqName); + return false; + } - // Disable so we don't receive any stray interrupts - irqs[irqName].irqController->disableInterrupt(irqs[irqName]); + // Disable so we don't receive any stray interrupts + irqs[irqName].irqController->disableInterrupt(irqs[irqName]); - return true; + return true; } -bool Timer::start(uint32_t ticks) -{ - irqs[irqName].irqController->enableInterrupt(irqs[irqName], false); +bool Timer::start(uint32_t ticks) { + irqs[irqName].irqController->enableInterrupt(irqs[irqName], false); - XTmrCtr_SetOptions(&xTmr, 0, XTC_EXT_COMPARE_OPTION | XTC_DOWN_COUNT_OPTION); - XTmrCtr_SetResetValue(&xTmr, 0, ticks); - XTmrCtr_Start(&xTmr, 0); + XTmrCtr_SetOptions(&xTmr, 0, XTC_EXT_COMPARE_OPTION | XTC_DOWN_COUNT_OPTION); + XTmrCtr_SetResetValue(&xTmr, 0, ticks); + XTmrCtr_Start(&xTmr, 0); - return true; + return true; } -bool Timer::wait() -{ - int count = irqs[irqName].irqController->waitForInterrupt(irqs[irqName]); - irqs[irqName].irqController->disableInterrupt(irqs[irqName]); +bool Timer::wait() { + int count = irqs[irqName].irqController->waitForInterrupt(irqs[irqName]); + irqs[irqName].irqController->disableInterrupt(irqs[irqName]); - return (count == 1); + return (count == 1); } -uint32_t Timer::remaining() -{ - return XTmrCtr_GetValue(&xTmr, 0); -} +uint32_t Timer::remaining() { return XTmrCtr_GetValue(&xTmr, 0); } static char n[] = "timer"; static char d[] = "Xilinx's programmable timer / counter"; diff --git a/fpga/lib/memory.cpp b/fpga/lib/memory.cpp index 1970e113f..3a213a158 100644 --- a/fpga/lib/memory.cpp +++ b/fpga/lib/memory.cpp @@ -12,17 +12,13 @@ using namespace villas; -bool -HostRam::free(void* addr, size_t length) -{ - return munmap(addr, length) == 0; +bool HostRam::free(void *addr, size_t length) { + return munmap(addr, length) == 0; } -void* -HostRam::allocate(size_t length, int flags) -{ - const int mmap_flags = flags | MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT; - const int mmap_protection = PROT_READ | PROT_WRITE; +void *HostRam::allocate(size_t length, int flags) { + const int mmap_flags = flags | MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT; + const int mmap_protection = PROT_READ | PROT_WRITE; - return mmap(nullptr, length, mmap_protection, mmap_flags, 0, 0); + return mmap(nullptr, length, mmap_protection, mmap_flags, 0, 0); } diff --git a/fpga/lib/pcie_card.cpp b/fpga/lib/pcie_card.cpp index fdc078c76..2e84f8b95 100644 --- a/fpga/lib/pcie_card.cpp +++ b/fpga/lib/pcie_card.cpp @@ -5,17 +5,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include #include +#include +#include +#include #include -#include -#include -#include #include #include #include +#include +#include +#include using namespace villas; using namespace villas::fpga; @@ -23,7 +23,8 @@ using namespace villas::fpga; // Instantiate factory to register static PCIeCardFactory PCIeCardFactoryInstance; -static const kernel::pci::Device defaultFilter((kernel::pci::Id(FPGA_PCI_VID_XILINX, FPGA_PCI_PID_VFPGA))); +static const kernel::pci::Device + defaultFilter((kernel::pci::Id(FPGA_PCI_VID_XILINX, FPGA_PCI_PID_VFPGA))); std::shared_ptr PCIeCardFactory::make(json_t *json_card, std::string card_name, @@ -155,39 +156,35 @@ PCIeCardFactory::make(json_t *json_card, std::string card_name, return card; } -PCIeCard::~PCIeCard() -{ +PCIeCard::~PCIeCard() {} -} - -bool PCIeCard::init() -{ - logger = getLogger(); - - logger->info("Initializing FPGA card {}", name); - - // Attach PCIe card to VFIO container - vfioDevice = vfioContainer->attachDevice(*pdev); - - // Enable memory access and PCI bus mastering for DMA - if (not vfioDevice->pciEnable()) { - logger->error("Failed to enable PCI device"); - return false; - } - - // Reset system? - if (doReset) { - // Reset / detect PCI device - if (not vfioDevice->pciHotReset()) { - logger->error("Failed to reset PCI device"); - return false; - } - - if (not reset()) { - logger->error("Failed to reset FGPA card"); - return false; - } - } - - return true; +bool PCIeCard::init() { + logger = getLogger(); + + logger->info("Initializing FPGA card {}", name); + + // Attach PCIe card to VFIO container + vfioDevice = vfioContainer->attachDevice(*pdev); + + // Enable memory access and PCI bus mastering for DMA + if (not vfioDevice->pciEnable()) { + logger->error("Failed to enable PCI device"); + return false; + } + + // Reset system? + if (doReset) { + // Reset / detect PCI device + if (not vfioDevice->pciHotReset()) { + logger->error("Failed to reset PCI device"); + return false; + } + + if (not reset()) { + logger->error("Failed to reset FGPA card"); + return false; + } + } + + return true; } diff --git a/fpga/lib/utils.cpp b/fpga/lib/utils.cpp index 70af11bbc..efee49621 100644 --- a/fpga/lib/utils.cpp +++ b/fpga/lib/utils.cpp @@ -6,14 +6,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include #include +#include +#include +#include #include #include -#include +#include +#include #include #include @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -61,8 +60,7 @@ fpga::ConnectString::ConnectString(std::string &connectString, int maxPortNum) parseString(connectString); } -void fpga::ConnectString::parseString(std::string& connectString) -{ +void fpga::ConnectString::parseString(std::string &connectString) { if (connectString.empty()) return; @@ -119,8 +117,7 @@ void fpga::ConnectString::parseString(std::string& connectString) } } -int fpga::ConnectString::portStringToInt(std::string &str) const -{ +int fpga::ConnectString::portStringToInt(std::string &str) const { if (str == "stdin" || str == "stdout" || str == "pipe" || str == "dma" || str == "dino") { return -1; @@ -134,7 +131,6 @@ int fpga::ConnectString::portStringToInt(std::string &str) const } } - // parses a string like "1->2" or "1<->stdout" and configures the crossbar accordingly void fpga::ConnectString::configCrossBar( std::shared_ptr card) const { @@ -205,24 +201,23 @@ void fpga::ConnectString::configCrossBar( } } -void fpga::setupColorHandling() -{ - // Handle Control-C nicely - struct sigaction sigIntHandler; - sigIntHandler.sa_handler = [](int){ - std::cout << std::endl << rang::style::reset << rang::fgB::red; - std::cout << "Control-C detected, exiting..." << rang::style::reset << std::endl; - std::exit(1); // Will call the correct exit func, no unwinding of the stack though - }; +void fpga::setupColorHandling() { + // Handle Control-C nicely + struct sigaction sigIntHandler; + sigIntHandler.sa_handler = [](int) { + std::cout << std::endl << rang::style::reset << rang::fgB::red; + std::cout << "Control-C detected, exiting..." << rang::style::reset + << std::endl; + std::exit( + 1); // Will call the correct exit func, no unwinding of the stack though + }; - sigemptyset(&sigIntHandler.sa_mask); - sigIntHandler.sa_flags = 0; - sigaction(SIGINT, &sigIntHandler, nullptr); + sigemptyset(&sigIntHandler.sa_mask); + sigIntHandler.sa_flags = 0; + sigaction(SIGINT, &sigIntHandler, nullptr); - // Reset color if exiting not by signal - std::atexit([](){ - std::cout << rang::style::reset; - }); + // Reset color if exiting not by signal + std::atexit([]() { std::cout << rang::style::reset; }); } std::shared_ptr @@ -331,15 +326,16 @@ std::shared_ptr fpga::setupFpgaCard(const std::string &configFile, return card; } -std::unique_ptr fpga::getBufferedSampleFormatter( - const std::string &format, - size_t bufSizeInSamples) -{ - if (format == "long") { - return std::make_unique(bufSizeInSamples); - } else if (format == "short") { - return std::make_unique(bufSizeInSamples); - } else { - throw RuntimeError("Unknown output format '{}'", format); - } +std::unique_ptr +fpga::getBufferedSampleFormatter(const std::string &format, + size_t bufSizeInSamples) { + if (format == "long") { + return std::make_unique( + bufSizeInSamples); + } else if (format == "short") { + return std::make_unique( + bufSizeInSamples); + } else { + throw RuntimeError("Unknown output format '{}'", format); + } } diff --git a/fpga/lib/vlnv.cpp b/fpga/lib/vlnv.cpp index a656e7fd3..ae16d5298 100644 --- a/fpga/lib/vlnv.cpp +++ b/fpga/lib/vlnv.cpp @@ -5,56 +5,53 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include #include using namespace villas::fpga; -bool -Vlnv::operator==(const Vlnv &other) const -{ - // If a field is empty, it means wildcard matching everything - const bool vendorWildcard = vendor.empty() or other.vendor.empty(); - const bool libraryWildcard = library.empty() or other.library.empty(); - const bool nameWildcard = name.empty() or other.name.empty(); - const bool versionWildcard = version.empty() or other.version.empty(); +bool Vlnv::operator==(const Vlnv &other) const { + // If a field is empty, it means wildcard matching everything + const bool vendorWildcard = vendor.empty() or other.vendor.empty(); + const bool libraryWildcard = library.empty() or other.library.empty(); + const bool nameWildcard = name.empty() or other.name.empty(); + const bool versionWildcard = version.empty() or other.version.empty(); - const bool vendorMatch = vendorWildcard or vendor == other.vendor; - const bool libraryMatch = libraryWildcard or library == other.library; - const bool nameMatch = nameWildcard or name == other.name; - const bool versionMatch = versionWildcard or version == other.version; + const bool vendorMatch = vendorWildcard or vendor == other.vendor; + const bool libraryMatch = libraryWildcard or library == other.library; + const bool nameMatch = nameWildcard or name == other.name; + const bool versionMatch = versionWildcard or version == other.version; - return vendorMatch and libraryMatch and nameMatch and versionMatch; + return vendorMatch and libraryMatch and nameMatch and versionMatch; } -void -Vlnv::parseFromString(std::string vlnv) -{ - // Tokenize by delimiter - std::stringstream sstream(vlnv); - std::getline(sstream, vendor, delimiter); - std::getline(sstream, library, delimiter); - std::getline(sstream, name, delimiter); - std::getline(sstream, version, delimiter); +void Vlnv::parseFromString(std::string vlnv) { + // Tokenize by delimiter + std::stringstream sstream(vlnv); + std::getline(sstream, vendor, delimiter); + std::getline(sstream, library, delimiter); + std::getline(sstream, name, delimiter); + std::getline(sstream, version, delimiter); - // Represent wildcard internally as empty string - if (vendor == "*") vendor = ""; - if (library == "*") library = ""; - if (name == "*") name = ""; - if (version == "*") version = ""; + // Represent wildcard internally as empty string + if (vendor == "*") + vendor = ""; + if (library == "*") + library = ""; + if (name == "*") + name = ""; + if (version == "*") + version = ""; } -std::string -Vlnv::toString() const -{ - std::stringstream stream; - std::string string; +std::string Vlnv::toString() const { + std::stringstream stream; + std::string string; - stream << *this; - stream >> string; + stream << *this; + stream >> string; - return string; + return string; } - diff --git a/fpga/src/pcimem.c b/fpga/src/pcimem.c index 56199acc8..5e5e11c9e 100644 --- a/fpga/src/pcimem.c +++ b/fpga/src/pcimem.c @@ -9,121 +9,124 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ +#include +#include +#include +#include +#include #include #include -#include -#include #include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include -#define PRINT_ERROR \ - do { \ - fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \ - __LINE__, __FILE__, errno, strerror(errno)); exit(1); \ - } while (0) +#define PRINT_ERROR \ + do { \ + fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", __LINE__, \ + __FILE__, errno, strerror(errno)); \ + exit(1); \ + } while (0) #define MAP_SIZE 4096UL #define MAP_MASK (MAP_SIZE - 1) int main(int argc, char **argv) { - int fd; - void *map_base, *virt_addr; - unsigned read_result, writeval; - char *filename; - off_t target; - int access_type = 'w'; + int fd; + void *map_base, *virt_addr; + unsigned read_result, writeval; + char *filename; + off_t target; + int access_type = 'w'; - if (argc < 3) { - // pcimem /sys/bus/pci/devices/0001\:00\:07.0/resource0 0x100 w 0x00 - // argv[0] [1] [2] [3] [4] - fprintf(stderr, "\nUsage:\t%s { sys file } { offset } [ type [ data ] ]\n" - "\tsys file: sysfs file for the pci resource to act on\n" - "\toffset : offset into pci memory region to act upon\n" - "\ttype : access operation type : [b]yte, [h]alfword, [w]ord\n" - "\tdata : data to be written\n\n", - argv[0]); - exit(1); - } + if (argc < 3) { + // pcimem /sys/bus/pci/devices/0001\:00\:07.0/resource0 0x100 w 0x00 + // argv[0] [1] [2] [3] [4] + fprintf(stderr, + "\nUsage:\t%s { sys file } { offset } [ type [ data ] ]\n" + "\tsys file: sysfs file for the pci resource to act on\n" + "\toffset : offset into pci memory region to act upon\n" + "\ttype : access operation type : [b]yte, [h]alfword, [w]ord\n" + "\tdata : data to be written\n\n", + argv[0]); + exit(1); + } - filename = argv[1]; - target = strtoul(argv[2], 0, 0); + filename = argv[1]; + target = strtoul(argv[2], 0, 0); - if (argc > 3) - access_type = tolower(argv[3][0]); + if (argc > 3) + access_type = tolower(argv[3][0]); - fd = open(filename, O_RDWR | O_SYNC); - if (fd < 0) - PRINT_ERROR; + fd = open(filename, O_RDWR | O_SYNC); + if (fd < 0) + PRINT_ERROR; - printf("%s opened.\n", filename); - printf("Target offset is %#jx, page size is %lu\n", (uintmax_t) target, sysconf(_SC_PAGE_SIZE)); + printf("%s opened.\n", filename); + printf("Target offset is %#jx, page size is %lu\n", (uintmax_t)target, + sysconf(_SC_PAGE_SIZE)); - fflush(stdout); + fflush(stdout); - // Map one page - printf("mmap(%d, %lu, %#x, %#x, %d, %#jx)\n", 0, - MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, - fd, (uintmax_t) target); + // Map one page + printf("mmap(%d, %lu, %#x, %#x, %d, %#jx)\n", 0, MAP_SIZE, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, (uintmax_t)target); - map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK); + map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, + target & ~MAP_MASK); - if (map_base == (void *) -1) - PRINT_ERROR; + if (map_base == (void *)-1) + PRINT_ERROR; - printf("PCI Memory mapped to address %p.\n", map_base); - fflush(stdout); + printf("PCI Memory mapped to address %p.\n", map_base); + fflush(stdout); - virt_addr = (uint8_t*) map_base + (target & MAP_MASK); + virt_addr = (uint8_t *)map_base + (target & MAP_MASK); - switch(access_type) { - case 'b': - read_result = *((unsigned char *) virt_addr); - break; - case 'h': - read_result = *((unsigned short *) virt_addr); - break; - case 'w': - read_result = *((unsigned int *) virt_addr); - break; - default: - fprintf(stderr, "Illegal data type '%c'.\n", access_type); - exit(2); - } + switch (access_type) { + case 'b': + read_result = *((unsigned char *)virt_addr); + break; + case 'h': + read_result = *((unsigned short *)virt_addr); + break; + case 'w': + read_result = *((unsigned int *)virt_addr); + break; + default: + fprintf(stderr, "Illegal data type '%c'.\n", access_type); + exit(2); + } - printf("Value at offset %#jx (%p): %#x\n", (uintmax_t) target, virt_addr, read_result); - fflush(stdout); + printf("Value at offset %#jx (%p): %#x\n", (uintmax_t)target, virt_addr, + read_result); + fflush(stdout); - if (argc > 4) { - writeval = strtoul(argv[4], 0, 0); - switch(access_type) { - case 'b': - *((unsigned char *) virt_addr) = writeval; - read_result = *((unsigned char *) virt_addr); - break; - case 'h': - *((unsigned short *) virt_addr) = writeval; - read_result = *((unsigned short *) virt_addr); - break; - case 'w': - *((unsigned int *) virt_addr) = writeval; - read_result = *((unsigned int *) virt_addr); - break; - } - printf("Written %#x; readback %#x\n", writeval, read_result); - fflush(stdout); - } + if (argc > 4) { + writeval = strtoul(argv[4], 0, 0); + switch (access_type) { + case 'b': + *((unsigned char *)virt_addr) = writeval; + read_result = *((unsigned char *)virt_addr); + break; + case 'h': + *((unsigned short *)virt_addr) = writeval; + read_result = *((unsigned short *)virt_addr); + break; + case 'w': + *((unsigned int *)virt_addr) = writeval; + read_result = *((unsigned int *)virt_addr); + break; + } + printf("Written %#x; readback %#x\n", writeval, read_result); + fflush(stdout); + } - if (munmap(map_base, MAP_SIZE) == -1) - PRINT_ERROR; + if (munmap(map_base, MAP_SIZE) == -1) + PRINT_ERROR; - close(fd); + close(fd); - return 0; + return 0; } - diff --git a/fpga/src/villas-fpga-pipe.cpp b/fpga/src/villas-fpga-pipe.cpp index 4245dc5da..0e8543e19 100644 --- a/fpga/src/villas-fpga-pipe.cpp +++ b/fpga/src/villas-fpga-pipe.cpp @@ -5,12 +5,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include -#include -#include #include +#include +#include #include #include @@ -18,128 +18,131 @@ #include #include #include -#include -#include #include -#include +#include +#include #include #include -#include #include +#include using namespace villas; static std::shared_ptr pciDevices; static auto logger = villas::logging.get("streamer"); -int main(int argc, char* argv[]) -{ - // Command Line Parser - CLI::App app{"VILLASfpga data streamer"}; +int main(int argc, char *argv[]) { + // Command Line Parser + CLI::App app{"VILLASfpga data streamer"}; - try { - std::string configFile; - app.add_option("-c,--config", configFile, "Configuration file") - ->check(CLI::ExistingFile); + try { + std::string configFile; + app.add_option("-c,--config", configFile, "Configuration file") + ->check(CLI::ExistingFile); - std::string fpgaName = "vc707"; - app.add_option("--fpga", fpgaName, "Which FPGA to use"); - app.parse(argc, argv); + std::string fpgaName = "vc707"; + app.add_option("--fpga", fpgaName, "Which FPGA to use"); + app.parse(argc, argv); - // Logging setup - spdlog::set_level(spdlog::level::debug); - fpga::setupColorHandling(); + // Logging setup + spdlog::set_level(spdlog::level::debug); + fpga::setupColorHandling(); - if (configFile.empty()) { - logger->error("No configuration file provided/ Please use -c/--config argument"); - return 1; - } + if (configFile.empty()) { + logger->error( + "No configuration file provided/ Please use -c/--config argument"); + return 1; + } - auto card = fpga::setupFpgaCard(configFile, fpgaName); + auto card = fpga::setupFpgaCard(configFile, fpgaName); - std::vector> aurora_channels; - for (int i = 0; i < 4; i++) { - auto name = fmt::format("aurora_8b10b_ch{}", i); - auto id = fpga::ip::IpIdentifier("xilinx.com:ip:aurora_8b10b:", name); - auto aurora = std::dynamic_pointer_cast(card->lookupIp(id)); - if (aurora == nullptr) { - logger->error("No Aurora interface found on FPGA"); - return 1; - } + std::vector> aurora_channels; + for (int i = 0; i < 4; i++) { + auto name = fmt::format("aurora_8b10b_ch{}", i); + auto id = fpga::ip::IpIdentifier("xilinx.com:ip:aurora_8b10b:", name); + auto aurora = + std::dynamic_pointer_cast(card->lookupIp(id)); + if (aurora == nullptr) { + logger->error("No Aurora interface found on FPGA"); + return 1; + } - aurora_channels.push_back(aurora); - } + aurora_channels.push_back(aurora); + } - auto dma = std::dynamic_pointer_cast - (card->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:"))); - if (dma == nullptr) { - logger->error("No DMA found on FPGA "); - return 1; - } + auto dma = std::dynamic_pointer_cast( + card->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:"))); + if (dma == nullptr) { + logger->error("No DMA found on FPGA "); + return 1; + } - for (auto aurora : aurora_channels) - aurora->dump(); + for (auto aurora : aurora_channels) + aurora->dump(); - // Configure Crossbar switch + // Configure Crossbar switch #if 1 - aurora_channels[3]->connect(aurora_channels[3]->getDefaultMasterPort(), dma->getDefaultSlavePort()); - dma->connect(dma->getDefaultMasterPort(), aurora_channels[3]->getDefaultSlavePort()); + aurora_channels[3]->connect(aurora_channels[3]->getDefaultMasterPort(), + dma->getDefaultSlavePort()); + dma->connect(dma->getDefaultMasterPort(), + aurora_channels[3]->getDefaultSlavePort()); #else - dma->connectLoopback(); + dma->connectLoopback(); #endif - auto &alloc = villas::HostRam::getAllocator(); - const std::shared_ptr block[] = { - alloc.allocateBlock(0x200 * sizeof(uint32_t)), - alloc.allocateBlock(0x200 * sizeof(uint32_t)) - }; - villas::MemoryAccessor mem[] = {*block[0], *block[1]}; + auto &alloc = villas::HostRam::getAllocator(); + const std::shared_ptr block[] = { + alloc.allocateBlock(0x200 * sizeof(uint32_t)), + alloc.allocateBlock(0x200 * sizeof(uint32_t))}; + villas::MemoryAccessor mem[] = {*block[0], *block[1]}; - for (auto b : block) { - dma->makeAccesibleFromVA(b); - } - auto &mm = MemoryManager::get(); - mm.getGraph().dump("graph.dot"); + for (auto b : block) { + dma->makeAccesibleFromVA(b); + } + auto &mm = MemoryManager::get(); + mm.getGraph().dump("graph.dot"); - while (true) { - // Setup read transfer - dma->read(*block[0], block[0]->getSize()); + while (true) { + // Setup read transfer + dma->read(*block[0], block[0]->getSize()); - // Read values from stdin - std::string line; - std::getline(std::cin, line); - auto values = villas::utils::tokenize(line, ";"); + // Read values from stdin + std::string line; + std::getline(std::cin, line); + auto values = villas::utils::tokenize(line, ";"); - size_t i = 0; - for (auto &value: values) { - if (value.empty()) continue; + size_t i = 0; + for (auto &value : values) { + if (value.empty()) + continue; - const int32_t number = std::stoi(value); - mem[1][i++] = number; - } + const int32_t number = std::stoi(value); + mem[1][i++] = number; + } - // Initiate write transfer - bool state = dma->write(*block[1], i * sizeof(int32_t)); - if (!state) - logger->error("Failed to write to device"); + // Initiate write transfer + bool state = dma->write(*block[1], i * sizeof(int32_t)); + if (!state) + logger->error("Failed to write to device"); - auto writeComp = dma->writeComplete(); - logger->info("Wrote {} bytes", writeComp.bytes); + auto writeComp = dma->writeComplete(); + logger->info("Wrote {} bytes", writeComp.bytes); - auto readComp = dma->readComplete(); - auto valuesRead = readComp.bytes / sizeof(int32_t); - logger->info("Read {} bytes, {} bds, {} interrupts", readComp.bytes, readComp.bds, readComp.interrupts); + auto readComp = dma->readComplete(); + auto valuesRead = readComp.bytes / sizeof(int32_t); + logger->info("Read {} bytes, {} bds, {} interrupts", readComp.bytes, + readComp.bds, readComp.interrupts); - for (size_t i = 0; i < valuesRead; i++) - std::cerr << mem[0][i] << ";"; - std::cerr << std::endl; - } - } catch (const RuntimeError &e) { - logger->error("Error: {}", e.what()); - return -1; - } catch (const CLI::ParseError &e) { - return app.exit(e); - } + for (size_t i = 0; i < valuesRead; i++) + std::cerr << mem[0][i] << ";"; + std::cerr << std::endl; + } + } catch (const RuntimeError &e) { + logger->error("Error: {}", e.what()); + return -1; + } catch (const CLI::ParseError &e) { + return app.exit(e); + } - return 0; + return 0; } diff --git a/fpga/tests/unit/dma.c b/fpga/tests/unit/dma.c index 436bb5ddf..466a1ea2c 100644 --- a/fpga/tests/unit/dma.c +++ b/fpga/tests/unit/dma.c @@ -5,97 +5,96 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include #include +#include +#include #include -int main(int argc, char *argv[]) -{ - int ret; - villasfpga_handle vh; - villasfpga_memory mem1, mem2; - void *mem1ptr, *mem2ptr; - size_t size; +int main(int argc, char *argv[]) { + int ret; + villasfpga_handle vh; + villasfpga_memory mem1, mem2; + void *mem1ptr, *mem2ptr; + size_t size; - if (argv == NULL) { - return 1; - } - if (argc != 2 || argv[1] == NULL) { - fprintf(stderr, "Usage: %s \n", argv[0]); - } + if (argv == NULL) { + return 1; + } + if (argc != 2 || argv[1] == NULL) { + fprintf(stderr, "Usage: %s \n", argv[0]); + } - if ((vh = villasfpga_init(argv[1])) == NULL) { - fprintf(stderr, "Failed to initialize FPGA\n"); - ret = 1; - goto out; - } + if ((vh = villasfpga_init(argv[1])) == NULL) { + fprintf(stderr, "Failed to initialize FPGA\n"); + ret = 1; + goto out; + } - if (villasfpga_alloc(vh, &mem1, 0x200 * sizeof(uint32_t)) != 0) { - fprintf(stderr, "Failed to allocate DMA memory 1\n"); - ret = 1; - goto out; - } + if (villasfpga_alloc(vh, &mem1, 0x200 * sizeof(uint32_t)) != 0) { + fprintf(stderr, "Failed to allocate DMA memory 1\n"); + ret = 1; + goto out; + } - if (villasfpga_alloc(vh, &mem2, 0x200 * sizeof(uint32_t)) != 0) { - fprintf(stderr, "Failed to allocate DMA memory 2\n"); - ret = 1; - goto out; - } + if (villasfpga_alloc(vh, &mem2, 0x200 * sizeof(uint32_t)) != 0) { + fprintf(stderr, "Failed to allocate DMA memory 2\n"); + ret = 1; + goto out; + } - if ((mem1ptr = villasfpga_get_ptr(mem1)) == NULL) { - fprintf(stderr, "Failed to get pointer to DMA memory 1\n"); - ret = 1; - goto out; - } + if ((mem1ptr = villasfpga_get_ptr(mem1)) == NULL) { + fprintf(stderr, "Failed to get pointer to DMA memory 1\n"); + ret = 1; + goto out; + } - if ((mem2ptr = villasfpga_get_ptr(mem2)) == NULL) { - fprintf(stderr, "Failed to get pointer to DMA memory 2\n"); - ret = 1; - goto out; - } + if ((mem2ptr = villasfpga_get_ptr(mem2)) == NULL) { + fprintf(stderr, "Failed to get pointer to DMA memory 2\n"); + ret = 1; + goto out; + } - printf("DMA memory 1: %p, DMA memory 2: %p\n", mem1ptr, mem2ptr); + printf("DMA memory 1: %p, DMA memory 2: %p\n", mem1ptr, mem2ptr); - while (1) { - // Setup read transfer - if ((ret = villasfpga_read(vh, mem1, 0x200 * sizeof(uint32_t))) != 0) { - fprintf(stderr, "Failed to initiate read transfer\n"); - ret = 1; - goto out; - } + while (1) { + // Setup read transfer + if ((ret = villasfpga_read(vh, mem1, 0x200 * sizeof(uint32_t))) != 0) { + fprintf(stderr, "Failed to initiate read transfer\n"); + ret = 1; + goto out; + } - printf("Enter a float:\n"); - if ((ret = scanf("%f", (float*)mem2ptr)) != 1) { - fprintf(stderr, "Failed to parse input: sscanf returned %d\n", ret); - ret = 1; - goto out; - } - printf("sending %f (%zu bytes)\n", ((float*)mem2ptr)[0], sizeof(float)); - // Initiate write transfer - if ((ret = villasfpga_write(vh, mem2, sizeof(float))) != 0) { - fprintf(stderr, "Failed to initiate write transfer\n"); - ret = 1; - goto out; - } + printf("Enter a float:\n"); + if ((ret = scanf("%f", (float *)mem2ptr)) != 1) { + fprintf(stderr, "Failed to parse input: sscanf returned %d\n", ret); + ret = 1; + goto out; + } + printf("sending %f (%zu bytes)\n", ((float *)mem2ptr)[0], sizeof(float)); + // Initiate write transfer + if ((ret = villasfpga_write(vh, mem2, sizeof(float))) != 0) { + fprintf(stderr, "Failed to initiate write transfer\n"); + ret = 1; + goto out; + } - if ((ret = villasfpga_write_complete(vh, &size)) != 0) { - fprintf(stderr, "Failed to write complete\n"); - ret = 1; - goto out; - } + if ((ret = villasfpga_write_complete(vh, &size)) != 0) { + fprintf(stderr, "Failed to write complete\n"); + ret = 1; + goto out; + } - if ((ret = villasfpga_read_complete(vh, &size)) != 0) { - fprintf(stderr, "Failed to write complete\n"); - ret = 1; - goto out; - } + if ((ret = villasfpga_read_complete(vh, &size)) != 0) { + fprintf(stderr, "Failed to write complete\n"); + ret = 1; + goto out; + } - printf("Read %f (%zu bytes)\n", ((float*)mem1ptr)[0], size); - } + printf("Read %f (%zu bytes)\n", ((float *)mem1ptr)[0], size); + } - ret = 0; - out: - return ret; + ret = 0; +out: + return ret; } diff --git a/fpga/tests/unit/dma.cpp b/fpga/tests/unit/dma.cpp index 9667355fd..03796a458 100644 --- a/fpga/tests/unit/dma.cpp +++ b/fpga/tests/unit/dma.cpp @@ -7,90 +7,92 @@ #include -#include -#include -#include #include -#include #include +#include +#include +#include +#include #include "global.hpp" using namespace villas; // cppcheck-suppress unknownMacro -Test(fpga, dma, .description = "DMA") -{ - auto logger = logging.get("unit-test:dma"); +Test(fpga, dma, .description = "DMA") { + auto logger = logging.get("unit-test:dma"); - std::list> dmaIps; + std::list> dmaIps; - for (auto &ip : state.cards.front()->ips) { - if (*ip == fpga::Vlnv("xilinx.com:ip:axi_dma:")) { - auto dma = std::dynamic_pointer_cast(ip); - dmaIps.push_back(dma); - } - } + for (auto &ip : state.cards.front()->ips) { + if (*ip == fpga::Vlnv("xilinx.com:ip:axi_dma:")) { + auto dma = std::dynamic_pointer_cast(ip); + dmaIps.push_back(dma); + } + } - size_t count = 0; - for (auto &dma : dmaIps) { - logger->info("Testing {}", *dma); + size_t count = 0; + for (auto &dma : dmaIps) { + logger->info("Testing {}", *dma); - if (not dma->loopbackPossible()) { - logger->info("Loopback test not possible for {}", *dma); - continue; - } + if (not dma->loopbackPossible()) { + logger->info("Loopback test not possible for {}", *dma); + continue; + } - dma->connectLoopback(); + dma->connectLoopback(); - // Simple DMA can only transfer up to 4 kb due to PCIe page size burst - // limitation - size_t len = 4 * (1 << 10); + // Simple DMA can only transfer up to 4 kb due to PCIe page size burst + // limitation + size_t len = 4 * (1 << 10); #if 0 // Allocate memory to use with DMA auto src = HostDmaRam::getAllocator().allocate(len); auto dst = HostDmaRam::getAllocator().allocate(len); #elif 0 - // ... only works with IOMMU enabled currently + // ... only works with IOMMU enabled currently - // Find a block RAM IP to write to - auto bramIp = state.cards.front()->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_bram_ctrl:")); - auto bram = std::dynamic_pointer_cast(bramIp); - cr_assert_not_null(bram, "Couldn't find BRAM"); + // Find a block RAM IP to write to + auto bramIp = state.cards.front()->lookupIp( + fpga::Vlnv("xilinx.com:ip:axi_bram_ctrl:")); + auto bram = std::dynamic_pointer_cast(bramIp); + cr_assert_not_null(bram, "Couldn't find BRAM"); - auto src = bram->getAllocator().allocate(len); - auto dst = bram->getAllocator().allocate(len); + auto src = bram->getAllocator().allocate(len); + auto dst = bram->getAllocator().allocate(len); #else - // ... only works with IOMMU enabled currently - auto &alloc = villas::HostRam::getAllocator(); - const std::shared_ptr srcBlock = alloc.allocateBlock(len); - const std::shared_ptr dstBlock = alloc.allocateBlock(len); - villas::MemoryAccessor src(*srcBlock); - villas::MemoryAccessor dst(*dstBlock); + // ... only works with IOMMU enabled currently + auto &alloc = villas::HostRam::getAllocator(); + const std::shared_ptr srcBlock = + alloc.allocateBlock(len); + const std::shared_ptr dstBlock = + alloc.allocateBlock(len); + villas::MemoryAccessor src(*srcBlock); + villas::MemoryAccessor dst(*dstBlock); #endif - // Make sure memory is accessible for DMA - dma->makeAccesibleFromVA(srcBlock); - dma->makeAccesibleFromVA(dstBlock); + // Make sure memory is accessible for DMA + dma->makeAccesibleFromVA(srcBlock); + dma->makeAccesibleFromVA(dstBlock); - // Get new random data - const size_t lenRandom = utils::readRandom(&src, len); - cr_assert(len == lenRandom, "Failed to get random data"); + // Get new random data + const size_t lenRandom = utils::readRandom(&src, len); + cr_assert(len == lenRandom, "Failed to get random data"); - // Start transfer - cr_assert(dma->memcpy(src.getMemoryBlock(), dst.getMemoryBlock(), len), - "DMA ping pong failed"); + // Start transfer + cr_assert(dma->memcpy(src.getMemoryBlock(), dst.getMemoryBlock(), len), + "DMA ping pong failed"); - // Compare data - cr_assert(memcmp(&src, &dst, len) == 0, "Data not equal"); + // Compare data + cr_assert(memcmp(&src, &dst, len) == 0, "Data not equal"); - logger->info(CLR_GRN("Passed")); + logger->info(CLR_GRN("Passed")); - count++; - } + count++; + } - cr_assert(count > 0, "No DMA found"); + cr_assert(count > 0, "No DMA found"); - MemoryManager::get().getGraph().dump(); - fpga::ip::Node::getGraph().dump(); + MemoryManager::get().getGraph().dump(); + fpga::ip::Node::getGraph().dump(); } diff --git a/fpga/tests/unit/fifo.cpp b/fpga/tests/unit/fifo.cpp index 6389a7196..958e3ccc9 100644 --- a/fpga/tests/unit/fifo.cpp +++ b/fpga/tests/unit/fifo.cpp @@ -18,59 +18,58 @@ using namespace villas; // cppcheck-suppress unknownMacro -Test(fpga, fifo, .description = "FIFO") -{ - ssize_t len; - char src[255], dst[255]; - size_t count = 0; +Test(fpga, fifo, .description = "FIFO") { + ssize_t len; + char src[255], dst[255]; + size_t count = 0; - auto logger = logging.get("unit-test:fifo"); + auto logger = logging.get("unit-test:fifo"); - for (auto &ip : state.cards.front()->ips) { - // Skip non-fifo IPs - if (*ip != fpga::Vlnv("xilinx.com:ip:axi_fifo_mm_s:")) - continue; + for (auto &ip : state.cards.front()->ips) { + // Skip non-fifo IPs + if (*ip != fpga::Vlnv("xilinx.com:ip:axi_fifo_mm_s:")) + continue; - logger->info("Testing {}", *ip); + logger->info("Testing {}", *ip); - auto fifo = std::dynamic_pointer_cast(ip); + auto fifo = std::dynamic_pointer_cast(ip); - if (not fifo->loopbackPossible()) { - logger->info("Loopback test not possible for {}", *ip); - continue; - } + if (not fifo->loopbackPossible()) { + logger->info("Loopback test not possible for {}", *ip); + continue; + } - if (not fifo->connectLoopback()) { - continue; - } + if (not fifo->connectLoopback()) { + continue; + } - // Get some random data to compare - memset(dst, 0, sizeof(dst)); - len = utils::readRandom((char *) src, sizeof(src)); - if (len != sizeof(src)) { - logger->error("Failed to get random data"); - continue; - } + // Get some random data to compare + memset(dst, 0, sizeof(dst)); + len = utils::readRandom((char *)src, sizeof(src)); + if (len != sizeof(src)) { + logger->error("Failed to get random data"); + continue; + } - len = fifo->write(src, sizeof(src)); - if (len != sizeof(src)) { - logger->error("Failed to send to FIFO"); - continue; - } + len = fifo->write(src, sizeof(src)); + if (len != sizeof(src)) { + logger->error("Failed to send to FIFO"); + continue; + } - len = fifo->read(dst, sizeof(dst)); - if (len != sizeof(dst)) { - logger->error("Failed to read from FIFO"); - continue; - } + len = fifo->read(dst, sizeof(dst)); + if (len != sizeof(dst)) { + logger->error("Failed to read from FIFO"); + continue; + } - // Compare data - cr_assert_eq(memcmp(src, dst, sizeof(src)), 0, "Data not equal"); + // Compare data + cr_assert_eq(memcmp(src, dst, sizeof(src)), 0, "Data not equal"); - logger->info(CLR_GRN("Passed")); + logger->info(CLR_GRN("Passed")); - count++; - } + count++; + } - cr_assert(count > 0, "No FIFO found"); + cr_assert(count > 0, "No FIFO found"); } diff --git a/fpga/tests/unit/fpga.cpp b/fpga/tests/unit/fpga.cpp index e3c9e6bf1..d6ad32478 100644 --- a/fpga/tests/unit/fpga.cpp +++ b/fpga/tests/unit/fpga.cpp @@ -18,12 +18,12 @@ #include -#define FPGA_CARD "vc707" -#define TEST_CONFIG "../etc/fpga.json" -#define TEST_LEN 0x1000 +#define FPGA_CARD "vc707" +#define TEST_CONFIG "../etc/fpga.json" +#define TEST_LEN 0x1000 -#define CPU_HZ 3392389000 -#define FPGA_AXI_HZ 125000000 +#define CPU_HZ 3392389000 +#define FPGA_AXI_HZ 125000000 using namespace villas; @@ -31,58 +31,53 @@ static kernel::pci::DeviceList *pciDevices; FpgaState state; -static void init() -{ - FILE *f; - json_error_t err; +static void init() { + FILE *f; + json_error_t err; - spdlog::set_level(spdlog::level::debug); - spdlog::set_pattern("[%T] [%l] [%n] %v"); + spdlog::set_level(spdlog::level::debug); + spdlog::set_pattern("[%T] [%l] [%n] %v"); - plugin::registry->dump(); + plugin::registry->dump(); - pciDevices = kernel::pci::DeviceList::getInstance(); + pciDevices = kernel::pci::DeviceList::getInstance(); - auto vfioContainer = std::make_shared(); + auto vfioContainer = std::make_shared(); - // Parse FPGA configuration - char *fn = getenv("TEST_CONFIG"); - f = fopen(fn ? fn : TEST_CONFIG, "r"); - cr_assert_not_null(f, "Cannot open config file"); + // Parse FPGA configuration + char *fn = getenv("TEST_CONFIG"); + f = fopen(fn ? fn : TEST_CONFIG, "r"); + cr_assert_not_null(f, "Cannot open config file"); - json_t *json = json_loadf(f, 0, &err); - cr_assert_not_null(json, "Cannot load JSON config"); + json_t *json = json_loadf(f, 0, &err); + cr_assert_not_null(json, "Cannot load JSON config"); - fclose(f); + fclose(f); - json_t *fpgas = json_object_get(json, "fpgas"); - cr_assert_not_null(fpgas, "No section 'fpgas' found in config"); - cr_assert(json_object_size(json) > 0, "No FPGAs defined in config"); + json_t *fpgas = json_object_get(json, "fpgas"); + cr_assert_not_null(fpgas, "No section 'fpgas' found in config"); + cr_assert(json_object_size(json) > 0, "No FPGAs defined in config"); - // Get the FPGA card plugin - auto fpgaCardFactory = plugin::registry->lookup("pcie"); - cr_assert_not_null(fpgaCardFactory, "No plugin for FPGA card found"); + // Get the FPGA card plugin + auto fpgaCardFactory = + plugin::registry->lookup("pcie"); + cr_assert_not_null(fpgaCardFactory, "No plugin for FPGA card found"); - // Create all FPGA card instances using the corresponding plugin - auto configDir = std::filesystem::path(fn).parent_path(); - auto cards = std::list>(); - fpga::createCards(json, cards, configDir); - state.cards = cards; + // Create all FPGA card instances using the corresponding plugin + auto configDir = std::filesystem::path(fn).parent_path(); + auto cards = std::list>(); + fpga::createCards(json, cards, configDir); + state.cards = cards; - cr_assert(state.cards.size() != 0, "No FPGA cards found!"); + cr_assert(state.cards.size() != 0, "No FPGA cards found!"); - json_decref(json); + json_decref(json); } -static void fini() -{ - // Release all cards - state.cards.clear(); +static void fini() { + // Release all cards + state.cards.clear(); } // cppcheck-suppress unknownMacro -TestSuite(fpga, - .init = init, - .fini = fini, - .description = "VILLASfpga" -); +TestSuite(fpga, .init = init, .fini = fini, .description = "VILLASfpga"); diff --git a/fpga/tests/unit/global.hpp b/fpga/tests/unit/global.hpp index 1b0ebd7ac..01f35799a 100644 --- a/fpga/tests/unit/global.hpp +++ b/fpga/tests/unit/global.hpp @@ -13,7 +13,7 @@ class FpgaState { public: - // List of all available FPGA cards, only first will be tested at the moment + // List of all available FPGA cards, only first will be tested at the moment std::list> cards; }; diff --git a/fpga/tests/unit/gpu.cpp b/fpga/tests/unit/gpu.cpp index 00eb4694d..ef249eedb 100644 --- a/fpga/tests/unit/gpu.cpp +++ b/fpga/tests/unit/gpu.cpp @@ -10,123 +10,126 @@ #include #include -#include #include -#include #include +#include +#include #include #include "global.hpp" -#include #include +#include using namespace villas; // cppcheck-suppress unknownMacro -Test(fpga, gpu_dma, .description = "GPU DMA tests") -{ - auto logger = logging.get("unit-test:dma"); +Test(fpga, gpu_dma, .description = "GPU DMA tests") { + auto logger = logging.get("unit-test:dma"); - auto &card = state.cards.front(); + auto &card = state.cards.front(); - auto gpuPlugin = Plugin::Registry("cuda"); - cr_assert_not_null(gpuPlugin, "No GPU plugin found"); + auto gpuPlugin = Plugin::Registry("cuda"); + cr_assert_not_null(gpuPlugin, "No GPU plugin found"); - auto gpus = gpuPlugin->make(); - cr_assert(gpus.size() > 0, "No GPUs found"); + auto gpus = gpuPlugin->make(); + cr_assert(gpus.size() > 0, "No GPUs found"); - // Just get first cpu - auto &gpu = gpus.front(); + // Just get first cpu + auto &gpu = gpus.front(); - size_t count = 0; - for (auto &ip : card->ips) { - // Skip non-dma IPs - if (*ip != fpga::Vlnv("xilinx.com:ip:axi_bram_ctrl:")) - continue; + size_t count = 0; + for (auto &ip : card->ips) { + // Skip non-dma IPs + if (*ip != fpga::Vlnv("xilinx.com:ip:axi_bram_ctrl:")) + continue; - logger->info("Testing {}", *ip); + logger->info("Testing {}", *ip); - auto bram = dynamic_cast(ip.get()); - cr_assert_not_null(bram, "Couldn't find BRAM"); + auto bram = dynamic_cast(ip.get()); + cr_assert_not_null(bram, "Couldn't find BRAM"); - count++; + count++; - size_t len = 4 * (1 << 10); + size_t len = 4 * (1 << 10); - // Allocate memory to use with DMA + // Allocate memory to use with DMA - auto bram0 = bram->getAllocator().allocate(len); - auto bram1 = bram->getAllocator().allocate(len); + auto bram0 = bram->getAllocator().allocate(len); + auto bram1 = bram->getAllocator().allocate(len); - gpu->makeAccessibleFromPCIeOrHostRam(bram0.getMemoryBlock()); - gpu->makeAccessibleFromPCIeOrHostRam(bram1.getMemoryBlock()); + gpu->makeAccessibleFromPCIeOrHostRam(bram0.getMemoryBlock()); + gpu->makeAccessibleFromPCIeOrHostRam(bram1.getMemoryBlock()); - auto hostRam0 = HostRam::getAllocator().allocate(len); - auto hostRam1 = HostRam::getAllocator().allocate(len); + auto hostRam0 = HostRam::getAllocator().allocate(len); + auto hostRam1 = HostRam::getAllocator().allocate(len); - gpu->makeAccessibleFromPCIeOrHostRam(hostRam0.getMemoryBlock()); - gpu->makeAccessibleFromPCIeOrHostRam(hostRam1.getMemoryBlock()); + gpu->makeAccessibleFromPCIeOrHostRam(hostRam0.getMemoryBlock()); + gpu->makeAccessibleFromPCIeOrHostRam(hostRam1.getMemoryBlock()); - auto dmaRam0 = HostDmaRam::getAllocator().allocate(len); - auto dmaRam1 = HostDmaRam::getAllocator().allocate(len); + auto dmaRam0 = HostDmaRam::getAllocator().allocate(len); + auto dmaRam1 = HostDmaRam::getAllocator().allocate(len); - gpu->makeAccessibleFromPCIeOrHostRam(dmaRam0.getMemoryBlock()); - gpu->makeAccessibleFromPCIeOrHostRam(dmaRam1.getMemoryBlock()); + gpu->makeAccessibleFromPCIeOrHostRam(dmaRam0.getMemoryBlock()); + gpu->makeAccessibleFromPCIeOrHostRam(dmaRam1.getMemoryBlock()); - auto gpuMem0 = gpu->getAllocator().allocate(64 << 10); - auto gpuMem1 = gpu->getAllocator().allocate(64 << 10); + auto gpuMem0 = gpu->getAllocator().allocate(64 << 10); + auto gpuMem1 = gpu->getAllocator().allocate(64 << 10); - gpu->makeAccessibleToPCIeAndVA(gpuMem0.getMemoryBlock()); - gpu->makeAccessibleToPCIeAndVA(gpuMem1.getMemoryBlock()); + gpu->makeAccessibleToPCIeAndVA(gpuMem0.getMemoryBlock()); + gpu->makeAccessibleToPCIeAndVA(gpuMem1.getMemoryBlock()); -// auto &src = bram0; -// auto &dst = bram1; + // auto &src = bram0; + // auto &dst = bram1; -// auto &src = hostRam0; -// auto &dst = hostRam1; + // auto &src = hostRam0; + // auto &dst = hostRam1; - auto &src = dmaRam0; -// auto &dst = dmaRam1; + auto &src = dmaRam0; + // auto &dst = dmaRam1; -// auto &src = gpuMem0; - auto &dst = gpuMem1; + // auto &src = gpuMem0; + auto &dst = gpuMem1; - std::list>> memcpyFuncs = { - {"cudaMemcpy", [&]() {gpu->memcpySync(src.getMemoryBlock(), dst.getMemoryBlock(), len);}}, - {"CUDA kernel", [&]() {gpu->memcpyKernel(src.getMemoryBlock(), dst.getMemoryBlock(), len);}}, - }; + std::list>> memcpyFuncs = { + {"cudaMemcpy", + [&]() { + gpu->memcpySync(src.getMemoryBlock(), dst.getMemoryBlock(), len); + }}, + {"CUDA kernel", + [&]() { + gpu->memcpyKernel(src.getMemoryBlock(), dst.getMemoryBlock(), len); + }}, + }; - auto dmaIp = card->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:")); - auto dma = std::dynamic_pointer_cast(dmaIp); + auto dmaIp = card->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:")); + auto dma = std::dynamic_pointer_cast(dmaIp); - if (dma != nullptr and dma->connectLoopback()) { - memcpyFuncs.push_back({ - "DMA memcpy", [&] (){ - dma->makeAccesibleFromVA(src.getMemoryBlock()); - dma->makeAccesibleFromVA(dst.getMemoryBlock()); - dma->memcpy(src.getMemoryBlock(), dst.getMemoryBlock(), len); - }}); - } + if (dma != nullptr and dma->connectLoopback()) { + memcpyFuncs.push_back({"DMA memcpy", [&]() { + dma->makeAccesibleFromVA(src.getMemoryBlock()); + dma->makeAccesibleFromVA(dst.getMemoryBlock()); + dma->memcpy(src.getMemoryBlock(), + dst.getMemoryBlock(), len); + }}); + } - for (auto& [name, memcpyFunc] : memcpyFuncs) { - logger->info("Testing {}", name); + for (auto &[name, memcpyFunc] : memcpyFuncs) { + logger->info("Testing {}", name); - // Get new random data - const size_t lenRandom = utils::read_random(&src, len); - cr_assert(len == lenRandom, "Failed to get random data"); + // Get new random data + const size_t lenRandom = utils::read_random(&src, len); + cr_assert(len == lenRandom, "Failed to get random data"); - memcpyFunc(); - const bool success = memcmp(&src, &dst, len) == 0; + memcpyFunc(); + const bool success = memcmp(&src, &dst, len) == 0; - logger->info(" {}", success ? - CLR_GRN("Passed") : - CLR_RED("Failed")); - } + logger->info(" {}", success ? CLR_GRN("Passed") : CLR_RED("Failed")); + } - MemoryManager::getGraph().dump(); - } + MemoryManager::getGraph().dump(); + } - cr_assert(count > 0, "No BRAM found"); + cr_assert(count > 0, "No BRAM found"); } diff --git a/fpga/tests/unit/logging.cpp b/fpga/tests/unit/logging.cpp index 168712094..2d7727c6d 100644 --- a/fpga/tests/unit/logging.cpp +++ b/fpga/tests/unit/logging.cpp @@ -11,100 +11,104 @@ #include #include -#include #include +#include extern "C" { - // We override criterions function here - void criterion_log_noformat(enum criterion_severity severity, const char *msg); - void criterion_plog(enum criterion_logging_level level, const struct criterion_prefix_data *prefix, const char *msg, ...); - void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list args); +// We override criterions function here +void criterion_log_noformat(enum criterion_severity severity, const char *msg); +void criterion_plog(enum criterion_logging_level level, + const struct criterion_prefix_data *prefix, const char *msg, + ...); +void criterion_vlog(enum criterion_logging_level level, const char *msg, + va_list args); } struct criterion_prefix_data { - const char *prefix; - const char *color; + const char *prefix; + const char *color; }; -static int format_msg(char *buf, size_t buflen, const char *msg, va_list args) -{ - int len = vsnprintf(buf, buflen, msg, args); +static int format_msg(char *buf, size_t buflen, const char *msg, va_list args) { + int len = vsnprintf(buf, buflen, msg, args); - // Strip new line - char *nl = strchr(buf, '\n'); - if (nl) - *nl = 0; + // Strip new line + char *nl = strchr(buf, '\n'); + if (nl) + *nl = 0; - return len; + return len; } -void criterion_log_noformat(enum criterion_severity severity, const char *msg) -{ - auto logger = villas::logging.get("criterion"); +void criterion_log_noformat(enum criterion_severity severity, const char *msg) { + auto logger = villas::logging.get("criterion"); - switch (severity) { - case CR_LOG_INFO: - logger->info(msg); - break; + switch (severity) { + case CR_LOG_INFO: + logger->info(msg); + break; - case CR_LOG_WARNING: - logger->warn(msg); - break; + case CR_LOG_WARNING: + logger->warn(msg); + break; - case CR_LOG_ERROR: - logger->error(msg); - break; - } + case CR_LOG_ERROR: + logger->error(msg); + break; + } } -void criterion_vlog(enum criterion_logging_level level, const char *msg, va_list args) -{ - char formatted_msg[1024]; +void criterion_vlog(enum criterion_logging_level level, const char *msg, + va_list args) { + char formatted_msg[1024]; - if (level < criterion_options.logging_threshold) - return; + if (level < criterion_options.logging_threshold) + return; - format_msg(formatted_msg, sizeof(formatted_msg), msg, args); + format_msg(formatted_msg, sizeof(formatted_msg), msg, args); - auto logger = villas::logging.get("criterion"); - logger->info(formatted_msg); + auto logger = villas::logging.get("criterion"); + logger->info(formatted_msg); } -void criterion_plog(enum criterion_logging_level level, const struct criterion_prefix_data *prefix, const char *msg, ...) -{ - char formatted_msg[1024]; +void criterion_plog(enum criterion_logging_level level, + const struct criterion_prefix_data *prefix, const char *msg, + ...) { + char formatted_msg[1024]; - va_list args; + va_list args; - if (level < criterion_options.logging_threshold) - return; + if (level < criterion_options.logging_threshold) + return; - va_start(args, msg); - format_msg(formatted_msg, sizeof(formatted_msg), msg, args); - va_end(args); + va_start(args, msg); + format_msg(formatted_msg, sizeof(formatted_msg), msg, args); + va_end(args); - auto logger = villas::logging.get("criterion"); + auto logger = villas::logging.get("criterion"); - if (strstr(formatted_msg, "Warning")) - logger->warn(formatted_msg); - else if (strstr(formatted_msg, "Failed")) - logger->error(formatted_msg); - else if (!strcmp(prefix->prefix, "----") && !strcmp(prefix->color, "\33[0;34m")) - logger->info(formatted_msg); - else if (!strcmp(prefix->prefix, "----") && !strcmp(prefix->color, "\33[1;30m")) - logger->debug(formatted_msg); - else if (!strcmp(prefix->prefix, "====")) - logger->info(formatted_msg); - else if (!strcmp(prefix->prefix, "RUN ")) - logger->info("Run: {}", formatted_msg); - else if (!strcmp(prefix->prefix, "SKIP")) - logger->info("Skip: {}", formatted_msg); - else if (!strcmp(prefix->prefix, "PASS")) - logger->info("Pass: {}", formatted_msg); - else if (!strcmp(prefix->prefix, "FAIL")) - logger->error("Fail: {}", formatted_msg); - else if (!strcmp(prefix->prefix, "WARN")) - logger->warn(formatted_msg); - else if (!strcmp(prefix->prefix, "ERR ")) - logger->error(formatted_msg); + if (strstr(formatted_msg, "Warning")) + logger->warn(formatted_msg); + else if (strstr(formatted_msg, "Failed")) + logger->error(formatted_msg); + else if (!strcmp(prefix->prefix, "----") && + !strcmp(prefix->color, "\33[0;34m")) + logger->info(formatted_msg); + else if (!strcmp(prefix->prefix, "----") && + !strcmp(prefix->color, "\33[1;30m")) + logger->debug(formatted_msg); + else if (!strcmp(prefix->prefix, "====")) + logger->info(formatted_msg); + else if (!strcmp(prefix->prefix, "RUN ")) + logger->info("Run: {}", formatted_msg); + else if (!strcmp(prefix->prefix, "SKIP")) + logger->info("Skip: {}", formatted_msg); + else if (!strcmp(prefix->prefix, "PASS")) + logger->info("Pass: {}", formatted_msg); + else if (!strcmp(prefix->prefix, "FAIL")) + logger->error("Fail: {}", formatted_msg); + else if (!strcmp(prefix->prefix, "WARN")) + logger->warn(formatted_msg); + else if (!strcmp(prefix->prefix, "ERR ")) + logger->error(formatted_msg); } diff --git a/fpga/tests/unit/main.cpp b/fpga/tests/unit/main.cpp index fb92de8c9..db8385218 100644 --- a/fpga/tests/unit/main.cpp +++ b/fpga/tests/unit/main.cpp @@ -6,59 +6,56 @@ */ #include -#include #include #include +#include #include #include // Returns true if there is at least one enabled test in this suite -static bool suite_enabled(struct criterion_test_set *tests, const char *name) -{ - FOREACH_SET(void *suite_ptr, tests->suites) { - struct criterion_suite_set *suite = (struct criterion_suite_set *) suite_ptr; +static bool suite_enabled(struct criterion_test_set *tests, const char *name) { + FOREACH_SET(void *suite_ptr, tests->suites) { + struct criterion_suite_set *suite = (struct criterion_suite_set *)suite_ptr; - if (!strcmp(suite->suite.name, name)) { - FOREACH_SET(void *test_ptr, suite->tests) { - struct criterion_test *test = (struct criterion_test *) test_ptr; + if (!strcmp(suite->suite.name, name)) { + FOREACH_SET(void *test_ptr, suite->tests) { + struct criterion_test *test = (struct criterion_test *)test_ptr; - if (!test->data->disabled) - return true; - } - } - } + if (!test->data->disabled) + return true; + } + } + } - return false; + return false; } // Limit number of parallel jobs to 1 in case we use the FPGA -ReportHook(PRE_ALL)(struct criterion_test_set *tests) -{ - if (suite_enabled(tests, "fpga")) { - auto logger = villas::logging.get("unittest"); +ReportHook(PRE_ALL)(struct criterion_test_set *tests) { + if (suite_enabled(tests, "fpga")) { + auto logger = villas::logging.get("unittest"); - logger->info("FPGA tests enabled. Only 1 job is executed in parallel!."); - criterion_options.jobs = 1; - } + logger->info("FPGA tests enabled. Only 1 job is executed in parallel!."); + criterion_options.jobs = 1; + } } -int main(int argc, char *argv[]) -{ - int ret; +int main(int argc, char *argv[]) { + int ret; - spdlog::set_level(spdlog::level::debug); - spdlog::set_pattern("[%T] [%l] [%n] %v"); + spdlog::set_level(spdlog::level::debug); + spdlog::set_pattern("[%T] [%l] [%n] %v"); - // Run criterion tests - auto tests = criterion_initialize(); + // Run criterion tests + auto tests = criterion_initialize(); - ret = criterion_handle_args(argc, argv, true); - if (ret) - ret = !criterion_run_all_tests(tests); + ret = criterion_handle_args(argc, argv, true); + if (ret) + ret = !criterion_run_all_tests(tests); - criterion_finalize(tests); + criterion_finalize(tests); - return ret; + return ret; } diff --git a/fpga/tests/unit/rtds.cpp b/fpga/tests/unit/rtds.cpp index 134d1bd1b..c3f64df4a 100644 --- a/fpga/tests/unit/rtds.cpp +++ b/fpga/tests/unit/rtds.cpp @@ -12,8 +12,8 @@ #include #include -#include #include +#include #include #include @@ -28,92 +28,93 @@ using namespace villas::fpga::ip; // cppcheck-suppress unknownMacro -Test(fpga, rtds, .description = "RTDS") -{ - auto logger = villas::logging.get("unit-test:rtds"); +Test(fpga, rtds, .description = "RTDS") { + auto logger = villas::logging.get("unit-test:rtds"); - std::list rtdsIps; - std::list dmaIps; + std::list rtdsIps; + std::list dmaIps; - for (auto &ip : state.cards.front()->ips) { - if (*ip == villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")) { - auto rtds = reinterpret_cast(ip.get()); - rtdsIps.push_back(rtds); - } + for (auto &ip : state.cards.front()->ips) { + if (*ip == + villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")) { + auto rtds = reinterpret_cast(ip.get()); + rtdsIps.push_back(rtds); + } - if (*ip == villas::fpga::Vlnv("xilinx.com:ip:axi_dma:")) { - auto dma = reinterpret_cast(ip.get()); - dmaIps.push_back(dma); - } - } + if (*ip == villas::fpga::Vlnv("xilinx.com:ip:axi_dma:")) { + auto dma = reinterpret_cast(ip.get()); + dmaIps.push_back(dma); + } + } - cr_assert(rtdsIps.size() > 0, "No RTDS IPs available to test"); - cr_assert(dmaIps.size() > 0, "No DMA IPs available to test RTDS with"); + cr_assert(rtdsIps.size() > 0, "No RTDS IPs available to test"); + cr_assert(dmaIps.size() > 0, "No DMA IPs available to test RTDS with"); - for (auto rtds : rtdsIps) { - for (auto dma : dmaIps) { - logger->info("Testing {} with DMA {}", *rtds, *dma); + for (auto rtds : rtdsIps) { + for (auto dma : dmaIps) { + logger->info("Testing {} with DMA {}", *rtds, *dma); - rtds->dump(); + rtds->dump(); - auto rtdsMaster = rtds->getMasterPort(rtds->masterPort); - auto rtdsSlave = rtds->getSlavePort(rtds->slavePort); + auto rtdsMaster = rtds->getMasterPort(rtds->masterPort); + auto rtdsSlave = rtds->getSlavePort(rtds->slavePort); - auto dmaMaster = dma->getMasterPort(dma->mm2sPort); - auto dmaSlave = dma->getSlavePort(dma->s2mmPort); + auto dmaMaster = dma->getMasterPort(dma->mm2sPort); + auto dmaSlave = dma->getSlavePort(dma->s2mmPort); -// rtds->connect(*rtds); -// logger->info("loopback"); -// while (1); + // rtds->connect(*rtds); + // logger->info("loopback"); + // while (1); -// rtds->connect(rtdsMaster, dmaSlave); -// dma->connect(dmaMaster, rtdsSlave); + // rtds->connect(rtdsMaster, dmaSlave); + // dma->connect(dmaMaster, rtdsSlave); - auto mem = villas::HostRam::getAllocator().allocate(0x100 / sizeof(int32_t)); + auto mem = villas::HostRam::getAllocator().allocate( + 0x100 / sizeof(int32_t)); -// auto start = std::chrono::high_resolution_clock::now(); + // auto start = std::chrono::high_resolution_clock::now(); - for (int i = 1; i < 5; i++) { - logger->info("RTT iteration {}", i); + for (int i = 1; i < 5; i++) { + logger->info("RTT iteration {}", i); -// logger->info("Prepare read"); - cr_assert(dma->read(mem.getMemoryBlock(), mem.getMemoryBlock().getSize()), - "Failed to initiate DMA read"); + // logger->info("Prepare read"); + cr_assert( + dma->read(mem.getMemoryBlock(), mem.getMemoryBlock().getSize()), + "Failed to initiate DMA read"); -// logger->info("Wait read"); - const size_t bytesRead = dma->readComplete().bytes; - cr_assert(bytesRead > 0, - "Failed to complete DMA read"); + // logger->info("Wait read"); + const size_t bytesRead = dma->readComplete().bytes; + cr_assert(bytesRead > 0, "Failed to complete DMA read"); -// logger->info("Bytes received: {}", bytesRead); -// logger->info("Prepare write"); - cr_assert(dma->write(mem.getMemoryBlock(), bytesRead), - "Failed to initiate DMA write"); + // logger->info("Bytes received: {}", bytesRead); + // logger->info("Prepare write"); + cr_assert(dma->write(mem.getMemoryBlock(), bytesRead), + "Failed to initiate DMA write"); -// logger->info("Wait write"); -// const size_t bytesWritten = dma->writeComplete(); -// cr_assert(bytesWritten > 0, -// "Failed to complete DMA write"); + // logger->info("Wait write"); + // const size_t bytesWritten = dma->writeComplete(); + // cr_assert(bytesWritten > 0, + // "Failed to complete DMA write"); -// usleep(5); -// sched_yield(); + // usleep(5); + // sched_yield(); -// for (int i = 0;) -// rdtsc_sleep(); + // for (int i = 0;) + // rdtsc_sleep(); -// static constexpr int loopCount = 10000; -// if (i % loopCount == 0) { -// const auto end = std::chrono::high_resolution_clock::now(); + // static constexpr int loopCount = 10000; + // if (i % loopCount == 0) { + // const auto end = std::chrono::high_resolution_clock::now(); -// auto durationUs = std::chrono::duration_cast(end - start) / loopCount; + // auto durationUs = std::chrono::duration_cast(end - start) / loopCount; -// logger->info("Avg. loop duration: {} us", durationUs.count()); + // logger->info("Avg. loop duration: {} us", durationUs.count()); -// start = std::chrono::high_resolution_clock::now(); -// } - } + // start = std::chrono::high_resolution_clock::now(); + // } + } - logger->info(CLR_GRN("Passed")); - } - } + logger->info(CLR_GRN("Passed")); + } + } } diff --git a/fpga/tests/unit/rtds2gpu.cpp b/fpga/tests/unit/rtds2gpu.cpp index 27d999eb3..a1f9ffcd2 100644 --- a/fpga/tests/unit/rtds2gpu.cpp +++ b/fpga/tests/unit/rtds2gpu.cpp @@ -9,308 +9,326 @@ #include +#include #include #include -#include -#include -#include -#include #include +#include #include +#include +#include #include #include "global.hpp" using namespace villas; -static constexpr size_t SAMPLE_SIZE = 4; -static constexpr size_t SAMPLE_COUNT = 1; -static constexpr size_t FRAME_SIZE = SAMPLE_COUNT * SAMPLE_SIZE; +static constexpr size_t SAMPLE_SIZE = 4; +static constexpr size_t SAMPLE_COUNT = 1; +static constexpr size_t FRAME_SIZE = SAMPLE_COUNT * SAMPLE_SIZE; static constexpr size_t DOORBELL_OFFSET = SAMPLE_COUNT; static constexpr size_t DATA_OFFSET = 0; -static void dumpMem(const uint32_t* addr, size_t len) -{ - const size_t bytesPerLine = 16; - const size_t lines = (len) / bytesPerLine + 1; - const uint8_t* buf = reinterpret_cast(addr); +static void dumpMem(const uint32_t *addr, size_t len) { + const size_t bytesPerLine = 16; + const size_t lines = (len) / bytesPerLine + 1; + const uint8_t *buf = reinterpret_cast(addr); - size_t bytesRead = 0; + size_t bytesRead = 0; - for (size_t line = 0; line < lines; line++) { - const unsigned base = line * bytesPerLine; - printf("0x%04x: ", base); + for (size_t line = 0; line < lines; line++) { + const unsigned base = line * bytesPerLine; + printf("0x%04x: ", base); - for (size_t i = 0; i < bytesPerLine && bytesRead < len; i++) { - printf("0x%02x ", buf[base + i]); - bytesRead++; - } - puts(""); - } + for (size_t i = 0; i < bytesPerLine && bytesRead < len; i++) { + printf("0x%02x ", buf[base + i]); + bytesRead++; + } + puts(""); + } } // cppcheck-suppress unknownMacro -Test(fpga, rtds2gpu_loopback_dma, .description = "Rtds2Gpu") -{ - auto logger = logging.get("unit-test:rtds2gpu"); +Test(fpga, rtds2gpu_loopback_dma, .description = "Rtds2Gpu") { + auto logger = logging.get("unit-test:rtds2gpu"); - for (auto &ip : state.cards.front()->ips) { - if (*ip != fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:")) - continue; + for (auto &ip : state.cards.front()->ips) { + if (*ip != fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:")) + continue; - logger->info("Testing {}", *ip); + logger->info("Testing {}", *ip); - // Collect neccessary IPs - auto rtds2gpu = std::dynamic_pointer_cast(ip); + // Collect neccessary IPs + auto rtds2gpu = std::dynamic_pointer_cast(ip); - auto axiSwitch = std::dynamic_pointer_cast( - state.cards.front()->lookupIp(fpga::Vlnv("xilinx.com:ip:axis_switch:"))); + auto axiSwitch = std::dynamic_pointer_cast( + state.cards.front()->lookupIp( + fpga::Vlnv("xilinx.com:ip:axis_switch:"))); - auto dma = std::dynamic_pointer_cast( - state.cards.front()->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:"))); + auto dma = std::dynamic_pointer_cast( + state.cards.front()->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:"))); - auto gpu2rtds = std::dynamic_pointer_cast( - state.cards.front()->lookupIp(fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:"))); + auto gpu2rtds = std::dynamic_pointer_cast( + state.cards.front()->lookupIp( + fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:"))); - auto rtds = std::dynamic_pointer_cast( - state.cards.front()->lookupIp(fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:"))); + auto rtds = + std::dynamic_pointer_cast(state.cards.front()->lookupIp( + fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:"))); - cr_assert_not_null(axiSwitch, "No AXI switch IP found"); - cr_assert_not_null(dma, "No DMA IP found"); - cr_assert_not_null(gpu2rtds, "No Gpu2Rtds IP found"); - cr_assert_not_null(rtds, "RTDS IP not found"); + cr_assert_not_null(axiSwitch, "No AXI switch IP found"); + cr_assert_not_null(dma, "No DMA IP found"); + cr_assert_not_null(gpu2rtds, "No Gpu2Rtds IP found"); + cr_assert_not_null(rtds, "RTDS IP not found"); - rtds2gpu.dump(spdlog::level::debug); - gpu2rtds->dump(spdlog::level::debug); + rtds2gpu.dump(spdlog::level::debug); + gpu2rtds->dump(spdlog::level::debug); - // Allocate and prepare memory + // Allocate and prepare memory - // Allocate space for all samples and doorbell register - auto dmaMemSrc = HostDmaRam::getAllocator(0).allocate(SAMPLE_COUNT + 1); - auto dmaMemDst = HostDmaRam::getAllocator(0).allocate(SAMPLE_COUNT + 1); - auto dmaMemDst2 = HostDmaRam::getAllocator(0).allocate(SAMPLE_COUNT + 1); + // Allocate space for all samples and doorbell register + auto dmaMemSrc = + HostDmaRam::getAllocator(0).allocate(SAMPLE_COUNT + 1); + auto dmaMemDst = + HostDmaRam::getAllocator(0).allocate(SAMPLE_COUNT + 1); + auto dmaMemDst2 = + HostDmaRam::getAllocator(0).allocate(SAMPLE_COUNT + 1); - memset(&dmaMemSrc, 0x11, dmaMemSrc.getMemoryBlock().getSize()); - memset(&dmaMemDst, 0x55, dmaMemDst.getMemoryBlock().getSize()); - memset(&dmaMemDst2, 0x77, dmaMemDst2.getMemoryBlock().getSize()); + memset(&dmaMemSrc, 0x11, dmaMemSrc.getMemoryBlock().getSize()); + memset(&dmaMemDst, 0x55, dmaMemDst.getMemoryBlock().getSize()); + memset(&dmaMemDst2, 0x77, dmaMemDst2.getMemoryBlock().getSize()); - const uint32_t* dataSrc = &dmaMemSrc[DATA_OFFSET]; - const uint32_t* dataDst = &dmaMemDst[DATA_OFFSET]; - const uint32_t* dataDst2 = &dmaMemDst2[0]; + const uint32_t *dataSrc = &dmaMemSrc[DATA_OFFSET]; + const uint32_t *dataDst = &dmaMemDst[DATA_OFFSET]; + const uint32_t *dataDst2 = &dmaMemDst2[0]; - dumpMem(dataSrc, dmaMemSrc.getMemoryBlock().getSize()); - dumpMem(dataDst, dmaMemDst.getMemoryBlock().getSize()); - dumpMem(dataDst2, dmaMemDst2.getMemoryBlock().getSize()); + dumpMem(dataSrc, dmaMemSrc.getMemoryBlock().getSize()); + dumpMem(dataDst, dmaMemDst.getMemoryBlock().getSize()); + dumpMem(dataDst2, dmaMemDst2.getMemoryBlock().getSize()); - // Connect AXI Stream from DMA to Rtds2Gpu IP - cr_assert(dma->connect(rtds2gpu)); + // Connect AXI Stream from DMA to Rtds2Gpu IP + cr_assert(dma->connect(rtds2gpu)); - cr_assert(rtds2gpu.startOnce(dmaMemDst.getMemoryBlock(), SAMPLE_COUNT, DATA_OFFSET * 4, DOORBELL_OFFSET * 4), - "Preparing Rtds2Gpu IP failed"); + cr_assert(rtds2gpu.startOnce(dmaMemDst.getMemoryBlock(), SAMPLE_COUNT, + DATA_OFFSET * 4, DOORBELL_OFFSET * 4), + "Preparing Rtds2Gpu IP failed"); - cr_assert(dma->write(dmaMemSrc.getMemoryBlock(), FRAME_SIZE), - "Starting DMA MM2S transfer failed"); + cr_assert(dma->write(dmaMemSrc.getMemoryBlock(), FRAME_SIZE), + "Starting DMA MM2S transfer failed"); - cr_assert(dma->writeComplete(), - "DMA failed"); + cr_assert(dma->writeComplete(), "DMA failed"); - while (not rtds2gpu.isFinished()); + while (not rtds2gpu.isFinished()) + ; - const uint32_t* doorbellDst = &dmaMemDst[DOORBELL_OFFSET]; - rtds2gpu.dump(spdlog::level::info); - rtds2gpu.dumpDoorbell(*doorbellDst); + const uint32_t *doorbellDst = &dmaMemDst[DOORBELL_OFFSET]; + rtds2gpu.dump(spdlog::level::info); + rtds2gpu.dumpDoorbell(*doorbellDst); - cr_assert(memcmp(dataSrc, dataDst, FRAME_SIZE) == 0, "Memory not equal"); + cr_assert(memcmp(dataSrc, dataDst, FRAME_SIZE) == 0, "Memory not equal"); - for (size_t i = 0; i < SAMPLE_COUNT; i++) - gpu2rtds->registerFrames[i] = dmaMemDst[i]; + for (size_t i = 0; i < SAMPLE_COUNT; i++) + gpu2rtds->registerFrames[i] = dmaMemDst[i]; - // Connect AXI Stream from Gpu2Rtds IP to DMA - cr_assert(gpu2rtds->connect(*dma)); + // Connect AXI Stream from Gpu2Rtds IP to DMA + cr_assert(gpu2rtds->connect(*dma)); - cr_assert(dma->read(dmaMemDst2.getMemoryBlock(), FRAME_SIZE), - "Starting DMA S2MM transfer failed"); + cr_assert(dma->read(dmaMemDst2.getMemoryBlock(), FRAME_SIZE), + "Starting DMA S2MM transfer failed"); - cr_assert(gpu2rtds->startOnce(SAMPLE_COUNT), - "Preparing Gpu2Rtds IP failed"); + cr_assert(gpu2rtds->startOnce(SAMPLE_COUNT), + "Preparing Gpu2Rtds IP failed"); - cr_assert(dma->readComplete(), - "DMA failed"); + cr_assert(dma->readComplete(), "DMA failed"); - while (not gpu2rtds->isFinished()); + while (not gpu2rtds->isFinished()) + ; - cr_assert(memcmp(dataSrc, dataDst2, FRAME_SIZE) == 0, "Memory not equal"); + cr_assert(memcmp(dataSrc, dataDst2, FRAME_SIZE) == 0, "Memory not equal"); - dumpMem(dataSrc, dmaMemSrc.getMemoryBlock().getSize()); - dumpMem(dataDst, dmaMemDst.getMemoryBlock().getSize()); - dumpMem(dataDst2, dmaMemDst2.getMemoryBlock().getSize()); + dumpMem(dataSrc, dmaMemSrc.getMemoryBlock().getSize()); + dumpMem(dataDst, dmaMemDst.getMemoryBlock().getSize()); + dumpMem(dataDst2, dmaMemDst2.getMemoryBlock().getSize()); - logger->info(CLR_GRN("Passed")); - } + logger->info(CLR_GRN("Passed")); + } } // cppcheck-suppress unknownMacro -Test(fpga, rtds2gpu_rtt_cpu, .description = "Rtds2Gpu RTT via CPU") -{ - auto logger = logging.get("unit-test:rtds2gpu"); +Test(fpga, rtds2gpu_rtt_cpu, .description = "Rtds2Gpu RTT via CPU") { + auto logger = logging.get("unit-test:rtds2gpu"); - // Collect neccessary IPs - auto gpu2rtds = std::dynamic_pointer_cast( - state.cards.front()->lookupIp(fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:"))); + // Collect neccessary IPs + auto gpu2rtds = std::dynamic_pointer_cast( + state.cards.front()->lookupIp( + fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:"))); - auto rtds2gpu = std::dynamic_pointer_cast( - state.cards.front()->lookupIp(fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:"))); + auto rtds2gpu = std::dynamic_pointer_cast( + state.cards.front()->lookupIp( + fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:"))); - cr_assert_not_null(gpu2rtds, "No Gpu2Rtds IP found"); - cr_assert_not_null(rtds2gpu, "No Rtds2Gpu IP not found"); + cr_assert_not_null(gpu2rtds, "No Gpu2Rtds IP found"); + cr_assert_not_null(rtds2gpu, "No Rtds2Gpu IP not found"); - for (auto &ip : state.cards.front()->ips) { - if (*ip != fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")) - continue; + for (auto &ip : state.cards.front()->ips) { + if (*ip != fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")) + continue; - auto &rtds = dynamic_cast(*ip); - logger->info("Testing {}", rtds); + auto &rtds = dynamic_cast(*ip); + logger->info("Testing {}", rtds); - auto dmaRam = HostDmaRam::getAllocator().allocate(SAMPLE_COUNT + 1); - uint32_t* data = &dmaRam[DATA_OFFSET]; - uint32_t* doorbell = &dmaRam[DOORBELL_OFFSET]; + auto dmaRam = + HostDmaRam::getAllocator().allocate(SAMPLE_COUNT + 1); + uint32_t *data = &dmaRam[DATA_OFFSET]; + uint32_t *doorbell = &dmaRam[DOORBELL_OFFSET]; - // TEST: rtds loopback via switch, this should always work and have RTT=1 - //cr_assert(rtds.connect(rtds)); - //logger->info("loopback"); - //while (1); + // TEST: rtds loopback via switch, this should always work and have RTT=1 + //cr_assert(rtds.connect(rtds)); + //logger->info("loopback"); + //while (1); - cr_assert(rtds.connect(*rtds2gpu)); - cr_assert(gpu2rtds->connect(rtds)); + cr_assert(rtds.connect(*rtds2gpu)); + cr_assert(gpu2rtds->connect(rtds)); - for (size_t i = 1; i <= 10000; ) { - rtds2gpu->doorbellReset(*doorbell); - rtds2gpu->startOnce(dmaRam.getMemoryBlock(), SAMPLE_COUNT, DATA_OFFSET * 4, DOORBELL_OFFSET * 4); + for (size_t i = 1; i <= 10000;) { + rtds2gpu->doorbellReset(*doorbell); + rtds2gpu->startOnce(dmaRam.getMemoryBlock(), SAMPLE_COUNT, + DATA_OFFSET * 4, DOORBELL_OFFSET * 4); - // Wait by polling rtds2gpu IP or ... - // while (not rtds2gpu->isFinished()); + // Wait by polling rtds2gpu IP or ... + // while (not rtds2gpu->isFinished()); - // Wait by polling (local) doorbell register (= just memory) - while (not rtds2gpu->doorbellIsValid(*doorbell)); + // Wait by polling (local) doorbell register (= just memory) + while (not rtds2gpu->doorbellIsValid(*doorbell)) + ; - // Copy samples to gpu2rtds IP - for (size_t i = 0; i < SAMPLE_COUNT; i++) { - gpu2rtds->registerFrames[i] = data[i]; - } + // Copy samples to gpu2rtds IP + for (size_t i = 0; i < SAMPLE_COUNT; i++) { + gpu2rtds->registerFrames[i] = data[i]; + } - // Waiting for gpu2rtds is not strictly required - gpu2rtds->startOnce(SAMPLE_COUNT); - //while (not gpu2rtds->isFinished()); + // Waiting for gpu2rtds is not strictly required + gpu2rtds->startOnce(SAMPLE_COUNT); + //while (not gpu2rtds->isFinished()); - if (i % 1000 == 0) { - logger->info("Successful iterations {}, data {}", i, data[0]); - rtds2gpu->dump(); - rtds2gpu->dumpDoorbell(data[1]); - } - } + if (i % 1000 == 0) { + logger->info("Successful iterations {}, data {}", i, data[0]); + rtds2gpu->dump(); + rtds2gpu->dumpDoorbell(data[1]); + } + } - logger->info(CLR_GRN("Passed")); - } + logger->info(CLR_GRN("Passed")); + } } -void gpu_rtds_rtt_start(volatile uint32_t* dataIn, volatile reg_doorbell_t* doorbellIn, - volatile uint32_t* dataOut, volatile fpga::ip::ControlRegister* controlRegister); +void gpu_rtds_rtt_start(volatile uint32_t *dataIn, + volatile reg_doorbell_t *doorbellIn, + volatile uint32_t *dataOut, + volatile fpga::ip::ControlRegister *controlRegister); void gpu_rtds_rtt_stop(); // cppcheck-suppress unknownMacro -Test(fpga, rtds2gpu_rtt_gpu, .description = "Rtds2Gpu RTT via GPU") -{ - auto logger = logging.get("unit-test:rtds2gpu"); +Test(fpga, rtds2gpu_rtt_gpu, .description = "Rtds2Gpu RTT via GPU") { + auto logger = logging.get("unit-test:rtds2gpu"); - // Collect neccessary IPs - auto gpu2rtds = std::dynamic_pointer_cast( - state.cards.front()->lookupIp(fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:"))); + // Collect neccessary IPs + auto gpu2rtds = std::dynamic_pointer_cast( + state.cards.front()->lookupIp( + fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:"))); - auto rtds2gpu = std::dynamic_pointer_cast( - state.cards.front()->lookupIp(fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:"))); + auto rtds2gpu = std::dynamic_pointer_cast( + state.cards.front()->lookupIp( + fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:"))); - cr_assert_not_null(gpu2rtds, "No Gpu2Rtds IP found"); - cr_assert_not_null(rtds2gpu, "No Rtds2Gpu IP not found"); + cr_assert_not_null(gpu2rtds, "No Gpu2Rtds IP found"); + cr_assert_not_null(rtds2gpu, "No Rtds2Gpu IP not found"); - auto gpuPlugin = Registry::lookup("cuda"); - cr_assert_not_null(gpuPlugin, "No GPU plugin found"); + auto gpuPlugin = Registry::lookup("cuda"); + cr_assert_not_null(gpuPlugin, "No GPU plugin found"); - auto gpus = gpuPlugin->make(); - cr_assert(gpus.size() > 0, "No GPUs found"); + auto gpus = gpuPlugin->make(); + cr_assert(gpus.size() > 0, "No GPUs found"); - // Just get first cpu - auto &gpu = gpus.front(); + // Just get first cpu + auto &gpu = gpus.front(); - // Allocate memory on GPU and make accessible by to PCIe/FPGA - auto gpuRam = gpu->getAllocator().allocate(SAMPLE_COUNT + 1); - cr_assert(gpu->makeAccessibleToPCIeAndVA(gpuRam.getMemoryBlock())); + // Allocate memory on GPU and make accessible by to PCIe/FPGA + auto gpuRam = gpu->getAllocator().allocate(SAMPLE_COUNT + 1); + cr_assert(gpu->makeAccessibleToPCIeAndVA(gpuRam.getMemoryBlock())); - // Make Gpu2Rtds IP register memory on FPGA accessible to GPU - cr_assert(gpu->makeAccessibleFromPCIeOrHostRam(gpu2rtds->getRegisterMemory())); + // Make Gpu2Rtds IP register memory on FPGA accessible to GPU + cr_assert( + gpu->makeAccessibleFromPCIeOrHostRam(gpu2rtds->getRegisterMemory())); - auto tr = gpu->translate(gpuRam.getMemoryBlock()); + auto tr = gpu->translate(gpuRam.getMemoryBlock()); - auto dataIn = reinterpret_cast(tr.getLocalAddr(DATA_OFFSET * sizeof(uint32_t))); - auto doorbellIn = reinterpret_cast(tr.getLocalAddr(DOORBELL_OFFSET * sizeof(uint32_t))); + auto dataIn = reinterpret_cast( + tr.getLocalAddr(DATA_OFFSET * sizeof(uint32_t))); + auto doorbellIn = reinterpret_cast( + tr.getLocalAddr(DOORBELL_OFFSET * sizeof(uint32_t))); - auto gpu2rtdsRegisters = gpu->translate(gpu2rtds->getRegisterMemory()); + auto gpu2rtdsRegisters = gpu->translate(gpu2rtds->getRegisterMemory()); - auto frameRegister = reinterpret_cast(gpu2rtdsRegisters.getLocalAddr(gpu2rtds->registerFrameOffset)); - auto controlRegister = reinterpret_cast(gpu2rtdsRegisters.getLocalAddr(gpu2rtds->registerControlAddr)); + auto frameRegister = reinterpret_cast( + gpu2rtdsRegisters.getLocalAddr(gpu2rtds->registerFrameOffset)); + auto controlRegister = reinterpret_cast( + gpu2rtdsRegisters.getLocalAddr(gpu2rtds->registerControlAddr)); -// auto doorbellInCpu = reinterpret_cast(&gpuRam[DOORBELL_OFFSET]); + // auto doorbellInCpu = reinterpret_cast(&gpuRam[DOORBELL_OFFSET]); - for (auto &ip : state.cards.front()->ips) { - if (*ip != fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")) - continue; + for (auto &ip : state.cards.front()->ips) { + if (*ip != fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")) + continue; - auto &rtds = dynamic_cast(*ip); - logger->info("Testing {}", rtds); + auto &rtds = dynamic_cast(*ip); + logger->info("Testing {}", rtds); - // TEST: rtds loopback via switch, this should always work and have RTT=1 - //cr_assert(rtds.connect(rtds)); - //logger->info("loopback"); - //while (1); + // TEST: rtds loopback via switch, this should always work and have RTT=1 + //cr_assert(rtds.connect(rtds)); + //logger->info("loopback"); + //while (1); - cr_assert(rtds.connect(*rtds2gpu)); - cr_assert(gpu2rtds->connect(rtds)); + cr_assert(rtds.connect(*rtds2gpu)); + cr_assert(gpu2rtds->connect(rtds)); - // Launch once so they are configured - cr_assert(rtds2gpu->startOnce(gpuRam.getMemoryBlock(), SAMPLE_COUNT, DATA_OFFSET * 4, DOORBELL_OFFSET * 4)); - cr_assert(gpu2rtds->startOnce(SAMPLE_COUNT)); + // Launch once so they are configured + cr_assert(rtds2gpu->startOnce(gpuRam.getMemoryBlock(), SAMPLE_COUNT, + DATA_OFFSET * 4, DOORBELL_OFFSET * 4)); + cr_assert(gpu2rtds->startOnce(SAMPLE_COUNT)); - rtds2gpu->setAutoRestart(true); - rtds2gpu->start(); + rtds2gpu->setAutoRestart(true); + rtds2gpu->start(); - logger->info("GPU RTT RTDS"); + logger->info("GPU RTT RTDS"); - std::string dummy; + std::string dummy; - gpu_rtds_rtt_start(dataIn, doorbellIn, frameRegister, controlRegister); + gpu_rtds_rtt_start(dataIn, doorbellIn, frameRegister, controlRegister); -// while (1) { -// cr_assert(rtds2gpu->startOnce(gpuRam.getMemoryBlock(), SAMPLE_COUNT, DATA_OFFSET * 4, DOORBELL_OFFSET * 4)); -// } + // while (1) { + // cr_assert(rtds2gpu->startOnce(gpuRam.getMemoryBlock(), SAMPLE_COUNT, DATA_OFFSET * 4, DOORBELL_OFFSET * 4)); + // } -// for (int i = 0; i < 10000; i++) { -// while (not doorbellInCpu->is_valid); -// logger->debug("received data"); -// } + // for (int i = 0; i < 10000; i++) { + // while (not doorbellInCpu->is_valid); + // logger->debug("received data"); + // } -// logger->info("Press enter to cancel"); -// std::cin >> dummy; + // logger->info("Press enter to cancel"); + // std::cin >> dummy; - while (1) { - sleep(1); -// logger->debug("Current sequence number: {}", doorbellInCpu->seq_nr); - logger->debug("Still running"); - } + while (1) { + sleep(1); + // logger->debug("Current sequence number: {}", doorbellInCpu->seq_nr); + logger->debug("Still running"); + } - gpu_rtds_rtt_stop(); + gpu_rtds_rtt_stop(); - logger->info(CLR_GRN("Passed")); - } + logger->info(CLR_GRN("Passed")); + } } diff --git a/fpga/tests/unit/rtds_rtt.cpp b/fpga/tests/unit/rtds_rtt.cpp index 0d35de117..273b46404 100644 --- a/fpga/tests/unit/rtds_rtt.cpp +++ b/fpga/tests/unit/rtds_rtt.cpp @@ -11,73 +11,72 @@ #include #include -#include #include +#include extern struct fpga_card *card; // cppcheck-suppress unknownMacro -Test(fpga, rtds_rtt, .description = "RTDS: tight rtt") -{ - int ret; - struct fpga_ip *ip, *rtds; - struct dma_mem buf; - size_t recvlen; +Test(fpga, rtds_rtt, .description = "RTDS: tight rtt") { + int ret; + struct fpga_ip *ip, *rtds; + struct dma_mem buf; + size_t recvlen; - std::list rtdsIps; - std::list dmaIps; + std::list rtdsIps; + std::list dmaIps; - // Get IP cores - for (auto &ip : state.cards.front()->ips) { - if (*ip == villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")) { - auto rtds = reinterpret_cast(ip.get()); - rtdsIps.push_back(rtds); - } + // Get IP cores + for (auto &ip : state.cards.front()->ips) { + if (*ip == + villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")) { + auto rtds = reinterpret_cast(ip.get()); + rtdsIps.push_back(rtds); + } - if (*ip == villas::fpga::Vlnv("xilinx.com:ip:axi_dma:")) { - auto dma = reinterpret_cast(ip.get()); - dmaIps.push_back(dma); - } - } + if (*ip == villas::fpga::Vlnv("xilinx.com:ip:axi_dma:")) { + auto dma = reinterpret_cast(ip.get()); + dmaIps.push_back(dma); + } + } - for (auto rtds : rtdsIps) { - for (auto dma : dmaIps) { + for (auto rtds : rtdsIps) { + for (auto dma : dmaIps) { - rtds->connect + rtds->connect + } + } - } - } + ret = switch_connect(card->sw, rtds, ip); + cr_assert_eq(ret, 0, "Failed to configure switch"); - ret = switch_connect(card->sw, rtds, ip); - cr_assert_eq(ret, 0, "Failed to configure switch"); + ret = switch_connect(card->sw, ip, rtds); + cr_assert_eq(ret, 0, "Failed to configure switch"); - ret = switch_connect(card->sw, ip, rtds); - cr_assert_eq(ret, 0, "Failed to configure switch"); + ret = dma_alloc(ip, &buf, 0x100, 0); + cr_assert_eq(ret, 0, "Failed to allocate DMA memory"); - ret = dma_alloc(ip, &buf, 0x100, 0); - cr_assert_eq(ret, 0, "Failed to allocate DMA memory"); + while (1) { - while (1) { + ret = dma_read(ip, buf.base_phys, buf.len); + cr_assert_eq(ret, 0, "Failed to start DMA read: %d", ret); - ret = dma_read(ip, buf.base_phys, buf.len); - cr_assert_eq(ret, 0, "Failed to start DMA read: %d", ret); + ret = dma_read_complete(ip, NULL, &recvlen); + cr_assert_eq(ret, 0, "Failed to complete DMA read: %d", ret); - ret = dma_read_complete(ip, NULL, &recvlen); - cr_assert_eq(ret, 0, "Failed to complete DMA read: %d", ret); + ret = dma_write(ip, buf.base_phys, recvlen); + cr_assert_eq(ret, 0, "Failed to start DMA write: %d", ret); - ret = dma_write(ip, buf.base_phys, recvlen); - cr_assert_eq(ret, 0, "Failed to start DMA write: %d", ret); + ret = dma_write_complete(ip, NULL, NULL); + cr_assert_eq(ret, 0, "Failed to complete DMA write: %d", ret); + } - ret = dma_write_complete(ip, NULL, NULL); - cr_assert_eq(ret, 0, "Failed to complete DMA write: %d", ret); - } + ret = switch_disconnect(card->sw, rtds, ip); + cr_assert_eq(ret, 0, "Failed to configure switch"); - ret = switch_disconnect(card->sw, rtds, ip); - cr_assert_eq(ret, 0, "Failed to configure switch"); + ret = switch_disconnect(card->sw, ip, rtds); + cr_assert_eq(ret, 0, "Failed to configure switch"); - ret = switch_disconnect(card->sw, ip, rtds); - cr_assert_eq(ret, 0, "Failed to configure switch"); - - ret = dma_free(ip, &buf); - cr_assert_eq(ret, 0, "Failed to release DMA memory"); + ret = dma_free(ip, &buf); + cr_assert_eq(ret, 0, "Failed to release DMA memory"); } diff --git a/fpga/tests/unit/timer.cpp b/fpga/tests/unit/timer.cpp index 8b8d748d8..23e518643 100644 --- a/fpga/tests/unit/timer.cpp +++ b/fpga/tests/unit/timer.cpp @@ -7,52 +7,53 @@ #include #include -#include #include #include +#include -#include #include "global.hpp" +#include // cppcheck-suppress unknownMacro -Test(fpga, timer, .description = "Timer Counter") -{ - auto logger = villas::logging.get("unit-test:timer"); +Test(fpga, timer, .description = "Timer Counter") { + auto logger = villas::logging.get("unit-test:timer"); - size_t count = 0; - for (auto &ip : state.cards.front()->ips) { - // Skip non-timer IPs - if (*ip != villas::fpga::Vlnv("xilinx.com:ip:axi_timer:")) - continue; + size_t count = 0; + for (auto &ip : state.cards.front()->ips) { + // Skip non-timer IPs + if (*ip != villas::fpga::Vlnv("xilinx.com:ip:axi_timer:")) + continue; - logger->info("Testing {}", *ip); + logger->info("Testing {}", *ip); - auto timer = dynamic_cast(*ip); + auto timer = dynamic_cast(*ip); - logger->info("Test simple waiting"); - timer.start(timer.getFrequency() / 10); - cr_assert(timer.wait(), "Waiting failed"); + logger->info("Test simple waiting"); + timer.start(timer.getFrequency() / 10); + cr_assert(timer.wait(), "Waiting failed"); - logger->info(CLR_GRN("Passed")); + logger->info(CLR_GRN("Passed")); - logger->info("Measure waiting time (1s)"); + logger->info("Measure waiting time (1s)"); - timer.start(timer.getFrequency()); - const auto start = std::chrono::high_resolution_clock::now(); + timer.start(timer.getFrequency()); + const auto start = std::chrono::high_resolution_clock::now(); - timer.wait(); - const auto stop = std::chrono::high_resolution_clock::now(); + timer.wait(); + const auto stop = std::chrono::high_resolution_clock::now(); - const int oneSecondInUs = 1000000; - const auto duration = stop - start; - const auto durationUs = std::chrono::duration_cast(duration).count(); + const int oneSecondInUs = 1000000; + const auto duration = stop - start; + const auto durationUs = + std::chrono::duration_cast(duration).count(); - cr_assert(std::abs(durationUs - oneSecondInUs) < 0.01 * oneSecondInUs, "Timer deviation > 1%%"); + cr_assert(std::abs(durationUs - oneSecondInUs) < 0.01 * oneSecondInUs, + "Timer deviation > 1%%"); - logger->info(CLR_GRN("Passed:") " Time passed: {} us", durationUs); + logger->info(CLR_GRN("Passed:") " Time passed: {} us", durationUs); - count++; - } + count++; + } - cr_assert(count > 0, "No timer found"); + cr_assert(count > 0, "No timer found"); } diff --git a/fpga/thirdparty/CLI11/CLI11.hpp b/fpga/thirdparty/CLI11/CLI11.hpp index f40619566..c439fd0d9 100644 --- a/fpga/thirdparty/CLI11/CLI11.hpp +++ b/fpga/thirdparty/CLI11/CLI11.hpp @@ -10,27 +10,27 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include +#include +#include +#include +#include #include -#include +#include +#include // From CLI/Version.hpp @@ -53,174 +53,188 @@ namespace detail { // Based on http://stackoverflow.com/questions/236129/split-a-string-in-c /// Split a string by a delim inline std::vector split(const std::string &s, char delim) { - std::vector elems; - // Check to see if empty string, give consistent result - if(s.empty()) - elems.emplace_back(""); - else { - std::stringstream ss; - ss.str(s); - std::string item; - while(std::getline(ss, item, delim)) { - elems.push_back(item); - } + std::vector elems; + // Check to see if empty string, give consistent result + if (s.empty()) + elems.emplace_back(""); + else { + std::stringstream ss; + ss.str(s); + std::string item; + while (std::getline(ss, item, delim)) { + elems.push_back(item); } - return elems; + } + return elems; } /// Simple function to join a string template std::string join(const T &v, std::string delim = ",") { - std::ostringstream s; - size_t start = 0; - for(const auto &i : v) { - if(start++ > 0) - s << delim; - s << i; - } - return s.str(); + std::ostringstream s; + size_t start = 0; + for (const auto &i : v) { + if (start++ > 0) + s << delim; + s << i; + } + return s.str(); } /// Join a string in reverse order template std::string rjoin(const T &v, std::string delim = ",") { - std::ostringstream s; - for(size_t start = 0; start < v.size(); start++) { - if(start > 0) - s << delim; - s << v[v.size() - start - 1]; - } - return s.str(); + std::ostringstream s; + for (size_t start = 0; start < v.size(); start++) { + if (start > 0) + s << delim; + s << v[v.size() - start - 1]; + } + return s.str(); } // Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string /// Trim whitespace from left of string inline std::string <rim(std::string &str) { - auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace(ch, std::locale()); }); - str.erase(str.begin(), it); - return str; + auto it = std::find_if(str.begin(), str.end(), [](char ch) { + return !std::isspace(ch, std::locale()); + }); + str.erase(str.begin(), it); + return str; } /// Trim anything from left of string inline std::string <rim(std::string &str, const std::string &filter) { - auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { return filter.find(ch) == std::string::npos; }); - str.erase(str.begin(), it); - return str; + auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { + return filter.find(ch) == std::string::npos; + }); + str.erase(str.begin(), it); + return str; } /// Trim whitespace from right of string inline std::string &rtrim(std::string &str) { - auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace(ch, std::locale()); }); - str.erase(it.base(), str.end()); - return str; + auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { + return !std::isspace(ch, std::locale()); + }); + str.erase(it.base(), str.end()); + return str; } /// Trim anything from right of string inline std::string &rtrim(std::string &str, const std::string &filter) { - auto it = - std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { return filter.find(ch) == std::string::npos; }); - str.erase(it.base(), str.end()); - return str; + auto it = std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { + return filter.find(ch) == std::string::npos; + }); + str.erase(it.base(), str.end()); + return str; } /// Trim whitespace from string inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); } /// Trim anything from string -inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); } +inline std::string &trim(std::string &str, const std::string filter) { + return ltrim(rtrim(str, filter), filter); +} /// Make a copy of the string and then trim it inline std::string trim_copy(const std::string &str) { - std::string s = str; - return trim(s); + std::string s = str; + return trim(s); } /// Make a copy of the string and then trim it, any filter string can be used (any char in string is filtered) -inline std::string trim_copy(const std::string &str, const std::string &filter) { - std::string s = str; - return trim(s, filter); +inline std::string trim_copy(const std::string &str, + const std::string &filter) { + std::string s = str; + return trim(s, filter); } /// Print a two part "help" string -inline void format_help(std::stringstream &out, std::string name, std::string description, size_t wid) { - name = " " + name; - out << std::setw(static_cast(wid)) << std::left << name; - if(!description.empty()) { - if(name.length() >= wid) - out << std::endl << std::setw(static_cast(wid)) << ""; - out << description; - } - out << std::endl; +inline void format_help(std::stringstream &out, std::string name, + std::string description, size_t wid) { + name = " " + name; + out << std::setw(static_cast(wid)) << std::left << name; + if (!description.empty()) { + if (name.length() >= wid) + out << std::endl << std::setw(static_cast(wid)) << ""; + out << description; + } + out << std::endl; } /// Verify the first character of an option -template bool valid_first_char(T c) { return std::isalpha(c, std::locale()) || c == '_'; } +template bool valid_first_char(T c) { + return std::isalpha(c, std::locale()) || c == '_'; +} /// Verify following characters of an option template bool valid_later_char(T c) { - return std::isalnum(c, std::locale()) || c == '_' || c == '.' || c == '-'; + return std::isalnum(c, std::locale()) || c == '_' || c == '.' || c == '-'; } /// Verify an option name inline bool valid_name_string(const std::string &str) { - if(str.empty() || !valid_first_char(str[0])) - return false; - for(auto c : str.substr(1)) - if(!valid_later_char(c)) - return false; - return true; + if (str.empty() || !valid_first_char(str[0])) + return false; + for (auto c : str.substr(1)) + if (!valid_later_char(c)) + return false; + return true; } /// Return a lower case version of a string inline std::string to_lower(std::string str) { - std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) { - return std::tolower(x, std::locale()); - }); - return str; + std::transform(std::begin(str), std::end(str), std::begin(str), + [](const std::string::value_type &x) { + return std::tolower(x, std::locale()); + }); + return str; } /// Split a string '"one two" "three"' into 'one two', 'three' inline std::vector split_up(std::string str) { - std::vector delims = {'\'', '\"'}; - auto find_ws = [](char ch) { return std::isspace(ch, std::locale()); }; - trim(str); + std::vector delims = {'\'', '\"'}; + auto find_ws = [](char ch) { return std::isspace(ch, std::locale()); }; + trim(str); - std::vector output; + std::vector output; - while(!str.empty()) { - if(str[0] == '\'') { - auto end = str.find('\'', 1); - if(end != std::string::npos) { - output.push_back(str.substr(1, end - 1)); - str = str.substr(end + 1); - } else { - output.push_back(str.substr(1)); - str = ""; - } - } else if(str[0] == '\"') { - auto end = str.find('\"', 1); - if(end != std::string::npos) { - output.push_back(str.substr(1, end - 1)); - str = str.substr(end + 1); - } else { - output.push_back(str.substr(1)); - str = ""; - } + while (!str.empty()) { + if (str[0] == '\'') { + auto end = str.find('\'', 1); + if (end != std::string::npos) { + output.push_back(str.substr(1, end - 1)); + str = str.substr(end + 1); + } else { + output.push_back(str.substr(1)); + str = ""; + } + } else if (str[0] == '\"') { + auto end = str.find('\"', 1); + if (end != std::string::npos) { + output.push_back(str.substr(1, end - 1)); + str = str.substr(end + 1); + } else { + output.push_back(str.substr(1)); + str = ""; + } - } else { - auto it = std::find_if(std::begin(str), std::end(str), find_ws); - if(it != std::end(str)) { - std::string value = std::string(str.begin(), it); - output.push_back(value); - str = std::string(it, str.end()); - } else { - output.push_back(str); - str = ""; - } - } - trim(str); + } else { + auto it = std::find_if(std::begin(str), std::end(str), find_ws); + if (it != std::end(str)) { + std::string value = std::string(str.begin(), it); + output.push_back(value); + str = std::string(it, str.end()); + } else { + output.push_back(str); + str = ""; + } } + trim(str); + } - return output; + return output; } /// Add a leader to the beginning of all new lines (nothing is added @@ -228,15 +242,15 @@ inline std::vector split_up(std::string str) { /// /// Can't use Regex, or this would be a subs. inline std::string fix_newlines(std::string leader, std::string input) { - std::string::size_type n = 0; - while(n != std::string::npos && n < input.size()) { - n = input.find('\n', n); - if(n != std::string::npos) { - input = input.substr(0, n + 1) + leader + input.substr(n + 1); - n += leader.size(); - } + std::string::size_type n = 0; + while (n != std::string::npos && n < input.size()) { + n = input.find('\n', n); + if (n != std::string::npos) { + input = input.substr(0, n + 1) + leader + input.substr(n + 1); + n += leader.size(); } - return input; + } + return input; } } // namespace detail @@ -247,40 +261,43 @@ inline std::string fix_newlines(std::string leader, std::string input) { namespace CLI { // Use one of these on all error classes -#define CLI11_ERROR_DEF(parent, name) \ - protected: \ - name(std::string name, std::string msg, int exit_code) : parent(std::move(name), std::move(msg), exit_code) {} \ - name(std::string name, std::string msg, ExitCodes exit_code) \ - : parent(std::move(name), std::move(msg), exit_code) {} \ - \ - public: \ - name(std::string msg, ExitCodes exit_code) : parent(#name, std::move(msg), exit_code) {} \ - name(std::string msg, int exit_code) : parent(#name, std::move(msg), exit_code) {} +#define CLI11_ERROR_DEF(parent, name) \ +protected: \ + name(std::string name, std::string msg, int exit_code) \ + : parent(std::move(name), std::move(msg), exit_code) {} \ + name(std::string name, std::string msg, ExitCodes exit_code) \ + : parent(std::move(name), std::move(msg), exit_code) {} \ + \ +public: \ + name(std::string msg, ExitCodes exit_code) \ + : parent(#name, std::move(msg), exit_code) {} \ + name(std::string msg, int exit_code) \ + : parent(#name, std::move(msg), exit_code) {} // This is added after the one above if a class is used directly and builds its own message -#define CLI11_ERROR_SIMPLE(name) \ - name(std::string msg) : name(#name, msg, ExitCodes::name) {} +#define CLI11_ERROR_SIMPLE(name) \ + name(std::string msg) : name(#name, msg, ExitCodes::name) {} /// These codes are part of every error in CLI. They can be obtained from e using e.exit_code or as a quick shortcut, /// int values from e.get_error_code(). enum class ExitCodes { - Success = 0, - IncorrectConstruction = 100, - BadNameString, - OptionAlreadyAdded, - FileError, - ConversionError, - ValidationError, - RequiredError, - RequiresError, - ExcludesError, - ExtrasError, - INIError, - InvalidError, - HorribleError, - OptionNotFound, - ArgumentMismatch, - BaseClass = 127 + Success = 0, + IncorrectConstruction = 100, + BadNameString, + OptionAlreadyAdded, + FileError, + ConversionError, + ValidationError, + RequiredError, + RequiresError, + ExcludesError, + ExtrasError, + INIError, + InvalidError, + HorribleError, + OptionNotFound, + ArgumentMismatch, + BaseClass = 127 }; // Error definitions @@ -293,223 +310,263 @@ enum class ExitCodes { /// All errors derive from this one class Error : public std::runtime_error { - int exit_code; - std::string name{"Error"}; + int exit_code; + std::string name{"Error"}; - public: - int get_exit_code() const { return exit_code; } +public: + int get_exit_code() const { return exit_code; } - std::string get_name() const { return name; } + std::string get_name() const { return name; } - Error(std::string name, std::string msg, int exit_code = static_cast(ExitCodes::BaseClass)) - : runtime_error(msg), exit_code(exit_code), name(std::move(name)) {} + Error(std::string name, std::string msg, + int exit_code = static_cast(ExitCodes::BaseClass)) + : runtime_error(msg), exit_code(exit_code), name(std::move(name)) {} - Error(std::string name, std::string msg, ExitCodes exit_code) : Error(name, msg, static_cast(exit_code)) {} + Error(std::string name, std::string msg, ExitCodes exit_code) + : Error(name, msg, static_cast(exit_code)) {} }; // Note: Using Error::Error constructors does not work on GCC 4.7 /// Construction errors (not in parsing) class ConstructionError : public Error { - CLI11_ERROR_DEF(Error, ConstructionError) + CLI11_ERROR_DEF(Error, ConstructionError) }; /// Thrown when an option is set to conflicting values (non-vector and multi args, for example) class IncorrectConstruction : public ConstructionError { - CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction) - CLI11_ERROR_SIMPLE(IncorrectConstruction) - static IncorrectConstruction PositionalFlag(std::string name) { - return IncorrectConstruction(name + ": Flags cannot be positional"); - } - static IncorrectConstruction Set0Opt(std::string name) { - return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead"); - } - static IncorrectConstruction ChangeNotVector(std::string name) { - return IncorrectConstruction(name + ": You can only change the expected arguments for vectors"); - } - static IncorrectConstruction AfterMultiOpt(std::string name) { - return IncorrectConstruction( - name + ": You can't change expected arguments after you've changed the multi option policy!"); - } - static IncorrectConstruction MissingOption(std::string name) { - return IncorrectConstruction("Option " + name + " is not defined"); - } - static IncorrectConstruction MultiOptionPolicy(std::string name) { - return IncorrectConstruction(name + ": multi_option_policy only works for flags and single value options"); - } + CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction) + CLI11_ERROR_SIMPLE(IncorrectConstruction) + static IncorrectConstruction PositionalFlag(std::string name) { + return IncorrectConstruction(name + ": Flags cannot be positional"); + } + static IncorrectConstruction Set0Opt(std::string name) { + return IncorrectConstruction(name + + ": Cannot set 0 expected, use a flag instead"); + } + static IncorrectConstruction ChangeNotVector(std::string name) { + return IncorrectConstruction( + name + ": You can only change the expected arguments for vectors"); + } + static IncorrectConstruction AfterMultiOpt(std::string name) { + return IncorrectConstruction(name + + ": You can't change expected arguments after " + "you've changed the multi option policy!"); + } + static IncorrectConstruction MissingOption(std::string name) { + return IncorrectConstruction("Option " + name + " is not defined"); + } + static IncorrectConstruction MultiOptionPolicy(std::string name) { + return IncorrectConstruction( + name + + ": multi_option_policy only works for flags and single value options"); + } }; /// Thrown on construction of a bad name class BadNameString : public ConstructionError { - CLI11_ERROR_DEF(ConstructionError, BadNameString) - CLI11_ERROR_SIMPLE(BadNameString) - static BadNameString OneCharName(std::string name) { return BadNameString("Invalid one char name: " + name); } - static BadNameString BadLongName(std::string name) { return BadNameString("Bad long name: " + name); } - static BadNameString DashesOnly(std::string name) { - return BadNameString("Must have a name, not just dashes: " + name); - } - static BadNameString MultiPositionalNames(std::string name) { - return BadNameString("Only one positional name allowed, remove: " + name); - } + CLI11_ERROR_DEF(ConstructionError, BadNameString) + CLI11_ERROR_SIMPLE(BadNameString) + static BadNameString OneCharName(std::string name) { + return BadNameString("Invalid one char name: " + name); + } + static BadNameString BadLongName(std::string name) { + return BadNameString("Bad long name: " + name); + } + static BadNameString DashesOnly(std::string name) { + return BadNameString("Must have a name, not just dashes: " + name); + } + static BadNameString MultiPositionalNames(std::string name) { + return BadNameString("Only one positional name allowed, remove: " + name); + } }; /// Thrown when an option already exists class OptionAlreadyAdded : public ConstructionError { - CLI11_ERROR_DEF(ConstructionError, OptionAlreadyAdded) - OptionAlreadyAdded(std::string name) - : OptionAlreadyAdded(name + " is already added", ExitCodes::OptionAlreadyAdded) {} - static OptionAlreadyAdded Requires(std::string name, std::string other) { - return OptionAlreadyAdded(name + " requires " + other, ExitCodes::OptionAlreadyAdded); - } - static OptionAlreadyAdded Excludes(std::string name, std::string other) { - return OptionAlreadyAdded(name + " excludes " + other, ExitCodes::OptionAlreadyAdded); - } + CLI11_ERROR_DEF(ConstructionError, OptionAlreadyAdded) + OptionAlreadyAdded(std::string name) + : OptionAlreadyAdded(name + " is already added", + ExitCodes::OptionAlreadyAdded) {} + static OptionAlreadyAdded Requires(std::string name, std::string other) { + return OptionAlreadyAdded(name + " requires " + other, + ExitCodes::OptionAlreadyAdded); + } + static OptionAlreadyAdded Excludes(std::string name, std::string other) { + return OptionAlreadyAdded(name + " excludes " + other, + ExitCodes::OptionAlreadyAdded); + } }; // Parsing errors /// Anything that can error in Parse class ParseError : public Error { - CLI11_ERROR_DEF(Error, ParseError) + CLI11_ERROR_DEF(Error, ParseError) }; // Not really "errors" /// This is a successful completion on parsing, supposed to exit class Success : public ParseError { - CLI11_ERROR_DEF(ParseError, Success) - Success() : Success("Successfully completed, should be caught and quit", ExitCodes::Success) {} + CLI11_ERROR_DEF(ParseError, Success) + Success() + : Success("Successfully completed, should be caught and quit", + ExitCodes::Success) {} }; /// -h or --help on command line class CallForHelp : public ParseError { - CLI11_ERROR_DEF(ParseError, CallForHelp) - CallForHelp() : CallForHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} + CLI11_ERROR_DEF(ParseError, CallForHelp) + CallForHelp() + : CallForHelp("This should be caught in your main function, see examples", + ExitCodes::Success) {} }; /// Does not output a diagnostic in CLI11_PARSE, but allows to return from main() with a specific error code. class RuntimeError : public ParseError { - CLI11_ERROR_DEF(ParseError, RuntimeError) - RuntimeError(int exit_code = 1) : RuntimeError("Runtime error", exit_code) {} + CLI11_ERROR_DEF(ParseError, RuntimeError) + RuntimeError(int exit_code = 1) : RuntimeError("Runtime error", exit_code) {} }; /// Thrown when parsing an INI file and it is missing class FileError : public ParseError { - CLI11_ERROR_DEF(ParseError, FileError) - CLI11_ERROR_SIMPLE(FileError) - static FileError Missing(std::string name) { return FileError(name + " was not readable (missing?)"); } + CLI11_ERROR_DEF(ParseError, FileError) + CLI11_ERROR_SIMPLE(FileError) + static FileError Missing(std::string name) { + return FileError(name + " was not readable (missing?)"); + } }; /// Thrown when conversion call back fails, such as when an int fails to coerce to a string class ConversionError : public ParseError { - CLI11_ERROR_DEF(ParseError, ConversionError) - CLI11_ERROR_SIMPLE(ConversionError) - ConversionError(std::string member, std::string name) - : ConversionError("The value " + member + " is not an allowed value for " + name) {} - ConversionError(std::string name, std::vector results) - : ConversionError("Could not convert: " + name + " = " + detail::join(results)) {} - static ConversionError TooManyInputsFlag(std::string name) { - return ConversionError(name + ": too many inputs for a flag"); - } - static ConversionError TrueFalse(std::string name) { - return ConversionError(name + ": Should be true/false or a number"); - } + CLI11_ERROR_DEF(ParseError, ConversionError) + CLI11_ERROR_SIMPLE(ConversionError) + ConversionError(std::string member, std::string name) + : ConversionError("The value " + member + + " is not an allowed value for " + name) {} + ConversionError(std::string name, std::vector results) + : ConversionError("Could not convert: " + name + " = " + + detail::join(results)) {} + static ConversionError TooManyInputsFlag(std::string name) { + return ConversionError(name + ": too many inputs for a flag"); + } + static ConversionError TrueFalse(std::string name) { + return ConversionError(name + ": Should be true/false or a number"); + } }; /// Thrown when validation of results fails class ValidationError : public ParseError { - CLI11_ERROR_DEF(ParseError, ValidationError) - CLI11_ERROR_SIMPLE(ValidationError) - ValidationError(std::string name, std::string msg) : ValidationError(name + ": " + msg) {} + CLI11_ERROR_DEF(ParseError, ValidationError) + CLI11_ERROR_SIMPLE(ValidationError) + ValidationError(std::string name, std::string msg) + : ValidationError(name + ": " + msg) {} }; /// Thrown when a required option is missing class RequiredError : public ParseError { - CLI11_ERROR_DEF(ParseError, RequiredError) - RequiredError(std::string name) : RequiredError(name + " is required", ExitCodes::RequiredError) {} - static RequiredError Subcommand(size_t min_subcom) { - if(min_subcom == 1) - return RequiredError("A subcommand"); - else - return RequiredError("Requires at least " + std::to_string(min_subcom) + " subcommands", - ExitCodes::RequiredError); - } + CLI11_ERROR_DEF(ParseError, RequiredError) + RequiredError(std::string name) + : RequiredError(name + " is required", ExitCodes::RequiredError) {} + static RequiredError Subcommand(size_t min_subcom) { + if (min_subcom == 1) + return RequiredError("A subcommand"); + else + return RequiredError("Requires at least " + std::to_string(min_subcom) + + " subcommands", + ExitCodes::RequiredError); + } }; /// Thrown when the wrong number of arguments has been received class ArgumentMismatch : public ParseError { - CLI11_ERROR_DEF(ParseError, ArgumentMismatch) - CLI11_ERROR_SIMPLE(ArgumentMismatch) - ArgumentMismatch(std::string name, int expected, size_t recieved) - : ArgumentMismatch(expected > 0 ? ("Expected exactly " + std::to_string(expected) + " arguments to " + name + - ", got " + std::to_string(recieved)) - : ("Expected at least " + std::to_string(-expected) + " arguments to " + name + - ", got " + std::to_string(recieved)), - ExitCodes::ArgumentMismatch) {} + CLI11_ERROR_DEF(ParseError, ArgumentMismatch) + CLI11_ERROR_SIMPLE(ArgumentMismatch) + ArgumentMismatch(std::string name, int expected, size_t recieved) + : ArgumentMismatch(expected > 0 + ? ("Expected exactly " + std::to_string(expected) + + " arguments to " + name + ", got " + + std::to_string(recieved)) + : ("Expected at least " + + std::to_string(-expected) + " arguments to " + + name + ", got " + std::to_string(recieved)), + ExitCodes::ArgumentMismatch) {} - static ArgumentMismatch AtLeast(std::string name, int num) { - return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required"); - } - static ArgumentMismatch TypedAtLeast(std::string name, int num, std::string type) { - return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing"); - } + static ArgumentMismatch AtLeast(std::string name, int num) { + return ArgumentMismatch(name + ": At least " + std::to_string(num) + + " required"); + } + static ArgumentMismatch TypedAtLeast(std::string name, int num, + std::string type) { + return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + + type + " missing"); + } }; /// Thrown when a requires option is missing class RequiresError : public ParseError { - CLI11_ERROR_DEF(ParseError, RequiresError) - RequiresError(std::string curname, std::string subname) - : RequiresError(curname + " requires " + subname, ExitCodes::RequiresError) {} + CLI11_ERROR_DEF(ParseError, RequiresError) + RequiresError(std::string curname, std::string subname) + : RequiresError(curname + " requires " + subname, + ExitCodes::RequiresError) {} }; /// Thrown when an excludes option is present class ExcludesError : public ParseError { - CLI11_ERROR_DEF(ParseError, ExcludesError) - ExcludesError(std::string curname, std::string subname) - : ExcludesError(curname + " excludes " + subname, ExitCodes::ExcludesError) {} + CLI11_ERROR_DEF(ParseError, ExcludesError) + ExcludesError(std::string curname, std::string subname) + : ExcludesError(curname + " excludes " + subname, + ExitCodes::ExcludesError) {} }; /// Thrown when too many positionals or options are found class ExtrasError : public ParseError { - CLI11_ERROR_DEF(ParseError, ExtrasError) - ExtrasError(std::vector args) - : ExtrasError((args.size() > 1 ? "The following arguments were not expected: " - : "The following argument was not expected: ") + - detail::rjoin(args, " "), - ExitCodes::ExtrasError) {} + CLI11_ERROR_DEF(ParseError, ExtrasError) + ExtrasError(std::vector args) + : ExtrasError((args.size() > 1 + ? "The following arguments were not expected: " + : "The following argument was not expected: ") + + detail::rjoin(args, " "), + ExitCodes::ExtrasError) {} }; /// Thrown when extra values are found in an INI file class INIError : public ParseError { - CLI11_ERROR_DEF(ParseError, INIError) - CLI11_ERROR_SIMPLE(INIError) - static INIError Extras(std::string item) { return INIError("INI was not able to parse " + item); } - static INIError NotConfigurable(std::string item) { - return INIError(item + ": This option is not allowed in a configuration file"); - } + CLI11_ERROR_DEF(ParseError, INIError) + CLI11_ERROR_SIMPLE(INIError) + static INIError Extras(std::string item) { + return INIError("INI was not able to parse " + item); + } + static INIError NotConfigurable(std::string item) { + return INIError(item + + ": This option is not allowed in a configuration file"); + } }; /// Thrown when validation fails before parsing class InvalidError : public ParseError { - CLI11_ERROR_DEF(ParseError, InvalidError) - InvalidError(std::string name) - : InvalidError(name + ": Too many positional arguments with unlimited expected args", ExitCodes::InvalidError) { - } + CLI11_ERROR_DEF(ParseError, InvalidError) + InvalidError(std::string name) + : InvalidError( + name + + ": Too many positional arguments with unlimited expected args", + ExitCodes::InvalidError) {} }; /// This is just a safety check to verify selection and parsing match - you should not ever see it /// Strings are directly added to this error, but again, it should never be seen. class HorribleError : public ParseError { - CLI11_ERROR_DEF(ParseError, HorribleError) - CLI11_ERROR_SIMPLE(HorribleError) + CLI11_ERROR_DEF(ParseError, HorribleError) + CLI11_ERROR_SIMPLE(HorribleError) }; // After parsing /// Thrown when counting a non-existent option class OptionNotFound : public Error { - CLI11_ERROR_DEF(Error, OptionNotFound) - OptionNotFound(std::string name) : OptionNotFound(name + " not found", ExitCodes::OptionNotFound) {} + CLI11_ERROR_DEF(Error, OptionNotFound) + OptionNotFound(std::string name) + : OptionNotFound(name + " not found", ExitCodes::OptionNotFound) {} }; /// @} @@ -526,11 +583,14 @@ namespace CLI { // (even Google does this: https://github.com/google/skia/blob/master/include/private/SkTLogic.h) // It is not in the std namespace anyway, so no harm done. -template using enable_if_t = typename std::enable_if::type; +template +using enable_if_t = typename std::enable_if::type; template struct is_vector { static const bool value = false; }; -template struct is_vector> { static bool const value = true; }; +template struct is_vector> { + static bool const value = true; +}; template struct is_bool { static const bool value = false; }; @@ -551,115 +611,129 @@ constexpr enabler dummy = {}; /// But this is cleaner and works better in this case template ::value && std::is_signed::value, detail::enabler> = detail::dummy> + enable_if_t::value && std::is_signed::value, + detail::enabler> = detail::dummy> constexpr const char *type_name() { - return "INT"; + return "INT"; } template ::value && std::is_unsigned::value, detail::enabler> = detail::dummy> + enable_if_t::value && std::is_unsigned::value, + detail::enabler> = detail::dummy> constexpr const char *type_name() { - return "UINT"; + return "UINT"; } -template ::value, detail::enabler> = detail::dummy> +template ::value, + detail::enabler> = detail::dummy> constexpr const char *type_name() { - return "FLOAT"; + return "FLOAT"; } /// This one should not be used, since vector types print the internal type -template ::value, detail::enabler> = detail::dummy> +template ::value, detail::enabler> = detail::dummy> constexpr const char *type_name() { - return "VECTOR"; + return "VECTOR"; } template ::value && !std::is_integral::value && !is_vector::value, + enable_if_t::value && + !std::is_integral::value && !is_vector::value, detail::enabler> = detail::dummy> constexpr const char *type_name() { - return "TEXT"; + return "TEXT"; } // Lexical cast /// Signed integers / enums -template ::value && std::is_signed::value) || std::is_enum::value, - detail::enabler> = detail::dummy> +template ::value && + std::is_signed::value) || + std::is_enum::value, + detail::enabler> = detail::dummy> bool lexical_cast(std::string input, T &output) { - try { - size_t n = 0; - long long output_ll = std::stoll(input, &n, 0); - output = static_cast(output_ll); - return n == input.size() && static_cast(output) == output_ll; - } catch(const std::invalid_argument &) { - return false; - } catch(const std::out_of_range &) { - return false; - } + try { + size_t n = 0; + long long output_ll = std::stoll(input, &n, 0); + output = static_cast(output_ll); + return n == input.size() && static_cast(output) == output_ll; + } catch (const std::invalid_argument &) { + return false; + } catch (const std::out_of_range &) { + return false; + } } /// Unsigned integers template ::value && std::is_unsigned::value, detail::enabler> = detail::dummy> + enable_if_t::value && std::is_unsigned::value, + detail::enabler> = detail::dummy> bool lexical_cast(std::string input, T &output) { - if(!input.empty() && input.front() == '-') - return false; // std::stoull happily converts negative values to junk without any errors. + if (!input.empty() && input.front() == '-') + return false; // std::stoull happily converts negative values to junk without any errors. - try { - size_t n = 0; - unsigned long long output_ll = std::stoull(input, &n, 0); - output = static_cast(output_ll); - return n == input.size() && static_cast(output) == output_ll; - } catch(const std::invalid_argument &) { - return false; - } catch(const std::out_of_range &) { - return false; - } + try { + size_t n = 0; + unsigned long long output_ll = std::stoull(input, &n, 0); + output = static_cast(output_ll); + return n == input.size() && + static_cast(output) == output_ll; + } catch (const std::invalid_argument &) { + return false; + } catch (const std::out_of_range &) { + return false; + } } /// Floats -template ::value, detail::enabler> = detail::dummy> +template ::value, + detail::enabler> = detail::dummy> bool lexical_cast(std::string input, T &output) { - try { - size_t n = 0; - output = static_cast(std::stold(input, &n)); - return n == input.size(); - } catch(const std::invalid_argument &) { - return false; - } catch(const std::out_of_range &) { - return false; - } + try { + size_t n = 0; + output = static_cast(std::stold(input, &n)); + return n == input.size(); + } catch (const std::invalid_argument &) { + return false; + } catch (const std::out_of_range &) { + return false; + } } /// String and similar -template ::value && !std::is_integral::value && !std::is_enum::value && - std::is_assignable::value, - detail::enabler> = detail::dummy> +template < + typename T, + enable_if_t::value && + !std::is_integral::value && !std::is_enum::value && + std::is_assignable::value, + detail::enabler> = detail::dummy> bool lexical_cast(std::string input, T &output) { - output = input; - return true; + output = input; + return true; } /// Non-string parsable -template ::value && !std::is_integral::value && !std::is_enum::value && - !std::is_assignable::value, - detail::enabler> = detail::dummy> +template < + typename T, + enable_if_t::value && + !std::is_integral::value && !std::is_enum::value && + !std::is_assignable::value, + detail::enabler> = detail::dummy> bool lexical_cast(std::string input, T &output) { // On GCC 4.7, thread_local is not available, so this optimization // is turned off (avoiding multiple initialisations on multiple usages -#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && __GNUC__ == 4 && (__GNUC_MINOR__ < 8) - std::istringstream is; +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && \ + __GNUC__ == 4 && (__GNUC_MINOR__ < 8) + std::istringstream is; #else - static thread_local std::istringstream is; + static thread_local std::istringstream is; #endif - is.str(input); - is >> output; - return !is.fail() && !is.rdbuf()->in_avail(); + is.str(input); + is >> output; + return !is.fail() && !is.rdbuf()->in_avail(); } } // namespace detail @@ -671,76 +745,80 @@ namespace CLI { namespace detail { // Returns false if not a short option. Otherwise, sets opt name and rest and returns true -inline bool split_short(const std::string ¤t, std::string &name, std::string &rest) { - if(current.size() > 1 && current[0] == '-' && valid_first_char(current[1])) { - name = current.substr(1, 1); - rest = current.substr(2); - return true; - } else - return false; +inline bool split_short(const std::string ¤t, std::string &name, + std::string &rest) { + if (current.size() > 1 && current[0] == '-' && valid_first_char(current[1])) { + name = current.substr(1, 1); + rest = current.substr(2); + return true; + } else + return false; } // Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true -inline bool split_long(const std::string ¤t, std::string &name, std::string &value) { - if(current.size() > 2 && current.substr(0, 2) == "--" && valid_first_char(current[2])) { - auto loc = current.find("="); - if(loc != std::string::npos) { - name = current.substr(2, loc - 2); - value = current.substr(loc + 1); - } else { - name = current.substr(2); - value = ""; - } - return true; - } else - return false; +inline bool split_long(const std::string ¤t, std::string &name, + std::string &value) { + if (current.size() > 2 && current.substr(0, 2) == "--" && + valid_first_char(current[2])) { + auto loc = current.find("="); + if (loc != std::string::npos) { + name = current.substr(2, loc - 2); + value = current.substr(loc + 1); + } else { + name = current.substr(2); + value = ""; + } + return true; + } else + return false; } // Splits a string into multiple long and short names inline std::vector split_names(std::string current) { - std::vector output; - size_t val; - while((val = current.find(",")) != std::string::npos) { - output.push_back(trim_copy(current.substr(0, val))); - current = current.substr(val + 1); - } - output.push_back(trim_copy(current)); - return output; + std::vector output; + size_t val; + while ((val = current.find(",")) != std::string::npos) { + output.push_back(trim_copy(current.substr(0, val))); + current = current.substr(val + 1); + } + output.push_back(trim_copy(current)); + return output; } /// Get a vector of short names, one of long names, and a single name -inline std::tuple, std::vector, std::string> +inline std::tuple, std::vector, + std::string> get_names(const std::vector &input) { - std::vector short_names; - std::vector long_names; - std::string pos_name; + std::vector short_names; + std::vector long_names; + std::string pos_name; - for(std::string name : input) { - if(name.length() == 0) - continue; - else if(name.length() > 1 && name[0] == '-' && name[1] != '-') { - if(name.length() == 2 && valid_first_char(name[1])) - short_names.emplace_back(1, name[1]); - else - throw BadNameString::OneCharName(name); - } else if(name.length() > 2 && name.substr(0, 2) == "--") { - name = name.substr(2); - if(valid_name_string(name)) - long_names.push_back(name); - else - throw BadNameString::BadLongName(name); - } else if(name == "-" || name == "--") { - throw BadNameString::DashesOnly(name); - } else { - if(pos_name.length() > 0) - throw BadNameString::MultiPositionalNames(name); - pos_name = name; - } + for (std::string name : input) { + if (name.length() == 0) + continue; + else if (name.length() > 1 && name[0] == '-' && name[1] != '-') { + if (name.length() == 2 && valid_first_char(name[1])) + short_names.emplace_back(1, name[1]); + else + throw BadNameString::OneCharName(name); + } else if (name.length() > 2 && name.substr(0, 2) == "--") { + name = name.substr(2); + if (valid_name_string(name)) + long_names.push_back(name); + else + throw BadNameString::BadLongName(name); + } else if (name == "-" || name == "--") { + throw BadNameString::DashesOnly(name); + } else { + if (pos_name.length() > 0) + throw BadNameString::MultiPositionalNames(name); + pos_name = name; } + } - return std::tuple, std::vector, std::string>( - short_names, long_names, pos_name); + return std::tuple, std::vector, + std::string>(short_names, long_names, pos_name); } } // namespace detail @@ -752,101 +830,104 @@ namespace CLI { namespace detail { inline std::string inijoin(std::vector args) { - std::ostringstream s; - size_t start = 0; - for(const auto &arg : args) { - if(start++ > 0) - s << " "; + std::ostringstream s; + size_t start = 0; + for (const auto &arg : args) { + if (start++ > 0) + s << " "; - auto it = std::find_if(arg.begin(), arg.end(), [](char ch) { return std::isspace(ch, std::locale()); }); - if(it == arg.end()) - s << arg; - else if(arg.find(R"(")") == std::string::npos) - s << R"(")" << arg << R"(")"; - else - s << R"(')" << arg << R"(')"; - } + auto it = std::find_if(arg.begin(), arg.end(), [](char ch) { + return std::isspace(ch, std::locale()); + }); + if (it == arg.end()) + s << arg; + else if (arg.find(R"(")") == std::string::npos) + s << R"(")" << arg << R"(")"; + else + s << R"(')" << arg << R"(')"; + } - return s.str(); + return s.str(); } struct ini_ret_t { - /// This is the full name with dots - std::string fullname; + /// This is the full name with dots + std::string fullname; - /// Listing of inputs - std::vector inputs; + /// Listing of inputs + std::vector inputs; - /// Current parent level - size_t level = 0; + /// Current parent level + size_t level = 0; - /// Return parent or empty string, based on level - /// - /// Level 0, a.b.c would return a - /// Level 1, a.b.c could return b - std::string parent() const { - std::vector plist = detail::split(fullname, '.'); - if(plist.size() > (level + 1)) - return plist[level]; - else - return ""; - } + /// Return parent or empty string, based on level + /// + /// Level 0, a.b.c would return a + /// Level 1, a.b.c could return b + std::string parent() const { + std::vector plist = detail::split(fullname, '.'); + if (plist.size() > (level + 1)) + return plist[level]; + else + return ""; + } - /// Return name - std::string name() const { - std::vector plist = detail::split(fullname, '.'); - return plist.at(plist.size() - 1); - } + /// Return name + std::string name() const { + std::vector plist = detail::split(fullname, '.'); + return plist.at(plist.size() - 1); + } }; /// Internal parsing function inline std::vector parse_ini(std::istream &input) { - std::string name, line; - std::string section = "default"; + std::string name, line; + std::string section = "default"; - std::vector output; + std::vector output; - while(getline(input, line)) { - std::vector items; + while (getline(input, line)) { + std::vector items; - detail::trim(line); - size_t len = line.length(); - if(len > 1 && line[0] == '[' && line[len - 1] == ']') { - section = line.substr(1, len - 2); - } else if(len > 0 && line[0] != ';') { - output.emplace_back(); - ini_ret_t &out = output.back(); + detail::trim(line); + size_t len = line.length(); + if (len > 1 && line[0] == '[' && line[len - 1] == ']') { + section = line.substr(1, len - 2); + } else if (len > 0 && line[0] != ';') { + output.emplace_back(); + ini_ret_t &out = output.back(); - // Find = in string, split and recombine - auto pos = line.find("="); - if(pos != std::string::npos) { - name = detail::trim_copy(line.substr(0, pos)); - std::string item = detail::trim_copy(line.substr(pos + 1)); - items = detail::split_up(item); - } else { - name = detail::trim_copy(line); - items = {"ON"}; - } + // Find = in string, split and recombine + auto pos = line.find("="); + if (pos != std::string::npos) { + name = detail::trim_copy(line.substr(0, pos)); + std::string item = detail::trim_copy(line.substr(pos + 1)); + items = detail::split_up(item); + } else { + name = detail::trim_copy(line); + items = {"ON"}; + } - if(detail::to_lower(section) == "default") - out.fullname = name; - else - out.fullname = section + "." + name; + if (detail::to_lower(section) == "default") + out.fullname = name; + else + out.fullname = section + "." + name; - out.inputs.insert(std::end(out.inputs), std::begin(items), std::end(items)); - } + out.inputs.insert(std::end(out.inputs), std::begin(items), + std::end(items)); } - return output; + } + return output; } /// Parse an INI file, throw an error (ParseError:INIParseError or FileError) on failure inline std::vector parse_ini(const std::string &name) { - std::ifstream input{name}; - if(!input.good()) - throw FileError::Missing(name); + std::ifstream input{name}; + if (!input.good()) + throw FileError::Missing(name); - return parse_ini(input); + return parse_ini(input); } } // namespace detail @@ -865,65 +946,68 @@ namespace CLI { /// Check for an existing file inline std::string ExistingFile(const std::string &filename) { - struct stat buffer; - bool exist = stat(filename.c_str(), &buffer) == 0; - bool is_dir = (buffer.st_mode & S_IFDIR) != 0; - if(!exist) { - return "File does not exist: " + filename; - } else if(is_dir) { - return "File is actually a directory: " + filename; - } - return std::string(); + struct stat buffer; + bool exist = stat(filename.c_str(), &buffer) == 0; + bool is_dir = (buffer.st_mode & S_IFDIR) != 0; + if (!exist) { + return "File does not exist: " + filename; + } else if (is_dir) { + return "File is actually a directory: " + filename; + } + return std::string(); } /// Check for an existing directory inline std::string ExistingDirectory(const std::string &filename) { - struct stat buffer; - bool exist = stat(filename.c_str(), &buffer) == 0; - bool is_dir = (buffer.st_mode & S_IFDIR) != 0; - if(!exist) { - return "Directory does not exist: " + filename; - } else if(!is_dir) { - return "Directory is actually a file: " + filename; - } - return std::string(); + struct stat buffer; + bool exist = stat(filename.c_str(), &buffer) == 0; + bool is_dir = (buffer.st_mode & S_IFDIR) != 0; + if (!exist) { + return "Directory does not exist: " + filename; + } else if (!is_dir) { + return "Directory is actually a file: " + filename; + } + return std::string(); } /// Check for an existing path inline std::string ExistingPath(const std::string &filename) { - struct stat buffer; - bool const exist = stat(filename.c_str(), &buffer) == 0; - if(!exist) { - return "Path does not exist: " + filename; - } - return std::string(); + struct stat buffer; + bool const exist = stat(filename.c_str(), &buffer) == 0; + if (!exist) { + return "Path does not exist: " + filename; + } + return std::string(); } /// Check for a non-existing path inline std::string NonexistentPath(const std::string &filename) { - struct stat buffer; - bool exist = stat(filename.c_str(), &buffer) == 0; - if(exist) { - return "Path already exists: " + filename; - } - return std::string(); + struct stat buffer; + bool exist = stat(filename.c_str(), &buffer) == 0; + if (exist) { + return "Path already exists: " + filename; + } + return std::string(); } /// Produce a range validator function -template std::function Range(T min, T max) { - return [min, max](std::string input) { - T val; - detail::lexical_cast(input, val); - if(val < min || val > max) - return "Value " + input + " not in range " + std::to_string(min) + " to " + std::to_string(max); +template +std::function Range(T min, T max) { + return [min, max](std::string input) { + T val; + detail::lexical_cast(input, val); + if (val < min || val > max) + return "Value " + input + " not in range " + std::to_string(min) + + " to " + std::to_string(max); - return std::string(); - }; + return std::string(); + }; } /// Range of one value is 0 to value -template std::function Range(T max) { - return Range(static_cast(0), max); +template +std::function Range(T max) { + return Range(static_cast(0), max); } /// @} @@ -945,597 +1029,614 @@ using Option_p = std::unique_ptr