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

several cleanups and bugfixes

This commit is contained in:
Steffen Vogel 2020-06-11 23:55:05 +02:00
parent bb8a711f02
commit 7c92a30ab4
20 changed files with 179 additions and 166 deletions

View file

@ -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 */

View file

@ -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:

View file

@ -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();

View file

@ -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

View file

@ -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;
}
}

View file

@ -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`

View file

@ -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

View file

@ -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;
}

View file

@ -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);

View file

@ -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");

View file

@ -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)

View file

@ -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;
for (auto& dma : dmaIps) {
logger->info("Testing {}", *dma);
logger->info("Testing {}", *ip);
auto dma = dynamic_cast<fpga::ip::Dma&>(*ip);
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);
/* 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);
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();
}

View file

@ -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");
}

View file

@ -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({

View file

@ -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()
}

View file

@ -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;

View file

@ -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);

View file

@ -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 = HostDmaRam::getAllocator(0).allocate<uint32_t>(SAMPLE_COUNT + 1);
memset(&dmaMemSrc, 0x11, dmaMemSrc.getMemoryBlock().getSize());
@ -176,27 +178,27 @@ Test(fpga, rtds2gpu_loopback_dma, .description = "Rtds2Gpu")
Test(fpga, rtds2gpu_rtt_cpu, .description = "Rtds2Gpu RTT via CPU")
{
auto logger = villas::logging.get("unit-test:rtds2gpu");
auto logger = logging.get("unit-test:rtds2gpu");
/* Collect neccessary IPs */
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 rtds2gpu = dynamic_cast<villas::fpga::ip::Rtds2Gpu*>(
state.cards.front()->lookupIp(villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:")));
auto rtds2gpu = std::dynamic_pointer_cast<fpga::ip::Rtds2Gpu>(
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");
for (auto& ip : state.cards.front()->ips) {
if (*ip != villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:"))
if (*ip != fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:"))
continue;
auto& rtds = dynamic_cast<villas::fpga::ip::Rtds&>(*ip);
auto& rtds = dynamic_cast<fpga::ip::Rtds&>(*ip);
logger->info("Testing {}", rtds);
auto dmaRam = villas::HostDmaRam::getAllocator().allocate<uint32_t>(SAMPLE_COUNT + 1);
auto dmaRam = HostDmaRam::getAllocator().allocate<uint32_t>(SAMPLE_COUNT + 1);
uint32_t* data = &dmaRam[DATA_OFFSET];
uint32_t* doorbell = &dmaRam[DOORBELL_OFFSET];
@ -241,26 +243,26 @@ Test(fpga, rtds2gpu_rtt_cpu, .description = "Rtds2Gpu RTT via CPU")
}
void gpu_rtds_rtt_start(volatile uint32_t* dataIn, volatile reg_doorbell_t* doorbellIn,
volatile uint32_t* dataOut, volatile villas::fpga::ip::ControlRegister* controlRegister);
volatile uint32_t* dataOut, volatile fpga::ip::ControlRegister* controlRegister);
void gpu_rtds_rtt_stop();
Test(fpga, rtds2gpu_rtt_gpu, .description = "Rtds2Gpu RTT via GPU")
{
auto logger = villas::logging.get("unit-test:rtds2gpu");
auto logger = logging.get("unit-test:rtds2gpu");
/* Collect neccessary IPs */
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 rtds2gpu = dynamic_cast<villas::fpga::ip::Rtds2Gpu*>(
state.cards.front()->lookupIp(villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:")));
auto rtds2gpu = std::dynamic_pointer_cast<fpga::ip::Rtds2Gpu>(
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");
auto gpuPlugin = villas::Registry::lookup<GpuFactory>("cuda");
auto gpuPlugin = Registry::lookup<GpuFactory>("cuda");
cr_assert_not_null(gpuPlugin, "No GPU plugin found");
auto gpus = gpuPlugin->make();
@ -285,15 +287,15 @@ Test(fpga, rtds2gpu_rtt_gpu, .description = "Rtds2Gpu RTT via GPU")
auto gpu2rtdsRegisters = gpu->translate(gpu2rtds->getRegisterMemory());
auto frameRegister = reinterpret_cast<uint32_t*>(gpu2rtdsRegisters.getLocalAddr(gpu2rtds->registerFrameOffset));
auto controlRegister = reinterpret_cast<villas::fpga::ip::ControlRegister*>(gpu2rtdsRegisters.getLocalAddr(gpu2rtds->registerControlAddr));
auto controlRegister = reinterpret_cast<fpga::ip::ControlRegister*>(gpu2rtdsRegisters.getLocalAddr(gpu2rtds->registerControlAddr));
// auto doorbellInCpu = reinterpret_cast<reg_doorbell_t*>(&gpuRam[DOORBELL_OFFSET]);
for (auto& ip : state.cards.front()->ips) {
if (*ip != villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:"))
if (*ip != fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:"))
continue;
auto& rtds = dynamic_cast<villas::fpga::ip::Rtds&>(*ip);
auto& rtds = dynamic_cast<fpga::ip::Rtds&>(*ip);
logger->info("Testing {}", rtds);

View file

@ -22,12 +22,12 @@
#include <criterion/criterion.h>
#include <villas/fpga/card.h>
#include <villas/fpga/vlnv.h>
#include <villas/fpga/card.hpp>
#include <villas/fpga/vlnv.hpp>
#include <villas/fpga/ips/dma.h>
#include <villas/fpga/ips/switch.h>
#include <villas/fpga/ips/rtds_axis.h>
#include <villas/fpga/ips/dma.hpp>
#include <villas/fpga/ips/switch.hpp>
#include <villas/fpga/ips/rtds.hpp>
extern struct fpga_card *card;
@ -38,12 +38,29 @@ Test(fpga, rtds_rtt, .description = "RTDS: tight rtt")
struct dma_mem buf;
size_t recvlen;
/* Get IP cores */
rtds = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL });
cr_assert(rtds);
std::list<villas::fpga::ip::Rtds*> rtdsIps;
std::list<villas::fpga::ip::Dma*> dmaIps;
ip = fpga_vlnv_lookup(&card->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_dma", NULL });
cr_assert(ip);
/* 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<villas::fpga::ip::Rtds*>(ip.get());
rtdsIps.push_back(rtds);
}
if (*ip == villas::fpga::Vlnv("xilinx.com:ip:axi_dma:")) {
auto dma = reinterpret_cast<villas::fpga::ip::Dma*>(ip.get());
dmaIps.push_back(dma);
}
}
for (auto rtds : rtdsIps) {
for (auto dma : dmaIps) {
rtds->connect
}
}
ret = switch_connect(card->sw, rtds, ip);
cr_assert_eq(ret, 0, "Failed to configure switch");

View file

@ -34,7 +34,6 @@ 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:")) {
@ -43,32 +42,31 @@ Test(fpga, timer, .description = "Timer Counter")
logger->info("Testing {}", *ip);
count++;
auto timer = dynamic_cast<villas::fpga::ip::Timer&>(*ip);
logger->info("Test simple waiting");
timer.start(timer.getFrequency() / 10);
cr_assert(timer.wait(), "Waiting failed");
logger->info("-> passed");
logger->info(CLR_GRN("Passed"));
logger->info("Measure waiting time (1s)");
timer.start(timer.getFrequency());
timer.start(timer.getFrequency());
const auto start = 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<std::chrono::microseconds>(duration).count();
logger->info("-> time passed: {} us", durationUs);
const auto durationUs = std::chrono::duration_cast<std::chrono::microseconds>(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"));
logger->info(CLR_GRN("Passed:") " Time passed: {} us", durationUs);
count++;
}
cr_assert(count > 0, "No timer found");