From 1c2d8e440bb67e32517ea0ee20b48fd02990a009 Mon Sep 17 00:00:00 2001 From: Niklas Eiling Date: Tue, 9 Jan 2024 17:11:06 +0100 Subject: [PATCH] update and reformat villas-fpga-ctrl Signed-off-by: Niklas Eiling --- fpga/src/villas-fpga-ctrl.cpp | 415 +++++++++++++++++----------------- 1 file changed, 208 insertions(+), 207 deletions(-) diff --git a/fpga/src/villas-fpga-ctrl.cpp b/fpga/src/villas-fpga-ctrl.cpp index 3fa4c41b7..38d24afe8 100644 --- a/fpga/src/villas-fpga-ctrl.cpp +++ b/fpga/src/villas-fpga-ctrl.cpp @@ -7,13 +7,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include -#include -#include #include +#include #include +#include #include #include @@ -22,262 +22,263 @@ #include #include -#include #include -#include -#include -#include +#include #include +#include +#include +#include +#include #include +#include using namespace villas; static std::shared_ptr pciDevices; static auto logger = villas::logging.get("ctrl"); -void writeToDmaFromStdIn(std::shared_ptr dma) -{ - auto &alloc = villas::HostRam::getAllocator(); - const std::shared_ptr block = alloc.allocateBlock(0x200 * sizeof(float)); - villas::MemoryAccessor mem = *block; - dma->makeAccesibleFromVA(block); +void writeToDmaFromStdIn(std::shared_ptr dma) { + auto &alloc = villas::HostRam::getAllocator(); + const std::shared_ptr block = + alloc.allocateBlock(0x200 * sizeof(float)); + villas::MemoryAccessor mem = *block; + dma->makeAccesibleFromVA(block); - logger->info("Please enter values to write to the device, separated by ';'"); + logger->info("Please enter values to write to the device, separated by ';'"); - while (true) { - // Read values from stdin - std::string line; - std::getline(std::cin, line); - auto values = villas::utils::tokenize(line, ";"); + while (true) { + // Read values from stdin + std::string line; + std::getline(std::cin, line); + auto values = villas::utils::tokenize(line, ";"); - size_t i = 0; - for (auto &value: values) { - if (value.empty()) continue; + size_t i = 0; + for (auto &value : values) { + if (value.empty()) + continue; - const float number = std::stof(value); - mem[i++] = number; - } + const float number = std::stof(value); + mem[i++] = number; + } - // Initiate write transfer - bool state = dma->write(*block, i * sizeof(float)); - if (!state) - logger->error("Failed to write to device"); + // Initiate write transfer + bool state = dma->write(*block, i * sizeof(float)); + if (!state) + logger->error("Failed to write to device"); - auto writeComp = dma->writeComplete(); - logger->debug("Wrote {} bytes", writeComp.bytes); - } - // auto &alloc = villas::HostRam::getAllocator(); + auto writeComp = dma->writeComplete(); + logger->debug("Wrote {} bytes", writeComp.bytes); + } + // auto &alloc = villas::HostRam::getAllocator(); - // const std::shared_ptr block[] = { - // alloc.allocateBlock(0x200 * sizeof(uint32_t)), - // alloc.allocateBlock(0x200 * sizeof(uint32_t)) - // }; - // villas::MemoryAccessor mem[] = {*block[0], *block[1]}; + // const std::shared_ptr block[] = { + // alloc.allocateBlock(0x200 * sizeof(uint32_t)), + // alloc.allocateBlock(0x200 * sizeof(uint32_t)) + // }; + // villas::MemoryAccessor mem[] = {*block[0], *block[1]}; - // for (auto b : block) { - // dma->makeAccesibleFromVA(b); - // } + // for (auto b : block) { + // dma->makeAccesibleFromVA(b); + // } - // size_t cur = 0, next = 1; - // std::ios::sync_with_stdio(false); - // std::string line; - // bool firstXfer = true; + // size_t cur = 0, next = 1; + // std::ios::sync_with_stdio(false); + // std::string line; + // bool firstXfer = true; - // while(true) { - // // Read values from stdin + // while(true) { + // // Read values from stdin - // std::getline(std::cin, line); - // auto values = villas::utils::tokenize(line, ";"); + // std::getline(std::cin, line); + // auto values = villas::utils::tokenize(line, ";"); - // size_t i = 0; - // for (auto &value: values) { - // if (value.empty()) continue; + // size_t i = 0; + // for (auto &value: values) { + // if (value.empty()) continue; - // const float number = std::stof(value); - // mem[cur][i++] = number; - // } + // const float number = std::stof(value); + // mem[cur][i++] = number; + // } - // // Initiate write transfer - // bool state = dma->write(*block[cur], i * sizeof(float)); - // if (!state) - // logger->error("Failed to write to device"); + // // Initiate write transfer + // bool state = dma->write(*block[cur], i * sizeof(float)); + // if (!state) + // logger->error("Failed to write to device"); - // if (!firstXfer) { - // auto bytesWritten = dma->writeComplete(); - // logger->debug("Wrote {} bytes", bytesWritten.bytes); - // } else { - // firstXfer = false; - // } + // if (!firstXfer) { + // auto bytesWritten = dma->writeComplete(); + // logger->debug("Wrote {} bytes", bytesWritten.bytes); + // } else { + // firstXfer = false; + // } - // cur = next; - // next = (next + 1) % (sizeof(mem) / sizeof(mem[0])); - // } + // cur = next; + // next = (next + 1) % (sizeof(mem) / sizeof(mem[0])); + // } } -void readFromDmaToStdOut(std::shared_ptr dma, - std::unique_ptr formatter) -{ - auto &alloc = villas::HostRam::getAllocator(); +void readFromDmaToStdOut( + std::shared_ptr dma, + std::unique_ptr formatter) { + auto &alloc = villas::HostRam::getAllocator(); - const std::shared_ptr block[] = { - alloc.allocateBlock(0x200 * sizeof(uint32_t)), - alloc.allocateBlock(0x200 * sizeof(uint32_t)) - }; - villas::MemoryAccessor mem[] = {*block[0], *block[1]}; + const std::shared_ptr block[] = { + alloc.allocateBlock(0x200 * sizeof(uint32_t)), + alloc.allocateBlock(0x200 * sizeof(uint32_t))}; + villas::MemoryAccessor mem[] = {*block[0], *block[1]}; - for (auto b : block) { - dma->makeAccesibleFromVA(b); - } + for (auto b : block) { + dma->makeAccesibleFromVA(b); + } - size_t cur = 0, next = 1; - std::ios::sync_with_stdio(false); + size_t cur = 0, next = 1; + std::ios::sync_with_stdio(false); - // Setup read transfer - dma->read(*block[0], block[0]->getSize()); + // Setup read transfer + dma->read(*block[0], block[0]->getSize()); - while (true) { - logger->trace("Read from stream and write to address {}:{:p}", block[next]->getAddrSpaceId(), block[next]->getOffset()); - // We could use the number of interrupts to determine if we missed a chunk of data - dma->read(*block[next], block[next]->getSize()); - auto c = dma->readComplete(); + while (true) { + logger->trace("Read from stream and write to address {}:{:p}", + block[next]->getAddrSpaceId(), block[next]->getOffset()); + // We could use the number of interrupts to determine if we missed a chunk of data + dma->read(*block[next], block[next]->getSize()); + auto c = dma->readComplete(); - if (c.interrupts > 1) { - logger->warn("Missed {} interrupts", c.interrupts - 1); - } + if (c.interrupts > 1) { + logger->warn("Missed {} interrupts", c.interrupts - 1); + } - logger->debug("bytes: {}, intrs: {}, bds: {}", - c.bytes, c.interrupts, c.bds); - try { - for (size_t i = 0; i*4 < c.bytes; i++) { - int32_t ival = mem[cur][i]; + logger->debug("bytes: {}, intrs: {}, bds: {}", c.bytes, c.interrupts, + c.bds); + try { + for (size_t i = 0; i * 4 < c.bytes; i++) { + int32_t ival = mem[cur][i]; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" - float fval = *((float*)(&ival)); // cppcheck-suppress invalidPointerCast + float fval = + *((float *)(&ival)); // cppcheck-suppress invalidPointerCast #pragma GCC diagnostic pop - formatter->format(fval); - printf("%#x\n", ival); - } - formatter->output(std::cout); - } catch (const std::exception &e) { - logger->warn("Failed to output data: {}", e.what()); - } + formatter->format(fval); + printf("%#x\n", ival); + } + formatter->output(std::cout); + } catch (const std::exception &e) { + logger->warn("Failed to output data: {}", e.what()); + } - cur = next; - next = (next + 1) % (sizeof(mem) / sizeof(mem[0])); - } + cur = next; + next = (next + 1) % (sizeof(mem) / sizeof(mem[0])); + } } -int main(int argc, char* argv[]) -{ - // Command Line Parser - CLI::App app{"VILLASfpga data output"}; +int main(int argc, char *argv[]) { + // Command Line Parser + CLI::App app{"VILLASfpga data output"}; - try { - std::string configFile; - app.add_option("-c,--config", configFile, "Configuration file") - ->check(CLI::ExistingFile); + try { + std::string configFile; + app.add_option("-c,--config", configFile, "Configuration file") + ->check(CLI::ExistingFile); - std::string fpgaName = "vc707"; - app.add_option("--fpga", fpgaName, "Which FPGA to use"); - std::vector connectStr; - app.add_option( - "-x,--connect", connectStr, - "Connect a FPGA port with another or stdin/stdout"); - bool noDma = false; - app.add_flag( - "--no-dma", noDma, - "Do not setup DMA, only setup FPGA and Crossbar links"); - std::string outputFormat = "short"; - app.add_option("--output-format", outputFormat, - "Output format (short, long)"); - bool dumpGraph = false; - app.add_flag( - "--dump-graph", dumpGraph, - "Dumps the graph of memory regions into \"graph.dot\""); - bool dumpAuroraChannels = true; - app.add_flag("--dump-aurora", dumpAuroraChannels, "Dumps the detected Aurora channels."); - app.parse(argc, argv); + std::string fpgaName = "vc707"; + app.add_option("--fpga", fpgaName, "Which FPGA to use"); + std::vector connectStr; + app.add_option("-x,--connect", connectStr, + "Connect a FPGA port with another or stdin/stdout"); + bool noDma = false; + app.add_flag("--no-dma", noDma, + "Do not setup DMA, only setup FPGA and Crossbar links"); + std::string outputFormat = "short"; + app.add_option("--output-format", outputFormat, + "Output format (short, long)"); + bool dumpGraph = false; + app.add_flag("--dump-graph", dumpGraph, + "Dumps the graph of memory regions into \"graph.dot\""); + bool dumpAuroraChannels = true; + app.add_flag("--dump-aurora", dumpAuroraChannels, + "Dumps the detected Aurora channels."); + app.parse(argc, argv); - // Logging setup + // Logging setup - logging.setLevel(spdlog::level::debug); - fpga::setupColorHandling(); + logging.setLevel(spdlog::level::debug); + fpga::setupColorHandling(); - if (configFile.empty()) { - logger->error("No configuration file provided/ Please use -c/--config argument"); - return 1; - } + if (configFile.empty()) { + logger->error( + "No configuration file provided/ Please use -c/--config argument"); + return 1; + } - auto card = fpga::setupFpgaCard(configFile, fpgaName); + auto card = fpga::setupFpgaCard(configFile, fpgaName); - std::vector> aurora_channels; - for (int i = 0; i < 4; i++) { - auto name = fmt::format("aurora_8b10b_ch{}", i); - auto id = fpga::ip::IpIdentifier("xilinx.com:ip:aurora_8b10b:", name); - auto aurora = std::dynamic_pointer_cast(card->lookupIp(id)); - if (aurora == nullptr) { - logger->error("No Aurora interface found on FPGA"); - return 1; - } + std::vector> aurora_channels; + for (int i = 0; i < 4; i++) { + auto name = fmt::format("aurora_aurora_8b10b_ch{}", i); + auto id = fpga::ip::IpIdentifier("xilinx.com:ip:aurora_8b10b:", name); + auto aurora = + std::dynamic_pointer_cast(card->lookupIp(id)); + if (aurora == nullptr) { + logger->error("No Aurora interface found on FPGA"); + return 1; + } - aurora_channels.push_back(aurora); - } + aurora_channels.push_back(aurora); + } - auto dma = std::dynamic_pointer_cast - (card->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:"))); - if (dma == nullptr) { - logger->error("No DMA found on FPGA "); - return 1; - } + auto dma = std::dynamic_pointer_cast( + card->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:"))); + if (dma == nullptr) { + logger->error("No DMA found on FPGA "); + return 1; + } - if (dumpGraph) { - auto &mm = MemoryManager::get(); - mm.getGraph().dump("graph.dot"); - } + if (dumpGraph) { + auto &mm = MemoryManager::get(); + mm.getGraph().dump("graph.dot"); + } - if (dumpAuroraChannels) { - for (auto aurora : aurora_channels) - aurora->dump(); - } - bool dstIsStdout = false; - bool srcIsStdin = false; - // Configure Crossbar switch - for (std::string str : connectStr) { - const fpga::ConnectString parsedConnectString(str); - parsedConnectString.configCrossBar(dma, aurora_channels); - dstIsStdout = - dstIsStdout || parsedConnectString.isDstStdout(); - srcIsStdin = srcIsStdin || parsedConnectString.isSrcStdin(); - } + if (dumpAuroraChannels) { + for (auto aurora : aurora_channels) + aurora->dump(); + } + bool dstIsStdout = false; + bool srcIsStdin = false; + // Configure Crossbar switch + for (std::string str : connectStr) { + const fpga::ConnectString parsedConnectString(str); + parsedConnectString.configCrossBar(dma, aurora_channels); + dstIsStdout = dstIsStdout || parsedConnectString.isDstStdout(); + srcIsStdin = srcIsStdin || parsedConnectString.isSrcStdin(); + } - std::unique_ptr stdInThread = nullptr; - if (!noDma && dstIsStdout) { - auto formatter = - fpga::getBufferedSampleFormatter(outputFormat, 16); - // We copy the dma shared ptr but move the fomatter unqiue ptr as we don't need it - // in this thread anymore - stdInThread = std::make_unique( - readFromDmaToStdOut, dma, std::move(formatter)); - } - if (!noDma && srcIsStdin) { - writeToDmaFromStdIn(dma); - } + std::unique_ptr stdInThread = nullptr; + if (!noDma && dstIsStdout) { + auto formatter = fpga::getBufferedSampleFormatter(outputFormat, 16); + // We copy the dma shared ptr but move the fomatter unqiue ptr as we don't need it + // in this thread anymore + stdInThread = std::make_unique(readFromDmaToStdOut, dma, + std::move(formatter)); + } + if (!noDma && srcIsStdin) { + writeToDmaFromStdIn(dma); + } - if (stdInThread) { - stdInThread->join(); - } - } catch (const RuntimeError &e) { - logger->error("Error: {}", e.what()); - return -1; - } catch (const CLI::ParseError &e) { - return app.exit(e); - } catch (const std::exception &e) { - logger->error("Error: {}", e.what()); - return -1; - } catch (...) { - logger->error("Unknown error"); - return -1; - } + if (stdInThread) { + stdInThread->join(); + } + } catch (const RuntimeError &e) { + logger->error("Error: {}", e.what()); + return -1; + } catch (const CLI::ParseError &e) { + return app.exit(e); + } catch (const std::exception &e) { + logger->error("Error: {}", e.what()); + return -1; + } catch (...) { + logger->error("Unknown error"); + return -1; + } - return 0; + return 0; }