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:
parent
bb8a711f02
commit
7c92a30ab4
20 changed files with 179 additions and 166 deletions
|
@ -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;
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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 = 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);
|
||||
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Add table
Reference in a new issue