Commit 8a13d8ad authored by Steffen Vogel's avatar Steffen Vogel 🎅🏼
Browse files

several cleanups and bugfixes

parent 2affde11
......@@ -75,9 +75,9 @@ public:
bool reset() { return true; }
void dump() { }
ip::IpCore* lookupIp(const std::string& name) const;
ip::IpCore* lookupIp(const Vlnv& vlnv) const;
ip::IpCore* lookupIp(const ip::IpIdentifier& id) const;
ip::IpCore::Ptr lookupIp(const std::string& name) const;
ip::IpCore::Ptr lookupIp(const Vlnv& vlnv) const;
ip::IpCore::Ptr lookupIp(const ip::IpIdentifier& id) const;
bool
mapMemoryBlock(const MemoryBlock& block);
......@@ -87,7 +87,7 @@ private:
std::set<MemoryManager::AddressSpaceId> memoryBlocksMapped;
public: // TODO: make this private
ip::IpCoreList ips; ///< IPs located on this FPGA card
ip::IpCore::List ips; ///< IPs located on this FPGA card
bool do_reset; /**< Reset VILLASfpga during startup? */
int affinity; /**< Affinity for MSI interrupts */
......
......@@ -55,11 +55,10 @@ class IpCore;
class IpCoreFactory;
class InterruptController;
using IpCoreList = std::list<std::unique_ptr<IpCore>>;
class IpIdentifier {
public:
IpIdentifier(Vlnv vlnv = Vlnv::getWildcard(), std::string name = "") :
vlnv(vlnv), name(name) {}
......@@ -106,6 +105,9 @@ public:
IpCore() : card(nullptr) {}
virtual ~IpCore() = default;
using Ptr = std::shared_ptr<IpCore>;
using List = std::list<IpCore::Ptr>;
public:
/* Generic management interface for IPs */
......@@ -240,7 +242,7 @@ public:
using plugin::Plugin::Plugin;
/// Returns a running and checked FPGA IP
static IpCoreList
static IpCore::List
make(PCIeCard* card, json_t *json_ips);
protected:
......
......@@ -118,11 +118,10 @@ public:
virtual const StreamVertex&
getDefaultMasterPort() const;
const StreamGraph&
getGraph() const
static const StreamGraph&
getGraph()
{ return streamGraph; }
bool loopbackPossible() const;
bool connectLoopback();
......
......@@ -58,6 +58,7 @@ public:
bool memcpy(const MemoryBlock& src, const MemoryBlock& dst, size_t len);
bool makeAccesibleFromVA(const MemoryBlock& mem);
bool makeInaccesibleFromVA(const MemoryBlock& mem);
inline bool
hasScatterGather() const
......
......@@ -119,7 +119,7 @@ PCIeCardFactory::create()
PCIeCard::~PCIeCard()
{
auto& mg = MemoryManager::get().getGraph();
auto& mm = MemoryManager::get();
// unmap all memory blocks
for (auto& mappedMemoryBlock : memoryBlocksMapped) {
......@@ -136,12 +136,12 @@ PCIeCard::~PCIeCard()
}
ip::IpCore*
ip::IpCore::Ptr
PCIeCard::lookupIp(const std::string& name) const
{
for (auto& ip : ips) {
if (*ip == name) {
return ip.get();
return ip;
}
}
......@@ -149,23 +149,24 @@ PCIeCard::lookupIp(const std::string& name) const
}
ip::IpCore*
ip::IpCore::Ptr
PCIeCard::lookupIp(const Vlnv& vlnv) const
{
for (auto& ip : ips) {
if (*ip == vlnv) {
return ip.get();
return ip;
}
}
return nullptr;
}
ip::IpCore*PCIeCard::lookupIp(const ip::IpIdentifier& id) const
ip::IpCore::Ptr
PCIeCard::lookupIp(const ip::IpIdentifier& id) const
{
for (auto& ip : ips) {
if (*ip == id) {
return ip.get();
return ip;
}
}
......
......@@ -52,7 +52,7 @@ vlnvInitializationOrder = {
};
IpCoreList
IpCore::List
IpCoreFactory::make(PCIeCard* card, json_t *json_ips)
{
// We only have this logger until we know the factory to build an IP with
......@@ -61,8 +61,8 @@ IpCoreFactory::make(PCIeCard* card, json_t *json_ips)
std::list<IpIdentifier> allIps; // all IPs available in config
std::list<IpIdentifier> orderedIps; // IPs ordered in initialization order
IpCoreList configuredIps; // Successfully configured IPs
IpCoreList initializedIps; // Initialized, i.e. ready-to-use IPs
IpCore::List configuredIps; // Successfully configured IPs
IpCore::List initializedIps; // Initialized, i.e. ready-to-use IPs
// parse all IP instance names and their VLNV into list `allIps`
......
......@@ -77,7 +77,6 @@ IpNodeFactory::configureJson(IpCore& ip, json_t* json_ip)
const std::string role(role_raw);
const bool isMaster = (role == "master" or role == "initiator");
auto thisVertex = IpNode::streamGraph.getOrCreateStreamVertex(
ip.getInstanceName(),
name_raw,
......@@ -104,10 +103,10 @@ IpNodeFactory::configureJson(IpCore& ip, json_t* json_ip)
std::pair<std::string, std::string>
IpNode::getLoopbackPorts() const
{
for (auto& [masterName, masterTo] : portsMaster) {
for (auto& [slaveName, slaveTo] : portsSlave) {
// TODO: should we also check which IP both ports are connected to?
if (masterTo->nodeName == slaveTo->nodeName) {
for (auto& [masterName, masterVertex] : portsMaster) {
for (auto& [slaveName, slaveVertex] : portsSlave) {
StreamGraph::Path path;
if (streamGraph.getPath(masterVertex->getIdentifier(), slaveVertex->getIdentifier(), path)) {
return { masterName, slaveName };
}
}
......@@ -159,7 +158,7 @@ bool IpNode::connect(const StreamVertex& from, const StreamVertex& to)
nextHopNode = secondHopNode;
}
auto nextHopNodeIp = dynamic_cast<IpNode*>
auto nextHopNodeIp = std::dynamic_pointer_cast<IpNode>
(card->lookupIp(nextHopNode->nodeName));
if (nextHopNodeIp == nullptr) {
......@@ -213,19 +212,7 @@ IpNode::connectLoopback()
logger->debug("master port: {}", ports.first);
logger->debug("slave port: {}", ports.second);
logger->debug("switch at: {}", portMaster->nodeName);
// TODO: verify this is really a switch!
auto axiStreamSwitch = dynamic_cast<ip::AxiStreamSwitch*>(
card->lookupIp(portMaster->nodeName));
if (axiStreamSwitch == nullptr) {
logger->error("Cannot find switch");
return false;
}
// switch's slave port is our master port and vice versa
return axiStreamSwitch->connect(*portMaster, *portSlave);
return connect(*portMaster, *portSlave);
}
} // namespace ip
......
......@@ -367,7 +367,7 @@ Dma::makeAccesibleFromVA(const MemoryBlock& mem)
// sanity-check if mapping worked, this shouldn't be neccessary
if (not isMemoryBlockAccesible(mem, s2mmInterface) or
not isMemoryBlockAccesible(mem, mm2sInterface)) {
not isMemoryBlockAccesible(mem, mm2sInterface)) {
logger->error("Mapping memory via card didn't work, but reported success?!");
return false;
}
......
......@@ -56,7 +56,7 @@ AxiPciExpressBridge::init()
// create a mapping from process address space to the FPGA card via vfio
mm.createMapping(reinterpret_cast<uintptr_t>(bar0_mapped),
0, bar0_size, "VFIO-H2D",
0, bar0_size, "vfio-h2d",
mm.getProcessAddressSpace(),
card->addrSpaceIdHostToDevice);
......
......@@ -143,12 +143,11 @@ int main(int argc, char* argv[])
auto card = setupFpgaCard(configFile, fpgaName);
auto aurora = dynamic_cast<fpga::ip::Aurora*>
auto aurora = std::dynamic_pointer_cast<fpga::ip::Aurora>
(card->lookupIp(fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:aurora_axis:")));
auto dma = dynamic_cast<fpga::ip::Dma*>
auto dma = std::dynamic_pointer_cast<fpga::ip::Dma>
(card->lookupIp("hier_0_axi_dma_axi_dma_0"));
if (aurora == nullptr) {
logger->error("No Aurora interface found on FPGA");
......
......@@ -21,22 +21,26 @@
##############################################################################
set(SOURCES
main.cpp
fpga.cpp
logging.cpp
dma.cpp
fifo.cpp
fpga.cpp
logging.cpp
main.cpp
rtds.cpp
timer.cpp
)
# rtds_rtt.cpp
# hls.cpp
# intc.cpp
add_executable(unit-tests ${SOURCES})
if(CMAKE_CUDA_COMPILER)
if (CMAKE_CUDA_COMPILER)
enable_language(CUDA)
target_sources(unit-tests PRIVATE
gpu.cpp rtds2gpu.cpp gpu_kernels.cu)
endif()
endif ()
find_package(Criterion REQUIRED)
......
......@@ -33,75 +33,77 @@
using namespace villas;
Test(fpga, dma, .description = "DMA")
{
auto logger = logging.get("unittest:dma");
auto logger = logging.get("unit-test:dma");
std::list<std::shared_ptr<fpga::ip::Dma>> dmaIps;
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);
}
}
size_t count = 0;
for(auto& ip : state.cards.front()->ips) {
// skip non-dma IPs
if(*ip != fpga::Vlnv("xilinx.com:ip:axi_dma:"))
continue;
logger->info("Testing {}", *ip);
auto dma = dynamic_cast<fpga::ip::Dma&>(*ip);
for (auto& dma : dmaIps) {
logger->info("Testing {}", *dma);
if(not dma.loopbackPossible()) {
logger->info("Loopback test not possible for {}", *ip);
if (not dma->loopbackPossible()) {
logger->info("Loopback test not possible for {}", *dma);
continue;
}
count++;
dma->connectLoopback();
// Simple DMA can only transfer up to 4 kb due to PCIe page size burst
// limitation
size_t len = 4 * (1 << 10);
// find a block RAM IP to write to
auto bramIp = state.cards.front()->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_bram_ctrl:"));
auto bram = reinterpret_cast<fpga::ip::Bram*>(bramIp);
cr_assert_not_null(bram, "Couldn't find BRAM");
#if 0
/* Allocate memory to use with DMA */
auto src = HostDmaRam::getAllocator().allocate<char>(len);
auto dst = HostDmaRam::getAllocator().allocate<char>(len);
#elif 0
/* ... only works with IOMMU enabled currently */
// auto src = bram->getAllocator().allocate<char>(len);
// auto dst = bram->getAllocator().allocate<char>(len);
/* ... only works with IOMMU enabled currently */
// auto src = HostRam::getAllocator().allocate<char>(len);
// auto dst = HostRam::getAllocator().allocate<char>(len);
/* 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<fpga::ip::Bram>(bramIp);
cr_assert_not_null(bram, "Couldn't find BRAM");
auto src = bram->getAllocator().allocate<char>(len);
auto dst = bram->getAllocator().allocate<char>(len);
#else
/* ... only works with IOMMU enabled currently */
auto src = HostRam::getAllocator().allocate<char>(len);
auto dst = HostRam::getAllocator().allocate<char>(len);
#endif
/* Make sure memory is accessible for DMA */
cr_assert(dma.makeAccesibleFromVA(src.getMemoryBlock()),
cr_assert(dma->makeAccesibleFromVA(src.getMemoryBlock()),
"Source memory not accessible for DMA");
cr_assert(dma.makeAccesibleFromVA(dst.getMemoryBlock()),
cr_assert(dma->makeAccesibleFromVA(dst.getMemoryBlock()),
"Destination memory not accessible for DMA");
/* Get new random data */
const size_t lenRandom = utils::read_random(&src, len);
cr_assert(len == lenRandom, "Failed to get random data");
/* Start transfer */
cr_assert(dma.memcpy(src.getMemoryBlock(), dst.getMemoryBlock(), len),
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");
logger->info(CLR_GRN("Passed"));
count++;
}
cr_assert(count > 0, "No DMA found");
MemoryManager::getGraph().dump();
IpNode::getGraph().dump();
MemoryManager::get().getGraph().dump();
fpga::ip::IpNode::getGraph().dump();
}
......@@ -47,16 +47,14 @@ Test(fpga, fifo, .description = "FIFO")
logger->info("Testing {}", *ip);
auto fifo = dynamic_cast<fpga::ip::Fifo&>(*ip);
auto fifo = std::dynamic_pointer_cast<fpga::ip::Fifo>(ip);
if (not fifo.connectLoopback()) {
if (not fifo->loopbackPossible()) {
logger->info("Loopback test not possible for {}", *ip);
continue;
}
count++;
if (not fifo.loopbackPossible()) {
logger->info("Loopback test not possible for {}", *ip);
if (not fifo->connectLoopback()) {
continue;
}
......@@ -68,13 +66,13 @@ Test(fpga, fifo, .description = "FIFO")
continue;
}
len = fifo.write(src, sizeof(src));
len = fifo->write(src, sizeof(src));
if (len != sizeof(src)) {
logger->error("Failed to send to FIFO");
continue;
}
len = fifo.read(dst, sizeof(dst));
len = fifo->read(dst, sizeof(dst));
if (len != sizeof(dst)) {
logger->error("Failed to read from FIFO");
continue;
......@@ -84,7 +82,9 @@ Test(fpga, fifo, .description = "FIFO")
cr_assert_eq(memcmp(src, dst, sizeof(src)), 0, "Data not equal");
logger->info(CLR_GRN("Passed"));
count++;
}
cr_assert(count > 0, "No fifo found");
cr_assert(count > 0, "No FIFO found");
}
......@@ -37,14 +37,16 @@
#include <villas/memory.hpp>
#include <villas/gpu.hpp>
using namespace villas;
Test(fpga, gpu_dma, .description = "GPU DMA tests")
{
auto logger = villas::logging.get("unit-test:dma");
auto logger = logging.get("unit-test:dma");
auto& card = state.cards.front();
auto gpuPlugin = villas::Plugin::Registry<GpuFactory>("cuda");
auto gpuPlugin = Plugin::Registry<GpuFactory>("cuda");
cr_assert_not_null(gpuPlugin, "No GPU plugin found");
auto gpus = gpuPlugin->make();
......@@ -56,12 +58,12 @@ Test(fpga, gpu_dma, .description = "GPU DMA tests")
size_t count = 0;
for (auto& ip : card->ips) {
// skip non-dma IPs
if (*ip != villas::fpga::Vlnv("xilinx.com:ip:axi_bram_ctrl:"))
if (*ip != fpga::Vlnv("xilinx.com:ip:axi_bram_ctrl:"))
continue;
logger->info("Testing {}", *ip);
auto bram = dynamic_cast<villas::fpga::ip::Bram*>(ip.get());
auto bram = dynamic_cast<fpga::ip::Bram*>(ip.get());
cr_assert_not_null(bram, "Couldn't find BRAM");
count++;
......@@ -76,14 +78,14 @@ Test(fpga, gpu_dma, .description = "GPU DMA tests")
gpu->makeAccessibleFromPCIeOrHostRam(bram0.getMemoryBlock());
gpu->makeAccessibleFromPCIeOrHostRam(bram1.getMemoryBlock());
auto hostRam0 = villas::HostRam::getAllocator().allocate<char>(len);
auto hostRam1 = villas::HostRam::getAllocator().allocate<char>(len);
auto hostRam0 = HostRam::getAllocator().allocate<char>(len);
auto hostRam1 = HostRam::getAllocator().allocate<char>(len);
gpu->makeAccessibleFromPCIeOrHostRam(hostRam0.getMemoryBlock());
gpu->makeAccessibleFromPCIeOrHostRam(hostRam1.getMemoryBlock());
auto dmaRam0 = villas::HostDmaRam::getAllocator().allocate<char>(len);
auto dmaRam1 = villas::HostDmaRam::getAllocator().allocate<char>(len);
auto dmaRam0 = HostDmaRam::getAllocator().allocate<char>(len);
auto dmaRam1 = HostDmaRam::getAllocator().allocate<char>(len);
gpu->makeAccessibleFromPCIeOrHostRam(dmaRam0.getMemoryBlock());
gpu->makeAccessibleFromPCIeOrHostRam(dmaRam1.getMemoryBlock());
......@@ -113,8 +115,8 @@ Test(fpga, gpu_dma, .description = "GPU DMA tests")
{"CUDA kernel", [&]() {gpu->memcpyKernel(src.getMemoryBlock(), dst.getMemoryBlock(), len);}},
};
auto dmaIp = card->lookupIp(villas::fpga::Vlnv("xilinx.com:ip:axi_dma:"));
auto dma = dynamic_cast<villas::fpga::ip::Dma*>(dmaIp);
auto dmaIp = card->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:"));
auto dma = std::dynamic_pointer_cast<fpga::ip::Dma>(dmaIp);
if (dma != nullptr and dma->connectLoopback()) {
memcpyFuncs.push_back({
......
......@@ -24,9 +24,9 @@
#include <criterion/criterion.h>
#include <villas/fpga/card.h>
#include <villas/fpga/vlnv.h>
#include <villas/fpga/ip.h>
#include <villas/fpga/card.hpp>
#include <villas/fpga/vlnv.hpp>
#include <villas/fpga/ip.hpp>
extern struct fpga_card *card;
......@@ -50,7 +50,7 @@ Test(fpga, hls_dft, .description = "HLS: hls_dft")
ret = switch_connect(card->sw, hls, rtds);
cr_assert_eq(ret, 0, "Failed to configure switch");
while(1) {
while (1) {
/* Dump RTDS AXI Stream state */
rtds_axis_dump(rtds);
sleep(1);
......@@ -62,10 +62,10 @@ Test(fpga, hls_dft, .description = "HLS: hls_dft")
for (int i = 0; i < len; i++) {
src[i] = 4 + 5.0 * sin(2.0 * M_PI * 1 * i / NSAMPLES) +
2.0 * sin(2.0 * M_PI * 2 * i / NSAMPLES) +
1.0 * sin(2.0 * M_PI * 5 * i / NSAMPLES) +
0.5 * sin(2.0 * M_PI * 9 * i / NSAMPLES) +
0.2 * sin(2.0 * M_PI * 15 * i / NSAMPLES);
2.0 * sin(2.0 * M_PI * 2 * i / NSAMPLES) +
1.0 * sin(2.0 * M_PI * 5 * i / NSAMPLES) +
0.5 * sin(2.0 * M_PI * 9 * i / NSAMPLES) +
0.2 * sin(2.0 * M_PI * 15 * i / NSAMPLES);
fifo_write()
}
......
......@@ -22,10 +22,10 @@
#include <criterion/criterion.h>
#include <villas/fpga/card.h>
#include <villas/fpga/ip.h>
#include <villas/fpga/card.hpp>
#include <villas/fpga/ip.hpp>
#include <villas/fpga/ips/intc.h>
#include <villas/fpga/ips/intc.hpp>
extern struct fpga_card *card;
......
......@@ -64,7 +64,6 @@ Test(fpga, rtds, .description = "RTDS")
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);
......
......@@ -38,6 +38,8 @@
#include "global.hpp"
using namespace villas;
static constexpr size_t SAMPLE_SIZE = 4;
static constexpr size_t SAMPLE_COUNT = 1;
......@@ -68,10 +70,10 @@ static void dumpMem(const uint32_t* addr, size_t len)
Test(fpga, rtds2gpu_loopback_dma, .description = "Rtds2Gpu")
{
auto logger = villas::logging.get("unit-test:rtds2gpu");
auto logger = logging.get("unit-test:rtds2gpu");
for (auto& ip : state.cards.front()->ips) {
if (*ip != villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:"))
if (*ip != fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:"))
continue;
logger->info("Testing {}", *ip);
......@@ -79,19 +81,19 @@ Test(fpga, rtds2gpu_loopback_dma, .description = "Rtds2Gpu")
/* Collect neccessary IPs */
auto rtds2gpu = dynamic_cast<villas::fpga::ip::Rtds2Gpu&>(*ip);
auto rtds2gpu = std::dynamic_pointer_cast<fpga::ip::Rtds2Gpu>(ip);
auto axiSwitch = dynamic_cast<villas::fpga::ip::AxiStreamSwitch*>(
state.cards.front()->lookupIp(villas::fpga::Vlnv("xilinx.com:ip:axis_switch:")));
auto axiSwitch = std::dynamic_pointer_cast<fpga::ip::AxiStreamSwitch>(
state.cards.front()->lookupIp(fpga::Vlnv("xilinx.com:ip:axis_switch:")));
auto dma = dynamic_cast<villas::fpga::ip::Dma*>(
state.cards.front()->lookupIp(villas::fpga::Vlnv("xilinx.com:ip:axi_dma:")));
auto dma = std::dynamic_pointer_cast<fpga::ip::Dma>(
state.cards.front()->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:")));
auto gpu2rtds = dynamic_cast<villas::fpga::ip::Gpu2Rtds*>(
state.cards.front()->lookupIp(villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:")));
auto gpu2rtds = std::dynamic_pointer_cast<fpga::ip::Gpu2Rtds>(
state.cards.front()->lookupIp(fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:")));
auto rtds = dynamic_cast<villas::fpga::ip::Rtds*>(
state.cards.front()->lookupIp(villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")));
auto rtds = std::dynamic_pointer_cast<fpga::ip::Rtds>(
state.cards.front()->lookupIp(fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")));
cr_assert_not_null(axiSwitch, "No AXI switch IP found");
......@@ -106,9 +108,9 @@ Test(fpga, rtds2gpu_loopback_dma, .description = "Rtds2Gpu")
/* Allocate and prepare memory */
// allocate space for all samples and doorbell register
auto dmaMemSrc = villas::HostDmaRam::getAllocator(0).allocate<uint32_t>(SAMPLE_COUNT + 1);
auto dmaMemDst = villas::HostDmaRam::getAllocator(0).allocate<uint32_t>(SAMPLE_COUNT + 1);
auto dmaMemDst2 = villas::HostDmaRam::getAllocator(0).allocate<uint32_t>(SAMPLE_COUNT + 1);
auto dmaMemSrc = HostDmaRam::getAllocator(0).allocate<uint32_t>(SAMPLE_COUNT + 1);
auto dmaMemDst = HostDmaRam::getAllocator(0).allocate<uint32_t>(SAMPLE_COUNT + 1);
auto dmaMemDst2 =