/** FIFO unit test. * * @file * @author Steffen Vogel * @copyright 2017, Steffen Vogel * @license GNU General Public License (version 3) * * VILLASfpga * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . *********************************************************************************/ #include #include #include #include #include #include #include #include #include #include "global.hpp" static constexpr size_t SAMPLE_SIZE = 4; static constexpr size_t SAMPLE_COUNT = 1; static constexpr size_t FRAME_SIZE = SAMPLE_COUNT * SAMPLE_SIZE; static constexpr size_t DOORBELL_OFFSET = SAMPLE_COUNT; static constexpr size_t DATA_OFFSET = 0; static void dumpMem(const uint32_t* addr, size_t len) { const size_t bytesPerLine = 16; const size_t lines = (len) / bytesPerLine + 1; const uint8_t* buf = reinterpret_cast(addr); size_t bytesRead = 0; for(size_t line = 0; line < lines; line++) { const unsigned base = line * bytesPerLine; printf("0x%04x: ", base); for(size_t i = 0; i < bytesPerLine && bytesRead < len; i++) { printf("0x%02x ", buf[base + i]); bytesRead++; } puts(""); } } Test(fpga, rtds2gpu, .description = "Rtds2Gpu") { auto logger = loggerGetOrCreate("unittest:rtds2gpu"); for(auto& ip : state.cards.front()->ips) { if(*ip != villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:")) continue; logger->info("Testing {}", *ip); /* Collect neccessary IPs */ auto rtds2gpu = dynamic_cast(*ip); auto axiSwitch = dynamic_cast( state.cards.front()->lookupIp(villas::fpga::Vlnv("xilinx.com:ip:axis_switch:"))); auto dma = dynamic_cast( state.cards.front()->lookupIp(villas::fpga::Vlnv("xilinx.com:ip:axi_dma:"))); auto gpu2rtds = dynamic_cast( state.cards.front()->lookupIp(villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:"))); auto rtds = dynamic_cast( state.cards.front()->lookupIp(villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:"))); cr_assert_not_null(axiSwitch, "No AXI switch IP found"); cr_assert_not_null(dma, "No DMA IP found"); cr_assert_not_null(gpu2rtds, "No Gpu2Rtds IP found"); cr_assert_not_null(rtds, "RTDS IP not found"); rtds2gpu.dump(spdlog::level::debug); gpu2rtds->dump(spdlog::level::debug); /* Allocate and prepare memory */ // allocate space for all samples and doorbell register auto dmaMemSrc = villas::HostDmaRam::getAllocator(0).allocate(SAMPLE_COUNT + 1); auto dmaMemDst = villas::HostDmaRam::getAllocator(0).allocate(SAMPLE_COUNT + 1); auto dmaMemDst2 = villas::HostDmaRam::getAllocator(0).allocate(SAMPLE_COUNT + 1); memset(&dmaMemSrc, 0x11, dmaMemSrc.getMemoryBlock().getSize()); memset(&dmaMemDst, 0x55, dmaMemDst.getMemoryBlock().getSize()); memset(&dmaMemDst2, 0x77, dmaMemDst2.getMemoryBlock().getSize()); const uint32_t* dataSrc = &dmaMemSrc[DATA_OFFSET]; const uint32_t* dataDst = &dmaMemDst[DATA_OFFSET]; const uint32_t* dataDst2 = &dmaMemDst2[0]; dumpMem(dataSrc, dmaMemSrc.getMemoryBlock().getSize()); dumpMem(dataDst, dmaMemDst.getMemoryBlock().getSize()); dumpMem(dataDst2, dmaMemDst2.getMemoryBlock().getSize()); // connect AXI Stream from DMA to Rtds2Gpu IP cr_assert(dma->connect(rtds2gpu)); cr_assert(rtds2gpu.startOnce(dmaMemDst.getMemoryBlock(), SAMPLE_COUNT, DATA_OFFSET * 4, DOORBELL_OFFSET * 4), "Preparing Rtds2Gpu IP failed"); cr_assert(dma->write(dmaMemSrc.getMemoryBlock(), FRAME_SIZE), "Starting DMA MM2S transfer failed"); cr_assert(dma->writeComplete(), "DMA failed"); while(not rtds2gpu.isFinished()); const uint32_t* doorbellDst = &dmaMemDst[DOORBELL_OFFSET]; rtds2gpu.dump(spdlog::level::info); rtds2gpu.dumpDoorbell(*doorbellDst); cr_assert(memcmp(dataSrc, dataDst, FRAME_SIZE) == 0, "Memory not equal"); for(size_t i = 0; i < SAMPLE_COUNT; i++) { gpu2rtds->registerFrames[i] = dmaMemDst[i]; } // connect AXI Stream from Gpu2Rtds IP to DMA cr_assert(gpu2rtds->connect(*dma)); cr_assert(dma->read(dmaMemDst2.getMemoryBlock(), FRAME_SIZE), "Starting DMA S2MM transfer failed"); cr_assert(gpu2rtds->startOnce(SAMPLE_COUNT), "Preparing Gpu2Rtds IP failed"); cr_assert(dma->readComplete(), "DMA failed"); while(not gpu2rtds->isFinished()); cr_assert(memcmp(dataSrc, dataDst2, FRAME_SIZE) == 0, "Memory not equal"); dumpMem(dataSrc, dmaMemSrc.getMemoryBlock().getSize()); dumpMem(dataDst, dmaMemDst.getMemoryBlock().getSize()); dumpMem(dataDst2, dmaMemDst2.getMemoryBlock().getSize()); logger->info(TXT_GREEN("Passed")); } } Test(fpga, rtds2gpu_rtt_cpu, .description = "Rtds2Gpu RTT via CPU") { auto logger = loggerGetOrCreate("unittest:rtds2gpu"); /* Collect neccessary IPs */ auto gpu2rtds = dynamic_cast( state.cards.front()->lookupIp(villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:"))); auto rtds2gpu = dynamic_cast( state.cards.front()->lookupIp(villas::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:")) continue; auto& rtds = dynamic_cast(*ip); logger->info("Testing {}", rtds); auto dmaRam = villas::HostDmaRam::getAllocator().allocate(SAMPLE_COUNT + 1); uint32_t* data = &dmaRam[DATA_OFFSET]; uint32_t* doorbell = &dmaRam[DOORBELL_OFFSET]; // TEST: rtds loopback via switch // cr_assert(rtds.connect(rtds)); // logger->info("loopback"); // while(1); cr_assert(rtds.connect(*rtds2gpu)); cr_assert(gpu2rtds->connect(rtds)); size_t count = 0; while(true) { rtds2gpu->doorbellReset(*doorbell); rtds2gpu->startOnce(dmaRam.getMemoryBlock(), SAMPLE_COUNT, DATA_OFFSET * 4, DOORBELL_OFFSET * 4); // while(not rtds2gpu->isFinished()); while(not rtds2gpu->doorbellIsValid(*doorbell)); // rtds2gpu->dump(); // rtds2gpu->dumpDoorbell(data[1]); // dumpMem(data, FRAME_SIZE + SAMPLE_SIZE); // copy samples to gpu2rtds IP for(size_t i = 0; i < SAMPLE_COUNT; i++) { gpu2rtds->registerFrames[i] = data[i]; } gpu2rtds->startOnce(SAMPLE_COUNT); // while(not gpu2rtds->isFinished()); count++; // logger->debug("Successful iterations {}, data {}", count, data[0]); } } }