1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-30 00:00:11 +01:00
VILLASnode/fpga/lib/card.cpp
Steffen Vogel 157d5b21d7 Make REUSE copyright notice the same as in other VILLASframework projects and fix comments (#82)
This edits the headers in every file so the copyright notice mentions RWTH Aachen University. We also update some copyright years and fix various comments so the header is the same across all of VILLASframework.

* Harmonize comment and code-style

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>

* Harmonize comment and code-style

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>

---------

Signed-off-by: Steffen Vogel <steffen.vogel@opal-rt.com>
2023-09-08 11:35:18 +02:00

129 lines
3.5 KiB
C++

/* FPGA card
*
* This class represents a FPGA device.
*
* Author: Steffen Vogel <post@steffenvogel.de>
* Author: Daniel Krebs <github@daniel-krebs.net>
* SPDX-FileCopyrightText: 2017 Institute for Automation of Complex Power Systems, RWTH Aachen University
* SPDX-License-Identifier: Apache-2.0
*/
#include <villas/fpga/card.hpp>
using namespace villas;
using namespace villas::fpga;
Card::~Card()
{
// Ensure IP destructors are called before memory is unmapped
ips.clear();
auto &mm = MemoryManager::get();
// Unmap all memory blocks
for (auto &mappedMemoryBlock : memoryBlocksMapped) {
auto translation = mm.getTranslation(addrSpaceIdDeviceToHost, mappedMemoryBlock.first);
const uintptr_t iova = translation.getLocalAddr(0);
const size_t size = translation.getSize();
logger->debug("Unmap block {} at IOVA {:#x} of size {:#x}",
mappedMemoryBlock.first, iova, size);
vfioContainer->memoryUnmap(iova, size);
}
}
std::shared_ptr<ip::Core> Card::lookupIp(const std::string &name) const
{
for(auto &ip : ips) {
if(*ip == name) {
return ip;
}
}
return nullptr;
}
std::shared_ptr<ip::Core> Card::lookupIp(const Vlnv &vlnv) const
{
for(auto &ip : ips) {
if(*ip == vlnv) {
return ip;
}
}
return nullptr;
}
std::shared_ptr<ip::Core> Card::lookupIp(const ip::IpIdentifier &id) const
{
for (auto &ip : ips) {
if (*ip == id) {
return ip;
}
}
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.");
}
auto &mm = MemoryManager::get();
auto translation = mm.getTranslation(addrSpaceIdDeviceToHost, block.getAddrSpaceId());
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);
memoryBlocksMapped.erase(block.getAddrSpaceId());
return true;
}
bool Card::mapMemoryBlock(const std::shared_ptr<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();
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());
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);
// Remember that this block has already been mapped for later
memoryBlocksMapped.insert({addrSpaceId, block});
return true;
}