1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

Merge branch 'refactoring' into 'master'

Refactoring

See merge request acs/public/villas/fpga/fpga!11
This commit is contained in:
Steffen Vogel 2020-06-15 22:12:35 +02:00
commit e3cfc26673
47 changed files with 361 additions and 469 deletions

View file

@ -1,19 +1,13 @@
variables:
GIT_STRATEGY: fetch
GIT_SUBMODULE_STRATEGY: recursive
PREFIX: /usr/
DOCKER_TAG_DEV: ${CI_BUILD_REF_SLUG}
DOCKER_IMAGE_DEV: villas/fpga-dev
# For some reason, GitLab CI prunes the contents of the submodules so we need to restore them.
before_script:
- git submodule foreach git checkout .
stages:
- prepare
- build
- test
# - deploy
# Stage: prepare
##############################################################################
@ -43,19 +37,6 @@ build:source:
tags:
- docker
#build:packages:
# stage: build
# script:
# - mkdir build && cd build && cmake3 .. && make package
# artifacts:
# expire_in: 1 week
# name: ${CI_PROJECT_NAME}-${CI_BUILD_REF}
# paths:
# - build/
# image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG_DEV}
# tags:
# - docker
# Stage: test
##############################################################################
@ -66,32 +47,12 @@ test:unit:
- cuda
allow_failure: true
script: |
rm -r build && mkdir build && cd build && cmake3 .. && make unit-tests -j8
rm -r build && mkdir build && cd build
cmake3 ..
make -j$(nproc) unit-tests
if [ "$(who | wc -l)" -eq "0" ]; then
tests/unit-tests --jobs 1 --filter 'fpga/*'
tests/fpga-unit-tests --jobs 1 --filter 'fpga/*'
else
echo "System is currently used by: $(who)"
echo "We are skipping the test. Please restart manually."
fi
# Stage: deploy
##############################################################################
#deploy:packages:
# stage: deploy
# script:
# - ssh ${DEPLOY_USER}@${DEPLOY_HOST} mkdir -p ${DEPLOY_PATH}/{dist,../packages}
# - rsync ${RSYNC_OPTS} build/*.rpm ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/../packages/
# - rsync ${RSYNC_OPTS} build//*.tar.gz ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/dist/
# - ssh ${DEPLOY_USER}@${DEPLOY_HOST} createrepo ${DEPLOY_PATH}/../packages
# dependencies:
# - build:packages
# tags:
# - villas-deploy
# only:
# - tags
#
#deploy:git-mirror:
# stage: deploy
# script:
# - git push --force --mirror --prune https://${GITHUB_USER}:${GITHUB_TOKEN}@github.com:VILLASframework/VILLASnode.git

View file

@ -29,9 +29,16 @@ project(VILLASfpga
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
# Several CMake settings/defaults
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
set(TOPLEVEL_PROJECT ON)
else()
set(TOPLEVEL_PROJECT OFF)
endif()
# GPU library is optional, check for CUDA presence
include(CheckLanguage)
check_language(CUDA)
@ -42,14 +49,26 @@ else()
message("No CUDA support, not building GPU library")
endif()
include(FindPkgConfig)
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig:/usr/local/lib64/pkgconfig:/usr/local/share/pkgconfig:/usr/lib64/pkgconfig")
pkg_check_modules(JANSSON REQUIRED IMPORTED_TARGET jansson)
pkg_check_modules(XIL REQUIRED IMPORTED_TARGET libxil)
find_package(Threads)
include_directories(thirdparty/CLI11)
include_directories(thirdparty/rang)
add_subdirectory(common)
add_subdirectory(lib)
add_subdirectory(src)
add_subdirectory(tests)
if(NOT CMAKE_PROJECT_NAME STREQUAL "villas-node")
add_subdirectory(common)
endif()
# Project settings
set(PROJECT_NAME "VILLASfpga")
set(PROJECT_DESCRIPTION "Host library for configuring and communicating with VILLASfpga")

View file

@ -42,9 +42,6 @@ LABEL \
org.label-schema.vcs-url="https://git.rwth-aachen.de/VILLASframework/VILLASfpga" \
org.label-schema.usage="https://villas.fein-aachen.org/doc/fpga.html"
# Some of the dependencies are only available in our own repo
ADD https://villas.fein-aachen.org/packages/villas.repo /etc/yum.repos.d/
# Enable Extra Packages for Enterprise Linux (EPEL) and Software collection repo
RUN yum -y install epel-release centos-release-scl
@ -62,12 +59,40 @@ RUN yum -y install \
# Dependencies
RUN yum -y install \
jansson-devel \
libxil-devel \
openssl-devel \
curl-devel \
lapack-devel
# Build & Install Fmtlib
RUN git clone --recursive https://github.com/fmtlib/fmt.git /tmp/fmt && \
mkdir -p /tmp/fmt/build && cd /tmp/fmt/build && \
git checkout 5.2.0 && \
cmake3 -DBUILD_SHARED_LIBS=1 .. && \
make -j$(nproc) install && \
rm -rf /tmp/fmt
# Build & Install spdlog
RUN git clone --recursive https://github.com/gabime/spdlog.git /tmp/spdlog && \
mkdir -p /tmp/spdlog/build && cd /tmp/spdlog/build && \
git checkout v1.3.1 && \
cmake3 -DSPDLOG_FMT_EXTERNAL=ON -DSPDLOG_BUILD_BENCH=OFF .. && \
make -j$(nproc) install && \
rm -rf /tmp/spdlog
# Build & Install Criterion
COPY thirdparty/criterion /tmp/criterion
RUN mkdir -p /tmp/criterion/build && cd /tmp/criterion/build && cmake3 .. && make install && rm -rf /tmp/*
RUN git clone --recursive https://github.com/Snaipe/Criterion /tmp/criterion && \
mkdir -p /tmp/criterion/build && cd /tmp/criterion/build && \
git checkout v2.3.3 && \
cmake3 .. && \
make -j$(nproc) install && \
rm -rf /tmp/*
# Build & Install libxil
RUN git clone https://git.rwth-aachen.de/acs/public/villas/fpga/libxil.git /tmp/libxil && \
mkdir -p /tmp/libxil/build && cd /tmp/libxil/build && \
cmake3 .. && \
make -j$(nproc) install && \
rm -rf /tmp/*
ENV LD_LIBRARY_PATH /usr/local/lib:/usr/local/lib64

@ -1 +1 @@
Subproject commit 952945fc4bcdcdca0dfbe1389f811ceb7b5c5744
Subproject commit 3b5952a413ba8f8c7731c6a0c8336e1f523884b8

View file

@ -45,25 +45,25 @@ public:
std::string getName() const;
GpuAllocator& getAllocator() const
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);
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);
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;
@ -86,7 +86,7 @@ class GpuAllocator : public BaseAllocator<GpuAllocator> {
public:
static constexpr size_t GpuPageSize = 64UL << 10;
GpuAllocator(Gpu& gpu);
GpuAllocator(Gpu &gpu);
std::string getName() const;
@ -94,7 +94,7 @@ public:
allocateBlock(size_t size);
private:
Gpu& gpu;
Gpu &gpu;
// TODO: replace by multimap (key is available memory)
std::list<std::unique_ptr<LinearAllocator>> chunks;
};

View file

@ -30,7 +30,7 @@
#include <villas/gpu.hpp>
#include <villas/log.hpp>
#include <villas/kernel/pci.h>
#include <villas/kernel/pci.hpp>
#include <villas/memory_manager.hpp>
#include <cuda.h>
@ -39,12 +39,12 @@
#include "kernels.hpp"
namespace villas {
namespace gpu {
using namespace villas::gpu;
static GpuFactory gpuFactory;
GpuAllocator::GpuAllocator(Gpu& gpu) :
GpuAllocator::GpuAllocator(Gpu &gpu) :
BaseAllocator(gpu.masterPciEAddrSpaceId),
gpu(gpu)
{
@ -77,7 +77,7 @@ GpuFactory::GpuFactory() :
// required to be defined here for PIMPL to compile
Gpu::~Gpu()
{
auto& mm = MemoryManager::get();
auto &mm = MemoryManager::get();
mm.removeAddressSpace(masterPciEAddrSpaceId);
}
@ -104,9 +104,9 @@ std::string Gpu::getName() const
return name.str();
}
bool Gpu::registerIoMemory(const MemoryBlock& mem)
bool Gpu::registerIoMemory(const MemoryBlock &mem)
{
auto& mm = MemoryManager::get();
auto &mm = MemoryManager::get();
const auto pciAddrSpaceId = mm.getPciAddressSpace();
// Check if we need to map anything at all, maybe it's already reachable
@ -115,14 +115,14 @@ bool Gpu::registerIoMemory(const MemoryBlock& mem)
// overlapping window, so this will fail badly!
auto translation = mm.getTranslation(masterPciEAddrSpaceId,
mem.getAddrSpaceId());
if (translation.getSize() >= mem.getSize()) {
if (translation.getSize() >= mem.getSize())
// there is already a sufficient path
logger->debug("Already mapped through another mapping");
return true;
} else {
else
logger->warn("There's already a mapping, but too small");
}
} catch(const std::out_of_range&) {
}
catch(const std::out_of_range&) {
// not yet reachable, that's okay, proceed
}
@ -187,9 +187,9 @@ bool Gpu::registerIoMemory(const MemoryBlock& mem)
}
bool
Gpu::registerHostMemory(const MemoryBlock& mem)
Gpu::registerHostMemory(const MemoryBlock &mem)
{
auto& mm = MemoryManager::get();
auto &mm = MemoryManager::get();
auto translation = mm.getTranslationFromProcess(mem.getAddrSpaceId());
auto localBase = reinterpret_cast<void*>(translation.getLocalAddr(0));
@ -214,14 +214,14 @@ Gpu::registerHostMemory(const MemoryBlock& mem)
return true;
}
bool Gpu::makeAccessibleToPCIeAndVA(const MemoryBlock& mem)
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());
@ -311,14 +311,14 @@ bool Gpu::makeAccessibleToPCIeAndVA(const MemoryBlock& mem)
}
bool
Gpu::makeAccessibleFromPCIeOrHostRam(const MemoryBlock& mem)
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 {
@ -333,7 +333,8 @@ Gpu::makeAccessibleFromPCIeOrHostRam(const MemoryBlock& mem)
mem.getAddrSpaceId());
return registerIoMemory(mem);
} else {
}
else {
logger->debug("Memory block {} is assumed to be non-CUDA host memory",
mem.getAddrSpaceId());
@ -341,9 +342,9 @@ Gpu::makeAccessibleFromPCIeOrHostRam(const MemoryBlock& mem)
}
}
void Gpu::memcpySync(const MemoryBlock& src, const MemoryBlock& dst, size_t size)
void Gpu::memcpySync(const MemoryBlock &src, const MemoryBlock &dst, size_t size)
{
auto& mm = MemoryManager::get();
auto &mm = MemoryManager::get();
auto src_translation = mm.getTranslation(masterPciEAddrSpaceId,
src.getAddrSpaceId());
@ -357,9 +358,9 @@ void Gpu::memcpySync(const MemoryBlock& src, const MemoryBlock& dst, size_t size
cudaMemcpy(dst_buf, src_buf, size, cudaMemcpyDefault);
}
void Gpu::memcpyKernel(const MemoryBlock& src, const MemoryBlock& dst, size_t size)
void Gpu::memcpyKernel(const MemoryBlock &src, const MemoryBlock &dst, size_t size)
{
auto& mm = MemoryManager::get();
auto &mm = MemoryManager::get();
auto src_translation = mm.getTranslation(masterPciEAddrSpaceId,
src.getAddrSpaceId());
@ -375,9 +376,9 @@ void Gpu::memcpyKernel(const MemoryBlock& src, const MemoryBlock& dst, size_t si
}
MemoryTranslation
Gpu::translate(const MemoryBlock& dst)
Gpu::translate(const MemoryBlock &dst)
{
auto& mm = MemoryManager::get();
auto &mm = MemoryManager::get();
return mm.getTranslation(masterPciEAddrSpaceId, dst.getAddrSpaceId());
}
@ -388,10 +389,10 @@ GpuAllocator::allocateBlock(size_t size)
cudaSetDevice(gpu.gpuId);
void* addr;
auto& mm = MemoryManager::get();
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) {
auto chunk = std::find_if(chunks.begin(), chunks.end(), [&](const auto &chunk) {
return chunk->getAvailableMemory() >= size;
});
@ -400,8 +401,8 @@ GpuAllocator::allocateBlock(size_t size)
logger->debug("Found existing chunk that can host the requested block");
return (*chunk)->allocateBlock(size);
} else {
}
else {
// allocate a new chunk
// rounded-up multiple of GPU page size
@ -452,7 +453,7 @@ Gpu::Gpu(int gpuId) :
bool Gpu::init()
{
auto& mm = MemoryManager::get();
auto &mm = MemoryManager::get();
const auto gpuPciEAddrSpaceName = mm.getMasterAddrSpaceName(getName(), "pcie");
masterPciEAddrSpaceId = mm.getOrCreateAddressSpace(gpuPciEAddrSpaceName);
@ -517,12 +518,9 @@ GpuFactory::make()
}
logger->info("Initialized {} GPUs", gpuList.size());
for (auto& gpu : gpuList) {
for (auto &gpu : gpuList) {
logger->debug(" - {}", gpu->getName());
}
return gpuList;
}
} // namespace villas
} // namespace gpu

View file

@ -20,8 +20,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <stdio.h>
#include <stdio.h>
#include <villas/gpu.hpp>
@ -30,8 +30,7 @@
#include "kernels.hpp"
namespace villas {
namespace gpu {
using namespace villas::gpu;
__global__ void
@ -61,6 +60,3 @@ kernel_memcpy(volatile uint8_t* dst, volatile uint8_t* src, size_t length)
length--;
}
}
} // namespace villas
} // namespace gpu

View file

@ -38,35 +38,32 @@
#include <villas/plugin.hpp>
#include <villas/memory.hpp>
#include <villas/kernel/pci.h>
#include <villas/kernel/pci.hpp>
#include <villas/kernel/vfio.hpp>
#include <villas/fpga/config.h>
#include <villas/fpga/core.hpp>
#define PCI_FILTER_DEFAULT_FPGA { \
.id = { \
.vendor = FPGA_PCI_VID_XILINX, \
.device = FPGA_PCI_PID_VFPGA, \
.class_code = 0 \
}, \
.slot = { } \
}
namespace villas {
namespace fpga {
/* Forward declarations */
struct vfio_container;
class PCIeCardFactory;
class PCIeCard {
class Card {
public:
using Ptr = std::shared_ptr<PCIeCard>;
using List = std::list<Ptr>;
friend PCIeCardFactory;
PCIeCard() : filter(PCI_FILTER_DEFAULT_FPGA) {}
};
class PCIeCard : public Card {
public:
~PCIeCard();
bool init();
@ -75,12 +72,18 @@ public:
bool reset() { return true; }
void dump() { }
ip::Core::Ptr lookupIp(const std::string& name) const;
ip::Core::Ptr lookupIp(const Vlnv& vlnv) const;
ip::Core::Ptr lookupIp(const ip::IpIdentifier& id) const;
ip::Core::Ptr
lookupIp(const std::string &name) const;
ip::Core::Ptr
lookupIp(const Vlnv &vlnv) const;
ip::Core::Ptr
lookupIp(const ip::IpIdentifier &id) const;
bool
mapMemoryBlock(const MemoryBlock& block);
mapMemoryBlock(const MemoryBlock &block);
private:
/// Cache a set of already mapped memory blocks
@ -89,20 +92,18 @@ private:
public: // TODO: make this private
ip::Core::List ips; ///< IPs located on this FPGA card
bool do_reset; /**< Reset VILLASfpga during startup? */
bool doReset; /**< Reset VILLASfpga during startup? */
int affinity; /**< Affinity for MSI interrupts */
std::string name; /**< The name of the FPGA card */
struct pci* pci;
struct pci_device filter; /**< Filter for PCI device. */
struct pci_device* pdev; /**< PCI device handle */
std::shared_ptr<kernel::pci::Device> pdev; /**< PCI device handle */
/// The VFIO container that this card is part of
std::shared_ptr<VfioContainer> vfioContainer;
std::shared_ptr<kernel::vfio::Container> vfioContainer;
/// The VFIO device that represents this card
VfioDevice* vfioDevice;
kernel::vfio::Device* vfioDevice;
/// Slave address space ID to access the PCIe address space from the FPGA
MemoryManager::AddressSpaceId addrSpaceIdDeviceToHost;
@ -119,16 +120,15 @@ protected:
Logger logger;
};
using CardList = std::list<std::shared_ptr<PCIeCard>>;
class PCIeCardFactory : public plugin::Plugin {
public:
static CardList
make(json_t *json, struct pci* pci, std::shared_ptr<VfioContainer> vc);
static Card::List
make(json_t *json, std::shared_ptr<kernel::pci::DeviceList> pci, std::shared_ptr<kernel::vfio::Container> vc);
static PCIeCard*
create();
create()
{ return new PCIeCard(); }
static Logger
getStaticLogger()

View file

@ -74,11 +74,11 @@ public:
{ return vlnv; }
friend std::ostream&
operator<< (std::ostream& stream, const IpIdentifier& id)
operator<< (std::ostream &stream, const IpIdentifier &id)
{ return stream << id.name << " vlnv=" << id.vlnv; }
bool
operator==(const IpIdentifier& otherId) const {
operator==(const IpIdentifier &otherId) const {
const bool vlnvWildcard = otherId.getVlnv() == Vlnv::getWildcard();
const bool nameWildcard = this->getName().empty() or otherId.getName().empty();
@ -89,7 +89,7 @@ public:
}
bool
operator!=(const IpIdentifier& otherId) const
operator!=(const IpIdentifier &otherId) const
{ return !(*this == otherId); }
private:
@ -144,66 +144,66 @@ public:
/* Operators */
bool
operator==(const Vlnv& otherVlnv) const
operator==(const Vlnv &otherVlnv) const
{ return id.getVlnv() == otherVlnv; }
bool
operator!=(const Vlnv& otherVlnv) const
operator!=(const Vlnv &otherVlnv) const
{ return id.getVlnv() != otherVlnv; }
bool
operator==(const IpIdentifier& otherId) const
operator==(const IpIdentifier &otherId) const
{ return this->id == otherId; }
bool
operator!=(const IpIdentifier& otherId) const
operator!=(const IpIdentifier &otherId) const
{ return this->id != otherId; }
bool
operator==(const std::string& otherName) const
operator==(const std::string &otherName) const
{ return getInstanceName() == otherName; }
bool
operator!=(const std::string& otherName) const
operator!=(const std::string &otherName) const
{ return getInstanceName() != otherName; }
bool
operator==(const Core& otherIp) const
operator==(const Core &otherIp) const
{ return this->id == otherIp.id; }
bool
operator!=(const Core& otherIp) const
operator!=(const Core &otherIp) const
{ return this->id != otherIp.id; }
friend std::ostream&
operator<< (std::ostream& stream, const Core& ip)
operator<< (std::ostream &stream, const Core &ip)
{ return stream << ip.id; }
protected:
uintptr_t
getBaseAddr(const MemoryBlockName& block) const
getBaseAddr(const MemoryBlockName &block) const
{ return getLocalAddr(block, 0); }
uintptr_t
getLocalAddr(const MemoryBlockName& block, uintptr_t address) const;
getLocalAddr(const MemoryBlockName &block, uintptr_t address) const;
MemoryManager::AddressSpaceId
getAddressSpaceId(const MemoryBlockName& block) const
getAddressSpaceId(const MemoryBlockName &block) const
{ return slaveAddressSpaces.at(block); }
InterruptController*
getInterruptController(const std::string& interruptName) const;
getInterruptController(const std::string &interruptName) const;
MemoryManager::AddressSpaceId
getMasterAddrSpaceByInterface(const std::string& masterInterfaceName) const
getMasterAddrSpaceByInterface(const std::string &masterInterfaceName) const
{ return busMasterInterfaces.at(masterInterfaceName); }
template<typename T>
T readMemory(const std::string& block, uintptr_t address) const
T readMemory(const std::string &block, uintptr_t address) const
{ return *(reinterpret_cast<T*>(getLocalAddr(block, address))); }
template<typename T>
void writeMemory(const std::string& block, uintptr_t address, T value)
void writeMemory(const std::string &block, uintptr_t address, T value)
{ T* ptr = reinterpret_cast<T*>(getLocalAddr(block, address)); *ptr = value; }
protected:
@ -266,7 +266,7 @@ protected:
private:
static CoreFactory*
lookup(const Vlnv& vlnv);
lookup(const Vlnv &vlnv);
};
/** @} */

View file

@ -59,7 +59,7 @@ private:
class BramFactory : public CoreFactory {
public:
bool configureJson(Core& ip, json_t *json_ip);
bool configureJson(Core &ip, json_t *json_ip);
Core* create()
{ return new Bram; }

View file

@ -44,10 +44,10 @@ public:
bool reset();
// memory-mapped to stream (MM2S)
bool write(const MemoryBlock& mem, size_t len);
bool write(const MemoryBlock &mem, size_t len);
// stream to memory-mapped (S2MM)
bool read(const MemoryBlock& mem, size_t len);
bool read(const MemoryBlock &mem, size_t len);
size_t writeComplete()
{ return hasScatterGather() ? writeCompleteSG() : writeCompleteSimple(); }
@ -55,10 +55,10 @@ public:
size_t readComplete()
{ return hasScatterGather() ? readCompleteSG() : readCompleteSimple(); }
bool memcpy(const MemoryBlock& src, const MemoryBlock& dst, size_t len);
bool memcpy(const MemoryBlock &src, const MemoryBlock &dst, size_t len);
bool makeAccesibleFromVA(const MemoryBlock& mem);
bool makeInaccesibleFromVA(const MemoryBlock& mem);
bool makeAccesibleFromVA(const MemoryBlock &mem);
bool makeInaccesibleFromVA(const MemoryBlock &mem);
inline bool
hasScatterGather() const
@ -87,7 +87,7 @@ public:
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();

View file

@ -13,7 +13,7 @@ class Hls : public virtual Core
public:
virtual bool init()
{
auto& registers = addressTranslations.at(registerMemory);
auto &registers = addressTranslations.at(registerMemory);
controlRegister = reinterpret_cast<ControlRegister*>(registers.getLocalAddr(registerControlAddr));
globalIntRegister = reinterpret_cast<GlobalIntRegister*>(registers.getLocalAddr(registerGlobalIntEnableAddr));

View file

@ -70,7 +70,7 @@ public:
getCompatibleVlnvString()
{ return "xilinx.com:ip:axi_pcie:"; }
bool configureJson(Core& ip, json_t *json_ip);
bool configureJson(Core &ip, json_t *json_ip);
Core* create()
{ return new AxiPciExpressBridge; }

View file

@ -34,16 +34,16 @@ public:
void dump(spdlog::level::level_enum logLevel = 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();
void dumpDoorbell(uint32_t doorbellRegister) const;
bool doorbellIsValid(const uint32_t& doorbellRegister) const
bool doorbellIsValid(const uint32_t &doorbellRegister) const
{ return reinterpret_cast<const reg_doorbell_t&>(doorbellRegister).is_valid; }
void doorbellReset(uint32_t& doorbellRegister) const
void doorbellReset(uint32_t &doorbellRegister) const
{ doorbellRegister = 0; }
static constexpr const char* registerMemory = "Reg";

View file

@ -46,11 +46,11 @@ public:
bool init();
bool connectInternal(const std::string& slavePort,
const std::string& masterPort);
bool connectInternal(const std::string &slavePort,
const std::string &masterPort);
private:
int portNameToNum(const std::string& portName);
int portNameToNum(const std::string &portName);
private:
static constexpr const char* PORT_DISABLED = "DISABLED";
@ -77,7 +77,7 @@ public:
getCompatibleVlnvString()
{ return "xilinx.com:ip:axis_switch:"; }
bool configureJson(Core& ip, json_t *json_ip);
bool configureJson(Core &ip, json_t *json_ip);
Core* create()
{ return new AxiStreamSwitch; }

View file

@ -44,14 +44,14 @@ namespace ip {
class StreamVertex : public graph::Vertex {
public:
StreamVertex(const std::string& node, const std::string& port, bool isMaster) :
StreamVertex(const std::string &node, const std::string &port, bool isMaster) :
nodeName(node), portName(port), isMaster(isMaster) {}
std::string getName() const
{ return nodeName + "/" + portName + "(" + (isMaster ? "M" : "S") + ")"; }
friend std::ostream&
operator<< (std::ostream& stream, const StreamVertex& vertex)
operator<< (std::ostream &stream, const StreamVertex &vertex)
{ return stream << vertex.getIdentifier() << ": " << vertex.getName(); }
public:
@ -66,12 +66,12 @@ public:
StreamGraph() : graph::DirectedGraph<StreamVertex>("StreamGraph") {}
std::shared_ptr<StreamVertex>
getOrCreateStreamVertex(const std::string& node,
const std::string& port,
getOrCreateStreamVertex(const std::string &node,
const std::string &port,
bool isMaster)
{
for (auto& vertexEntry : vertices) {
auto& vertex = vertexEntry.second;
for (auto &vertexEntry : vertices) {
auto &vertex = vertexEntry.second;
if (vertex->nodeName == node and vertex->portName == port and vertex->isMaster == isMaster)
return vertex;
}
@ -88,6 +88,8 @@ public:
class Node : public virtual Core {
public:
using Ptr = std::shared_ptr<Node>;
friend class NodeFactory;
struct StreamPort {
@ -95,20 +97,31 @@ public:
std::string nodeName;
};
bool connect(const StreamVertex& from, const StreamVertex& to);
const StreamVertex&
getMasterPort(const std::string& name) const
getMasterPort(const std::string &name) const
{ return *portsMaster.at(name); }
const StreamVertex&
getSlavePort(const std::string& name) const
getSlavePort(const std::string &name) const
{ return *portsSlave.at(name); }
bool connect(const StreamVertex &from, const StreamVertex &to);
bool connect(const StreamVertex &from, const StreamVertex &to, bool reverse)
{
bool ret;
ret = connect(from, to);
if (reverse)
ret &= connect(to, from);
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)
{ return this->connect(this->getDefaultMasterPort(), slaveNode.getDefaultSlavePort()); }
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&
@ -127,8 +140,8 @@ public:
protected:
virtual bool
connectInternal(const std::string& slavePort,
const std::string& masterPort);
connectInternal(const std::string &slavePort,
const std::string &masterPort);
private:
std::pair<std::string, std::string> getLoopbackPorts() const;
@ -144,7 +157,7 @@ class NodeFactory : public CoreFactory {
public:
using CoreFactory::CoreFactory;
virtual bool configureJson(Core& ip, json_t *json_ip);
virtual bool configureJson(Core &ip, json_t *json_ip);
};
/** @} */

View file

@ -53,14 +53,14 @@ public:
toString() const;
bool
operator==(const Vlnv& other) const;
operator==(const Vlnv &other) const;
bool
operator!=(const Vlnv& other) const
operator!=(const Vlnv &other) const
{ return !(*this == other); }
friend std::ostream&
operator<< (std::ostream& stream, const Vlnv& vlnv)
operator<< (std::ostream &stream, const Vlnv &vlnv)
{
return stream
<< (vlnv.vendor.empty() ? "*" : vlnv.vendor) << ":"

View file

@ -46,13 +46,6 @@ set(SOURCES
set_source_files_properties(ips/rtds2gpu/xrtds2gpu.c
PROPERTIES COMPILE_FLAGS -Wno-int-to-pointer-cast)
include(FindPkgConfig)
pkg_check_modules(JANSSON jansson)
pkg_check_modules(XIL libxil)
find_package(Threads)
add_library(villas-fpga SHARED ${SOURCES})
target_link_libraries(villas-fpga PUBLIC villas-common)
@ -64,7 +57,8 @@ target_compile_definitions(villas-fpga PRIVATE
target_include_directories(villas-fpga
PUBLIC
../include
${PROJECT_BINARY_DIR}/include
${PROJECT_SOURCE_DIR}/include
${XIL_INCLUDE_DIRS}
${JANSSON_INCLUDE_DIRS}
)

View file

@ -24,24 +24,27 @@
#include <memory>
#include <utility>
#include <villas/exceptions.hpp>
#include <villas/memory.hpp>
#include <villas/kernel/pci.h>
#include <villas/kernel/pci.hpp>
#include <villas/kernel/vfio.hpp>
#include <villas/fpga/core.hpp>
#include <villas/fpga/card.hpp>
namespace villas {
namespace fpga {
using namespace villas;
using namespace villas::fpga;
// instantiate factory to register
static PCIeCardFactory PCIeCardFactory;
static PCIeCardFactory villas::fpga::PCIeCardFactory;
CardList
PCIeCardFactory::make(json_t *json, struct pci* pci, std::shared_ptr<VfioContainer> vc)
static const kernel::pci::Device defaultFilter((kernel::pci::Id(FPGA_PCI_VID_XILINX, FPGA_PCI_PID_VFPGA)));
PCIeCard::List
PCIeCardFactory::make(json_t *json, std::shared_ptr<kernel::pci::DeviceList> pci, std::shared_ptr<kernel::vfio::Container> vc)
{
CardList cards;
PCIeCard::List cards;
auto logger = getStaticLogger();
const char *card_name;
@ -71,37 +74,38 @@ PCIeCardFactory::make(json_t *json, struct pci* pci, std::shared_ptr<VfioContain
// populate generic properties
card->name = std::string(card_name);
card->pci = pci;
card->vfioContainer = std::move(vc);
card->affinity = affinity;
card->do_reset = do_reset != 0;
card->doReset = do_reset != 0;
const char* error;
kernel::pci::Device filter = defaultFilter;
if (pci_id)
filter.id = kernel::pci::Id(pci_id);
if (pci_slot)
filter.slot = kernel::pci::Slot(pci_slot);
if (pci_slot != nullptr and pci_device_parse_slot(&card->filter, pci_slot, &error) != 0) {
logger->warn("Failed to parse PCI slot: {}", error);
/* Search for FPGA card */
card->pdev = pci->lookupDevice(filter);
if (!card->pdev) {
logger->warn("Failed to find PCI device");
continue;
}
if (pci_id != nullptr and pci_device_parse_id(&card->filter, pci_id, &error) != 0) {
logger->warn("Failed to parse PCI ID: {}", error);
}
if (not card->init()) {
logger->warn("Cannot start FPGA card {}", card_name);
continue;
}
card->ips = ip::CoreFactory::make(card.get(), json_ips);
if (card->ips.empty()) {
logger->error("Cannot initialize IPs of FPGA card {}", card_name);
continue;
}
if (not json_is_object(json_ips))
throw ConfigError(json_ips, "node-config-fpga-ips", "FPGA IP core list must be an object!");
if (not card->check()) {
logger->warn("Checking of FPGA card {} failed", card_name);
continue;
}
card->ips = ip::CoreFactory::make(card.get(), json_ips);
if (card->ips.empty())
throw ConfigError(json_ips, "node-config-fpga-ips", "Cannot initialize IPs of FPGA card {}", card_name);
if (not card->check())
throw RuntimeError("Checking of FPGA card {} failed", card_name);
cards.push_back(std::move(card));
}
@ -109,20 +113,12 @@ PCIeCardFactory::make(json_t *json, struct pci* pci, std::shared_ptr<VfioContain
return cards;
}
PCIeCard*
PCIeCardFactory::create()
{
return new fpga::PCIeCard;
}
PCIeCard::~PCIeCard()
{
auto& mm = MemoryManager::get();
auto &mm = MemoryManager::get();
// unmap all memory blocks
for (auto& mappedMemoryBlock : memoryBlocksMapped) {
for (auto &mappedMemoryBlock : memoryBlocksMapped) {
auto translation = mm.getTranslation(addrSpaceIdDeviceToHost,
mappedMemoryBlock);
@ -137,9 +133,9 @@ PCIeCard::~PCIeCard()
ip::Core::Ptr
PCIeCard::lookupIp(const std::string& name) const
PCIeCard::lookupIp(const std::string &name) const
{
for (auto& ip : ips) {
for (auto &ip : ips) {
if (*ip == name) {
return ip;
}
@ -150,9 +146,9 @@ PCIeCard::lookupIp(const std::string& name) const
ip::Core::Ptr
PCIeCard::lookupIp(const Vlnv& vlnv) const
PCIeCard::lookupIp(const Vlnv &vlnv) const
{
for (auto& ip : ips) {
for (auto &ip : ips) {
if (*ip == vlnv) {
return ip;
}
@ -162,9 +158,9 @@ PCIeCard::lookupIp(const Vlnv& vlnv) const
}
ip::Core::Ptr
PCIeCard::lookupIp(const ip::IpIdentifier& id) const
PCIeCard::lookupIp(const ip::IpIdentifier &id) const
{
for (auto& ip : ips) {
for (auto &ip : ips) {
if (*ip == id) {
return ip;
}
@ -175,22 +171,21 @@ PCIeCard::lookupIp(const ip::IpIdentifier& id) const
bool
PCIeCard::mapMemoryBlock(const MemoryBlock& block)
PCIeCard::mapMemoryBlock(const MemoryBlock &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()) {
if (memoryBlocksMapped.find(addrSpaceId) != memoryBlocksMapped.end())
// block already mapped
return true;
} else {
else
logger->debug("Create VFIO mapping for {}", addrSpaceId);
}
auto translationFromProcess = mm.getTranslationFromProcess(addrSpaceId);
uintptr_t processBaseAddr = translationFromProcess.getLocalAddr(0);
@ -223,15 +218,8 @@ PCIeCard::init()
logger->info("Initializing FPGA card {}", name);
/* Search for FPGA card */
pdev = pci_lookup_device(pci, &filter);
if (!pdev) {
logger->error("Failed to find PCI device");
return false;
}
/* Attach PCIe card to VFIO container */
VfioDevice& device = vfioContainer->attachDevice(pdev);
kernel::vfio::Device &device = vfioContainer->attachDevice(*pdev);
this->vfioDevice = &device;
/* Enable memory access and PCI bus mastering for DMA */
@ -241,7 +229,7 @@ PCIeCard::init()
}
/* Reset system? */
if (do_reset) {
if (doReset) {
/* Reset / detect PCI device */
if (not vfioDevice->pciHotReset()) {
logger->error("Failed to reset PCI device");
@ -256,6 +244,3 @@ PCIeCard::init()
return true;
}
} // namespace fpga
} // namespace villas

View file

@ -36,10 +36,8 @@
#include <villas/fpga/ips/intc.hpp>
#include <villas/fpga/ips/switch.hpp>
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga;
using namespace villas::fpga::ip;
// Special IPs that have to be initialized first. Will be initialized in the
// same order as they appear in this list, i.e. first here will be initialized
@ -85,7 +83,7 @@ CoreFactory::make(PCIeCard* card, json_t *json_ips)
// first to be initialized.
vlnvInitializationOrder.reverse();
for (auto& vlnvInitFirst : vlnvInitializationOrder) {
for (auto &vlnvInitFirst : vlnvInitializationOrder) {
// iterate over IPs, if VLNV matches, push to front and remove from list
for (auto it = allIps.begin(); it != allIps.end(); ++it) {
if (vlnvInitFirst == it->getVlnv()) {
@ -99,12 +97,12 @@ CoreFactory::make(PCIeCard* card, json_t *json_ips)
orderedIps.splice(orderedIps.end(), allIps);
loggerStatic->debug("IP initialization order:");
for (auto& id : orderedIps) {
for (auto &id : orderedIps) {
loggerStatic->debug(" " CLR_BLD("{}"), id.getName());
}
// configure all IPs
for (auto& id : orderedIps) {
for (auto &id : orderedIps) {
loggerStatic->info("Configuring {}", id);
// find the appropriate factory that can create the specified VLNV
@ -117,10 +115,9 @@ CoreFactory::make(PCIeCard* card, json_t *json_ips)
if (CoreFactory == nullptr) {
loggerStatic->warn("No plugin found to handle {}", id.getVlnv());
continue;
} else {
loggerStatic->debug("Using {} for IP {}",
CoreFactory->getName(), id.getVlnv());
}
else
loggerStatic->debug("Using {} for IP {}", CoreFactory->getName(), id.getVlnv());
auto logger = CoreFactory->getLogger();
@ -162,10 +159,10 @@ CoreFactory::make(PCIeCard* card, json_t *json_ips)
continue;
}
const std::string& irqControllerName = tokens[0];
const std::string &irqControllerName = tokens[0];
InterruptController* intc = nullptr;
for (auto& configuredIp : configuredIps) {
for (auto &configuredIp : configuredIps) {
if (*configuredIp == irqControllerName) {
intc = dynamic_cast<InterruptController*>(configuredIp.get());
break;
@ -265,12 +262,12 @@ CoreFactory::make(PCIeCard* card, json_t *json_ips)
}
// Start and check IPs now
for (auto& ip : configuredIps) {
for (auto &ip : configuredIps) {
// Translate all memory blocks that the IP needs to be accessible from
// the process and cache in the instance, so this has not to be done at
// runtime.
for (auto& memoryBlock : ip->getMemoryBlocks()) {
for (auto &memoryBlock : ip->getMemoryBlocks()) {
// construct the global name of this address block
const auto addrSpaceName =
MemoryManager::getSlaveAddrSpaceName(ip->getInstanceName(),
@ -284,7 +281,7 @@ CoreFactory::make(PCIeCard* card, json_t *json_ips)
ip->slaveAddressSpaces.emplace(memoryBlock, addrSpaceId);
// get the translation to the address space
const auto& translation =
const auto &translation =
MemoryManager::get().getTranslationFromProcess(addrSpaceId);
// cache it in the IP instance only with local name
@ -309,7 +306,7 @@ CoreFactory::make(PCIeCard* card, json_t *json_ips)
loggerStatic->debug("Initialized IPs:");
for (auto& ip : initializedIps) {
for (auto &ip : initializedIps) {
loggerStatic->debug(" {}", *ip);
}
@ -335,7 +332,7 @@ Core::dump()
CoreFactory*
CoreFactory::lookup(const Vlnv &vlnv)
{
for (auto& ip : plugin::Registry::lookup<CoreFactory>()) {
for (auto &ip : plugin::Registry::lookup<CoreFactory>()) {
if (ip->getCompatibleVlnv() == vlnv)
return ip;
}
@ -345,17 +342,17 @@ CoreFactory::lookup(const Vlnv &vlnv)
uintptr_t
Core::getLocalAddr(const MemoryBlockName& block, uintptr_t address) const
Core::getLocalAddr(const MemoryBlockName &block, uintptr_t address) const
{
// throws exception if block not present
auto& translation = addressTranslations.at(block);
auto &translation = addressTranslations.at(block);
return translation.getLocalAddr(address);
}
InterruptController*
Core::getInterruptController(const std::string& interruptName) const
Core::getInterruptController(const std::string &interruptName) const
{
try {
const IrqPort irq = irqs.at(interruptName);
@ -364,8 +361,3 @@ Core::getInterruptController(const std::string& interruptName) const
return nullptr;
}
}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -66,9 +66,7 @@
#define AURORA_AXIS_CR_SEQ_ECHO (1 << 4)
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga::ip;
static AuroraFactory auroraFactoryInstance;
@ -118,7 +116,3 @@ void Aurora::resetFrameCounters()
writeMemory<uint32_t>(registerMemory, AURORA_AXIS_CR_OFFSET, cr);
}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -22,16 +22,14 @@
#include <villas/fpga/ips/bram.hpp>
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga::ip;
static BramFactory factory;
bool
BramFactory::configureJson(Core& ip, json_t* json_ip)
BramFactory::configureJson(Core &ip, json_t* json_ip)
{
auto& bram = dynamic_cast<Bram&>(ip);
auto &bram = dynamic_cast<Bram&>(ip);
if (json_unpack(json_ip, "{ s: i }", "size", &bram.size) != 0) {
getLogger()->error("Cannot parse 'size'");
@ -49,6 +47,3 @@ bool Bram::init()
return true;
}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -35,9 +35,7 @@
#define FPGA_DMA_BOUNDARY 0x1000
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga::ip;
// instantiate factory to make available to plugin infrastructure
static DmaFactory factory;
@ -75,9 +73,9 @@ Dma::init()
if (XAxiDma_Selftest(&xDma) != XST_SUCCESS) {
logger->error("DMA selftest failed");
return false;
} else {
logger->debug("DMA selftest passed");
}
else
logger->debug("DMA selftest passed");
/* Map buffer descriptors */
if (hasScatterGather()) {
@ -126,7 +124,7 @@ Dma::reset()
bool
Dma::memcpy(const MemoryBlock& src, const MemoryBlock& dst, size_t len)
Dma::memcpy(const MemoryBlock &src, const MemoryBlock &dst, size_t len)
{
if (len == 0)
return true;
@ -151,9 +149,9 @@ Dma::memcpy(const MemoryBlock& src, const MemoryBlock& dst, size_t len)
bool
Dma::write(const MemoryBlock& mem, size_t len)
Dma::write(const MemoryBlock &mem, size_t len)
{
auto& mm = MemoryManager::get();
auto &mm = MemoryManager::get();
// user has to make sure that memory is accessible, otherwise this will throw
auto translation = mm.getTranslation(busMasterInterfaces[mm2sInterface],
@ -166,9 +164,9 @@ Dma::write(const MemoryBlock& mem, size_t len)
bool
Dma::read(const MemoryBlock& mem, size_t len)
Dma::read(const MemoryBlock &mem, size_t len)
{
auto& mm = MemoryManager::get();
auto &mm = MemoryManager::get();
// user has to make sure that memory is accessible, otherwise this will throw
auto translation = mm.getTranslation(busMasterInterfaces[s2mmInterface],
@ -351,7 +349,7 @@ Dma::readCompleteSimple()
bool
Dma::makeAccesibleFromVA(const MemoryBlock& mem)
Dma::makeAccesibleFromVA(const MemoryBlock &mem)
{
// only symmetric mapping supported currently
if (isMemoryBlockAccesible(mem, s2mmInterface) and
@ -377,9 +375,9 @@ Dma::makeAccesibleFromVA(const MemoryBlock& mem)
bool
Dma::isMemoryBlockAccesible(const MemoryBlock& mem, const std::string& interface)
Dma::isMemoryBlockAccesible(const MemoryBlock &mem, const std::string &interface)
{
auto& mm = MemoryManager::get();
auto &mm = MemoryManager::get();
try {
mm.findPath(getMasterAddrSpaceByInterface(interface), mem.getAddrSpaceId());
@ -401,7 +399,3 @@ Dma::dump()
logger->info("S2MM_LENGTH: {:x}", XAxiDma_ReadReg(xDma.RegBase, XAXIDMA_RX_OFFSET + XAXIDMA_BUFFLEN_OFFSET));
}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -32,9 +32,7 @@
#include <villas/fpga/ips/intc.hpp>
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga::ip;
// instantiate factory to make available to plugin infrastructure
static FifoFactory factory;
@ -113,6 +111,3 @@ size_t Fifo::read(void *buf, size_t len)
return nextlen;
}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -31,9 +31,7 @@
#include <villas/fpga/card.hpp>
#include <villas/fpga/ips/gpio.hpp>
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga::ip;
// instantiate factory to make available to plugin infrastructure
@ -47,6 +45,3 @@ GeneralPurposeIO::init()
return true;
}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -31,10 +31,7 @@
#include <villas/fpga/card.hpp>
#include <villas/fpga/ips/intc.hpp>
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga::ip;
// instantiate factory to make available to plugin infrastructure
static InterruptControllerFactory factory;
@ -171,6 +168,3 @@ InterruptController::waitForInterrupt(int irq)
}
}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -29,16 +29,14 @@
#include <villas/fpga/ips/pcie.hpp>
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga::ip;
static AxiPciExpressBridgeFactory factory;
bool
AxiPciExpressBridge::init()
{
auto& mm = MemoryManager::get();
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
@ -74,34 +72,28 @@ AxiPciExpressBridge::init()
auto pciAddrSpaceId = mm.getPciAddressSpace();
struct pci_region* pci_regions = nullptr;
size_t num_regions = pci_get_regions(card->pdev, &pci_regions);
auto regions = card->pdev->getRegions();
for (size_t i = 0; i < num_regions; i++) {
const size_t region_size = pci_regions[i].end - pci_regions[i].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' + pci_regions[i].num;
barName[3] = '0' + region.num;
auto pciBar = pcieToAxiTranslations.at(barName);
logger->info("PCI-BAR{}: bus addr={:#x} size={:#x}",
pci_regions[i].num, pci_regions[i].start, region_size);
region.num, region.start, region_size);
logger->info("PCI-BAR{}: AXI translation offset {:#x}",
i, pciBar.translation);
mm.createMapping(pci_regions[i].start, pciBar.translation, region_size,
mm.createMapping(region.start, pciBar.translation, region_size,
std::string("PCI-") + barName,
pciAddrSpaceId, card->addrSpaceIdHostToDevice);
}
if (pci_regions != nullptr) {
logger->debug("freeing pci regions");
free(pci_regions);
}
for (auto& [barName, axiBar] : axiToPcieTranslations) {
logger->info("AXI-{}: bus addr={:#x} size={:#x}",
barName, axiBar.base, axiBar.size);
@ -116,16 +108,18 @@ AxiPciExpressBridge::init()
mm.createMapping(0, axiBar.translation, axiBar.size,
std::string("AXI-") + barName,
barXAddrSpaceId, pciAddrSpaceId);
i++;
}
return true;
}
bool
AxiPciExpressBridgeFactory::configureJson(Core& ip, json_t* json_ip)
AxiPciExpressBridgeFactory::configureJson(Core &ip, json_t* json_ip)
{
auto logger = getLogger();
auto& pcie = dynamic_cast<AxiPciExpressBridge&>(ip);
auto &pcie = dynamic_cast<AxiPciExpressBridge&>(ip);
for (auto barType : std::list<std::string>{"axi_bars", "pcie_bars"}) {
json_t* json_bars = json_object_get(json_ip, barType.c_str());
@ -159,18 +153,12 @@ AxiPciExpressBridgeFactory::configureJson(Core& ip, json_t* json_ip)
.size = static_cast<size_t>(size),
.translation = translation
};
} else {
} else
pcie.pcieToAxiTranslations[bar_name] = {
.translation = translation
};
}
}
}
return true;
}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -53,9 +53,7 @@
/* Control register bits */
#define RTDS_AXIS_CR_DISABLE_LINK 0 /**< Disable SFP TX when set */
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga::ip;
static RtdsFactory rtdsFactoryInstance;
@ -92,6 +90,3 @@ double Rtds::getDt()
return (dt == 0xFFFF) ? 0.0 : (double) dt / RTDS_HZ;
}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -5,9 +5,7 @@
#include <villas/memory_manager.hpp>
#include <villas/fpga/ips/gpu2rtds.hpp>
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga::ip;
static Gpu2RtdsFactory factory;
@ -15,7 +13,7 @@ bool Gpu2Rtds::init()
{
Hls::init();
auto& registers = addressTranslations.at(registerMemory);
auto &registers = addressTranslations.at(registerMemory);
registerStatus = reinterpret_cast<StatusRegister*>(registers.getLocalAddr(registerStatusOffset));
registerStatusCtrl = reinterpret_cast<StatusControlRegister*>(registers.getLocalAddr(registerStatusCtrlOffset));
@ -55,9 +53,9 @@ void Gpu2Rtds::dump(spdlog::level::level_enum logLevel)
logger->log(logLevel, " Max. frame size: {}", status.max_frame_size);
}
//bool Gpu2Rtds::startOnce(const MemoryBlock& mem, size_t frameSize, size_t dataOffset, size_t doorbellOffset)
//bool Gpu2Rtds::startOnce(const MemoryBlock &mem, size_t frameSize, size_t dataOffset, size_t doorbellOffset)
//{
// auto& mm = MemoryManager::get();
// auto &mm = MemoryManager::get();
// if (frameSize > maxFrameSize) {
// logger->error("Requested frame size of {} exceeds max. frame size of {}",
@ -123,7 +121,7 @@ Gpu2Rtds::getMaxFrameSize()
//void
//Gpu2Rtds::dumpDoorbell(uint32_t doorbellRegister) const
//{
// auto& doorbell = reinterpret_cast<reg_doorbell_t&>(doorbellRegister);
// auto &doorbell = reinterpret_cast<reg_doorbell_t&>(doorbellRegister);
// logger->info("Doorbell register: {:#08x}", doorbell.value);
// logger->info(" Valid: {}", (doorbell.is_valid ? "yes" : "no"));
@ -131,6 +129,3 @@ Gpu2Rtds::getMaxFrameSize()
// logger->info(" Seq. number: {}", doorbell.seq_nr);
//}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -5,10 +5,7 @@
#include <villas/memory_manager.hpp>
#include <villas/fpga/ips/rtds2gpu.hpp>
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga::ip;
static Rtds2GpuFactory factory;
bool Rtds2Gpu::init()
@ -28,8 +25,6 @@ bool Rtds2Gpu::init()
return true;
}
void Rtds2Gpu::dump(spdlog::level::level_enum logLevel)
{
const auto baseaddr = XRtds2gpu_Get_baseaddr(&xInstance);
@ -52,9 +47,9 @@ void Rtds2Gpu::dump(spdlog::level::level_enum logLevel)
logger->log(logLevel, " Max. frame size: {}", status.max_frame_size);
}
bool Rtds2Gpu::startOnce(const MemoryBlock& mem, size_t frameSize, size_t dataOffset, size_t doorbellOffset)
bool Rtds2Gpu::startOnce(const MemoryBlock &mem, size_t frameSize, size_t dataOffset, size_t doorbellOffset)
{
auto& mm = MemoryManager::get();
auto &mm = MemoryManager::get();
if (frameSize > maxFrameSize) {
logger->error("Requested frame size of {} exceeds max. frame size of {}",
@ -108,7 +103,7 @@ Rtds2Gpu::getMaxFrameSize()
void
Rtds2Gpu::dumpDoorbell(uint32_t doorbellRegister) const
{
auto& doorbell = reinterpret_cast<reg_doorbell_t&>(doorbellRegister);
auto &doorbell = reinterpret_cast<reg_doorbell_t&>(doorbellRegister);
logger->info("Doorbell register: {:#08x}", doorbell.value);
logger->info(" Valid: {}", (doorbell.is_valid ? "yes" : "no"));
@ -116,6 +111,3 @@ Rtds2Gpu::dumpDoorbell(uint32_t doorbellRegister) const
logger->info(" Seq. number: {}", doorbell.seq_nr);
}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -70,8 +70,8 @@ AxiStreamSwitch::init()
}
bool
AxiStreamSwitch::connectInternal(const std::string& portSlave,
const std::string& portMaster)
AxiStreamSwitch::connectInternal(const std::string &portSlave,
const std::string &portMaster)
{
// check if slave port exists
try {
@ -129,21 +129,21 @@ AxiStreamSwitch::connectInternal(const std::string& portSlave,
}
int
AxiStreamSwitch::portNameToNum(const std::string& portName)
AxiStreamSwitch::portNameToNum(const std::string &portName)
{
const std::string number = portName.substr(1, 2);
return std::stoi(number);
}
bool
AxiStreamSwitchFactory::configureJson(Core& ip, json_t* json_ip)
AxiStreamSwitchFactory::configureJson(Core &ip, json_t* json_ip)
{
if (not NodeFactory::configureJson(ip, json_ip))
return false;
auto logger = getLogger();
auto& axiSwitch = dynamic_cast<AxiStreamSwitch&>(ip);
auto &axiSwitch = dynamic_cast<AxiStreamSwitch&>(ip);
if (json_unpack(json_ip, "{ s: i }", "num_ports", &axiSwitch.num_ports) != 0) {
logger->error("Cannot parse 'num_ports'");
@ -154,6 +154,6 @@ AxiStreamSwitchFactory::configureJson(Core& ip, json_t* json_ip)
}
} // namespace ip
} // namespace fpga
} // namespace villas
} /* namespace ip */
} /* namespace fpga */
} /* namespace villas */

View file

@ -30,9 +30,7 @@
#include <villas/fpga/ips/timer.hpp>
#include <villas/fpga/ips/intc.hpp>
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga::ip;
// instantiate factory to make available to plugin infrastructure
@ -80,8 +78,3 @@ uint32_t Timer::remaining()
{
return XTmrCtr_GetValue(&xTmr, 0);
}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -25,7 +25,7 @@
#include <villas/memory.hpp>
namespace villas {
using namespace villas;
bool
HostRam::free(void* addr, size_t length)
@ -42,5 +42,3 @@ HostRam::allocate(size_t length, int flags)
return mmap(nullptr, length, mmap_protection, mmap_flags, 0, 0);
}
} // namespace villas

View file

@ -30,18 +30,15 @@
#include <villas/fpga/node.hpp>
#include <villas/fpga/ips/switch.hpp>
namespace villas {
namespace fpga {
namespace ip {
using namespace villas::fpga::ip;
StreamGraph
Node::streamGraph;
bool
NodeFactory::configureJson(Core& ip, json_t* json_ip)
NodeFactory::configureJson(Core &ip, json_t* json_ip)
{
auto& Node = dynamic_cast<ip::Node&>(ip);
auto &Node = dynamic_cast<ip::Node&>(ip);
auto logger = getLogger();
json_t* json_ports = json_object_get(json_ip, "ports");
@ -115,7 +112,7 @@ Node::getLoopbackPorts() const
return { "", "" };
}
bool Node::connect(const StreamVertex& from, const StreamVertex& to)
bool Node::connect(const StreamVertex &from, const StreamVertex &to)
{
if (from.nodeName != getInstanceName()) {
logger->error("Cannot connect from a foreign StreamVertex: {}", from);
@ -192,8 +189,8 @@ Node::loopbackPossible() const
}
bool
Node::connectInternal(const std::string& slavePort,
const std::string& masterPort)
Node::connectInternal(const std::string &slavePort,
const std::string &masterPort)
{
(void) slavePort;
(void) masterPort;
@ -206,15 +203,11 @@ bool
Node::connectLoopback()
{
auto ports = getLoopbackPorts();
const auto& portMaster = portsMaster[ports.first];
const auto& portSlave = portsSlave[ports.second];
const auto &portMaster = portsMaster[ports.first];
const auto &portSlave = portsSlave[ports.second];
logger->debug("master port: {}", ports.first);
logger->debug("slave port: {}", ports.second);
return connect(*portMaster, *portSlave);
}
} // namespace ip
} // namespace fpga
} // namespace villas

View file

@ -25,8 +25,7 @@
#include <villas/fpga/vlnv.hpp>
namespace villas {
namespace fpga {
using namespace villas::fpga;
bool
Vlnv::operator==(const Vlnv &other) const
@ -74,5 +73,3 @@ Vlnv::toString() const
return string;
}
} // namespace fpga
} // namespace villas

View file

@ -28,7 +28,7 @@
#include <villas/log.h>
#include <villas/utils.hpp>
#include <villas/kernel/pci.h>
#include <villas/kernel/pci.hpp>
#include <villas/kernel/kernel.hpp>
#include <villas/fpga/card.h>
@ -54,7 +54,6 @@ int main(int argc, char *argv[])
struct list cards;
struct vfio_container vc;
struct pci pci;
struct fpga_card *card;
/* Parse arguments */
@ -88,9 +87,7 @@ check: if (optarg == endptr)
json_error_t err;
json_t *json;
ret = pci_init(&pci);
if (ret)
return -1;
auto pciDevices = std::make_shared<kernel::pci::DeviceList>();
ret = vfio_init(&vc);
if (ret)

View file

@ -43,7 +43,7 @@
using namespace villas;
static struct pci pci;
static std::shared_ptr<kernel::pci::DeviceList> pciDevices;
static auto logger = villas::logging.get("streamer");
void setupColorHandling()
@ -64,14 +64,11 @@ void setupColorHandling()
}
std::shared_ptr<fpga::PCIeCard>
setupFpgaCard(const std::string& configFile, const std::string& fpgaName)
setupFpgaCard(const std::string &configFile, const std::string &fpgaName)
{
if (pci_init(&pci) != 0) {
logger->error("Cannot initialize PCI");
exit(1);
}
pciDevices = std::make_shared<kernel::pci::DeviceList>();
auto vfioContainer = villas::VfioContainer::create();
auto vfioContainer = kernel::vfio::Container::create();
/* Parse FPGA configuration */
FILE* f = fopen(configFile.c_str(), "r");
@ -102,9 +99,9 @@ setupFpgaCard(const std::string& configFile, const std::string& fpgaName)
}
// create all FPGA card instances using the corresponding plugin
auto cards = fpgaCardPlugin->make(fpgas, &pci, vfioContainer);
auto cards = fpgaCardPlugin->make(fpgas, pciDevices, vfioContainer);
for (auto& fpgaCard : cards) {
for (auto &fpgaCard : cards) {
if (fpgaCard->name == fpgaName) {
return fpgaCard;
}
@ -192,7 +189,7 @@ int main(int argc, char* argv[])
size_t memIdx = 0;
for (auto& value: values) {
for (auto &value: values) {
if (value.empty()) continue;
const int32_t number = std::stoi(value);

View file

@ -34,22 +34,22 @@ set(SOURCES
# hls.cpp
# intc.cpp
add_executable(unit-tests ${SOURCES})
add_executable(unit-tests-fpga ${SOURCES})
if (CMAKE_CUDA_COMPILER)
enable_language(CUDA)
target_sources(unit-tests PRIVATE
target_sources(unit-tests-fpga PRIVATE
gpu.cpp rtds2gpu.cpp gpu_kernels.cu)
endif ()
find_package(Criterion REQUIRED)
target_include_directories(unit-tests PUBLIC
target_include_directories(unit-tests-fpga PUBLIC
../include
${CRITERION_INCLUDE_DIRECTORIES}
)
target_link_libraries(unit-tests PUBLIC
target_link_libraries(unit-tests-fpga PUBLIC
villas-fpga
${CRITERION_LIBRARIES}
)

View file

@ -39,7 +39,7 @@ Test(fpga, dma, .description = "DMA")
std::list<std::shared_ptr<fpga::ip::Dma>> dmaIps;
for (auto& ip : state.cards.front()->ips) {
for (auto &ip : state.cards.front()->ips) {
if (*ip == fpga::Vlnv("xilinx.com:ip:axi_dma:")) {
auto dma = std::dynamic_pointer_cast<fpga::ip::Dma>(ip);
dmaIps.push_back(dma);
@ -47,7 +47,7 @@ Test(fpga, dma, .description = "DMA")
}
size_t count = 0;
for (auto& dma : dmaIps) {
for (auto &dma : dmaIps) {
logger->info("Testing {}", *dma);
if (not dma->loopbackPossible()) {

View file

@ -40,7 +40,7 @@ Test(fpga, fifo, .description = "FIFO")
auto logger = logging.get("unit-test:fifo");
for (auto& ip : state.cards.front()->ips) {
for (auto &ip : state.cards.front()->ips) {
// skip non-fifo IPs
if (*ip != fpga::Vlnv("xilinx.com:ip:axi_fifo_mm_s:"))
continue;

View file

@ -40,14 +40,12 @@
using namespace villas;
static struct pci pci;
static std::shared_ptr<kernel::pci::DeviceList> pciDevices;
FpgaState state;
static void init()
{
int ret;
FILE *f;
json_error_t err;
@ -56,10 +54,9 @@ static void init()
plugin::Registry::dumpList();
ret = pci_init(&pci);
cr_assert_eq(ret, 0, "Failed to initialize PCI sub-system");
pciDevices = std::make_shared<kernel::pci::DeviceList>();
auto vfioContainer = VfioContainer::create();
auto vfioContainer = kernel::vfio::Container::create();
/* Parse FPGA configuration */
char *fn = getenv("TEST_CONFIG");
@ -80,7 +77,7 @@ static void init()
cr_assert_not_null(fpgaCardPlugin, "No plugin for FPGA card found");
// create all FPGA card instances using the corresponding plugin
state.cards = fpgaCardPlugin->make(fpgas, &pci, vfioContainer);
state.cards = fpgaCardPlugin->make(fpgas, pciDevices, vfioContainer);
cr_assert(state.cards.size() != 0, "No FPGA cards found!");

View file

@ -29,7 +29,7 @@
class FpgaState {
public:
// list of all available FPGA cards, only first will be tested at the moment
villas::fpga::CardList cards;
villas::fpga::PCIeCard::List cards;
};
// global state to be shared by unittests

View file

@ -44,7 +44,7 @@ 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<GpuFactory>("cuda");
cr_assert_not_null(gpuPlugin, "No GPU plugin found");
@ -53,10 +53,10 @@ Test(fpga, gpu_dma, .description = "GPU DMA tests")
cr_assert(gpus.size() > 0, "No GPUs found");
// just get first cpu
auto& gpu = gpus.front();
auto &gpu = gpus.front();
size_t count = 0;
for (auto& ip : card->ips) {
for (auto &ip : card->ips) {
// skip non-dma IPs
if (*ip != fpga::Vlnv("xilinx.com:ip:axi_bram_ctrl:"))
continue;
@ -97,17 +97,17 @@ Test(fpga, gpu_dma, .description = "GPU DMA tests")
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<std::pair<std::string, std::function<void()>>> memcpyFuncs = {

View file

@ -49,7 +49,7 @@ Test(fpga, rtds, .description = "RTDS")
std::list<villas::fpga::ip::Rtds*> rtdsIps;
std::list<villas::fpga::ip::Dma*> dmaIps;
for (auto& ip : state.cards.front()->ips) {
for (auto &ip : state.cards.front()->ips) {
if (*ip == villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")) {
auto rtds = reinterpret_cast<villas::fpga::ip::Rtds*>(ip.get());
rtdsIps.push_back(rtds);

View file

@ -72,7 +72,7 @@ Test(fpga, rtds2gpu_loopback_dma, .description = "Rtds2Gpu")
{
auto logger = logging.get("unit-test:rtds2gpu");
for (auto& ip : state.cards.front()->ips) {
for (auto &ip : state.cards.front()->ips) {
if (*ip != fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:"))
continue;
@ -191,11 +191,11 @@ Test(fpga, rtds2gpu_rtt_cpu, .description = "Rtds2Gpu RTT via CPU")
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) {
for (auto &ip : state.cards.front()->ips) {
if (*ip != fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:"))
continue;
auto& rtds = dynamic_cast<fpga::ip::Rtds&>(*ip);
auto &rtds = dynamic_cast<fpga::ip::Rtds&>(*ip);
logger->info("Testing {}", rtds);
auto dmaRam = HostDmaRam::getAllocator().allocate<uint32_t>(SAMPLE_COUNT + 1);
@ -269,7 +269,7 @@ Test(fpga, rtds2gpu_rtt_gpu, .description = "Rtds2Gpu RTT via GPU")
cr_assert(gpus.size() > 0, "No GPUs found");
// just get first cpu
auto& gpu = gpus.front();
auto &gpu = gpus.front();
// allocate memory on GPU and make accessible by to PCIe/FPGA
auto gpuRam = gpu->getAllocator().allocate<uint32_t>(SAMPLE_COUNT + 1);
@ -291,11 +291,11 @@ Test(fpga, rtds2gpu_rtt_gpu, .description = "Rtds2Gpu RTT via GPU")
// auto doorbellInCpu = reinterpret_cast<reg_doorbell_t*>(&gpuRam[DOORBELL_OFFSET]);
for (auto& ip : state.cards.front()->ips) {
for (auto &ip : state.cards.front()->ips) {
if (*ip != fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:"))
continue;
auto& rtds = dynamic_cast<fpga::ip::Rtds&>(*ip);
auto &rtds = dynamic_cast<fpga::ip::Rtds&>(*ip);
logger->info("Testing {}", rtds);

View file

@ -42,7 +42,7 @@ Test(fpga, rtds_rtt, .description = "RTDS: tight rtt")
std::list<villas::fpga::ip::Dma*> dmaIps;
/* Get IP cores */
for (auto& ip : state.cards.front()->ips) {
for (auto &ip : state.cards.front()->ips) {
if (*ip == villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")) {
auto rtds = reinterpret_cast<villas::fpga::ip::Rtds*>(ip.get());
rtdsIps.push_back(rtds);

View file

@ -34,7 +34,7 @@ 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) {
for (auto &ip : state.cards.front()->ips) {
// skip non-timer IPs
if (*ip != villas::fpga::Vlnv("xilinx.com:ip:axi_timer:")) {
continue;