From a818bc0b648709ffad4449154a5399b511986243 Mon Sep 17 00:00:00 2001 From: Niklas Eiling Date: Wed, 4 Jan 2023 17:11:57 +0100 Subject: [PATCH] combine functionalities of binaries into a single one combine what was previously achieved by the separate binaries villas-fpga-xbar-select and villas-fpga-cat into a single new binary villas-fpga-ctl. Here we can select crossbar connections via command line parameters. To avoid regression there are shell scripts providing the old functionalities directly. Currently the villas-fpga-pipe functionality is not supported, because we still need to implement stdin input and routing that to the fpga. Signed-off-by: Niklas Eiling --- fpga/.vscode/launch.json | 4 +- fpga/include/villas/fpga/fpgaHelper.hpp | 4 + fpga/lib/fpgaHelper.cpp | 59 +++++++++ fpga/src/CMakeLists.txt | 15 +-- fpga/src/villas-fpga-cat.sh | 18 +++ ...llas-fpga-cat.cpp => villas-fpga-ctrl.cpp} | 91 +++++++------- fpga/src/villas-fpga-xbar-select.cpp | 118 ------------------ fpga/src/villas-fpga-xbar-select.sh | 19 +++ 8 files changed, 156 insertions(+), 172 deletions(-) create mode 100755 fpga/src/villas-fpga-cat.sh rename fpga/src/{villas-fpga-cat.cpp => villas-fpga-ctrl.cpp} (69%) delete mode 100644 fpga/src/villas-fpga-xbar-select.cpp create mode 100644 fpga/src/villas-fpga-xbar-select.sh diff --git a/fpga/.vscode/launch.json b/fpga/.vscode/launch.json index 50829781b..42ab0f641 100644 --- a/fpga/.vscode/launch.json +++ b/fpga/.vscode/launch.json @@ -8,9 +8,9 @@ "name": "(gdb) Launch", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/build/src/villas-fpga-pipe", + "program": "${workspaceFolder}/build/src/villas-fpga-ctrl", "args": [ - "-c", "${workspaceFolder}/etc/fpgas.json" + "-c", "${workspaceFolder}/etc/fpgas.json", "--connect", "\"2<->stdout\"", "--no-dma" ], "stopAtEntry": false, "cwd": "${workspaceFolder}", diff --git a/fpga/include/villas/fpga/fpgaHelper.hpp b/fpga/include/villas/fpga/fpgaHelper.hpp index f9e6a1696..e9ee48163 100644 --- a/fpga/include/villas/fpga/fpgaHelper.hpp +++ b/fpga/include/villas/fpga/fpgaHelper.hpp @@ -32,6 +32,10 @@ namespace fpga { std::shared_ptr setupFpgaCard(const std::string &configFile, const std::string &fpgaName); +void configCrossBarUsingConnectString(std::string connectString, + std::shared_ptr dma, + std::vector>& aurora_channels); + void setupColorHandling(); } /* namespace fpga */ diff --git a/fpga/lib/fpgaHelper.cpp b/fpga/lib/fpgaHelper.cpp index d255bcc71..502380001 100644 --- a/fpga/lib/fpgaHelper.cpp +++ b/fpga/lib/fpgaHelper.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -48,6 +49,64 @@ using namespace villas; static std::shared_ptr pciDevices; static auto logger = villas::logging.get("streamer"); +const std::shared_ptr portStringToStreamVertex(std::string &str, + std::shared_ptr dma, + std::vector>& aurora_channels) +{ + if (str == "stdin" || str == "stdout") { + return dma; + } else { + int port = std::stoi(str); + + if (port > 7 || port < 0) + throw std::runtime_error("Invalid port number"); + + return aurora_channels[port]; + } +} +// parses a string lik "1->2" or "1<->stdout" and configures the crossbar +void fpga::configCrossBarUsingConnectString(std::string connectString, + std::shared_ptr dma, + std::vector>& aurora_channels) +{ + bool bidirectional = false; + bool invert = false; + + if (connectString.empty()) + return; + + if (connectString == "loopback") { + logger->info("Connecting loopback"); + // is this working? + dma->connectLoopback(); + } + + static std::regex re("([0-9]+)([<\\->]+)([0-9]+|stdin|stdout)"); + std::smatch match; + + if (!std::regex_match(connectString, match, re)) { + logger->error("Invalid connect string: {}", connectString); + throw std::runtime_error("Invalid connect string"); + } + if (match[2] == "<->") { + bidirectional = true; + } else if(match[2] == "<-") { + invert = true; + } + + std::string srcStr = (invert ? match[3] : match[1]); + std::string dstStr = (invert ? match[1] : match[3]); + logger->info("Connect string {}: Connecting {} to {}, {}directional", + connectString, srcStr, dstStr, + (bidirectional ? "bi" : "uni")); + auto src = portStringToStreamVertex(srcStr, dma, aurora_channels); + auto dest = portStringToStreamVertex(dstStr, dma, aurora_channels); + src->connect(src->getDefaultMasterPort(), dest->getDefaultSlavePort()); + if (bidirectional) { + dest->connect(dest->getDefaultMasterPort(), src->getDefaultSlavePort()); + } +} + void fpga::setupColorHandling() { // Handle Control-C nicely diff --git a/fpga/src/CMakeLists.txt b/fpga/src/CMakeLists.txt index bded7cb3b..dda082632 100644 --- a/fpga/src/CMakeLists.txt +++ b/fpga/src/CMakeLists.txt @@ -20,18 +20,13 @@ # along with this program. If not, see . ############################################################################## -add_executable(villas-fpga-pipe villas-fpga-pipe.cpp) -add_executable(villas-fpga-cat villas-fpga-cat.cpp) -add_executable(villas-fpga-xbar-select villas-fpga-xbar-select.cpp) +add_executable(villas-fpga-ctrl villas-fpga-ctrl.cpp) -target_link_libraries(villas-fpga-pipe PUBLIC - villas-fpga -) -target_link_libraries(villas-fpga-cat PUBLIC - villas-fpga -) -target_link_libraries(villas-fpga-xbar-select PUBLIC +target_link_libraries(villas-fpga-ctrl PUBLIC villas-fpga ) add_executable(pcimem pcimem.c) + +configure_file(villas-fpga-cat.sh villas-fpga-cat.sh COPYONLY) +configure_file(villas-fpga-xbar-select.sh villas-fpga-xbar-select.sh COPYONLY) diff --git a/fpga/src/villas-fpga-cat.sh b/fpga/src/villas-fpga-cat.sh new file mode 100755 index 000000000..8260be773 --- /dev/null +++ b/fpga/src/villas-fpga-cat.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Copyright 2023 Niklas Eiling +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +CWD=$(dirname -- "$0") + +${CWD}/villas-fpga-cat -c ${CWD}/../../etc/fpgas.json --connect "2<->stdout" diff --git a/fpga/src/villas-fpga-cat.cpp b/fpga/src/villas-fpga-ctrl.cpp similarity index 69% rename from fpga/src/villas-fpga-cat.cpp rename to fpga/src/villas-fpga-ctrl.cpp index 5b4f54bd7..56689ad3f 100644 --- a/fpga/src/villas-fpga-cat.cpp +++ b/fpga/src/villas-fpga-ctrl.cpp @@ -1,7 +1,9 @@ /** Streaming data from STDIN/OUT to FPGA. * * @author Daniel Krebs + * @author Niklas Eiling * @copyright 2017-2022, Steffen Vogel + * @copyright 2022-2023, Niklas Eiling * @license GNU General Public License (version 3) * * VILLASfpga @@ -48,6 +50,8 @@ using namespace villas; static std::shared_ptr pciDevices; static auto logger = villas::logging.get("cat"); + + int main(int argc, char* argv[]) { // Command Line Parser @@ -60,6 +64,11 @@ int main(int argc, char* argv[]) std::string fpgaName = "vc707"; app.add_option("--fpga", fpgaName, "Which FPGA to use"); + std::string 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"); + app.parse(argc, argv); // Logging setup @@ -105,50 +114,48 @@ int main(int argc, char* argv[]) aurora->dump(); // Configure Crossbar switch -#if 1 - aurora_channels[2]->connect(aurora_channels[2]->getDefaultMasterPort(), dma->getDefaultSlavePort()); - dma->connect(dma->getDefaultMasterPort(), aurora_channels[2]->getDefaultSlavePort()); -#else - dma->connectLoopback(); -#endif - for (auto b : block) { - dma->makeAccesibleFromVA(b); - } + fpga::configCrossBarUsingConnectString(connectStr, dma, aurora_channels); - auto &mm = MemoryManager::get(); - mm.getGraph().dump("graph.dot"); - - // Setup read transfer - dma->read(block[0], block[0].getSize()); - size_t cur = 0, next = 1; - while (true) { - dma->read(block[next], block[next].getSize()); - auto bytesRead = dma->readComplete(); - // Setup read transfer - - //auto valuesRead = bytesRead / sizeof(int32_t); - //logger->info("Read {} bytes", bytesRead); - - //for (size_t i = 0; i < valuesRead; i++) - // std::cerr << std::hex << mem[i] << ";"; - //std::cerr << std::endl; - - for (size_t i = 0; i*4 < bytesRead; i++) { - int32_t ival = mem[cur][i]; - float fval = *((float*)(&ival)); // cppcheck-suppress invalidPointerCast - //std::cerr << std::hex << ival << ","; - std::cerr << fval << std::endl; - /*int64_t ival = (int64_t)(mem[1] & 0xFFFF) << 48 | - (int64_t)(mem[1] & 0xFFFF0000) << 16 | - (int64_t)(mem[0] & 0xFFFF) << 16 | - (int64_t)(mem[0] & 0xFFFF0000) >> 16; - double dval = *((double*)(&ival)); - std::cerr << std::hex << ival << "," << dval << std::endl; - bytesRead -= 8;*/ - //logger->info("Read value: {}", dval); + if (!noDma) { + for (auto b : block) { + dma->makeAccesibleFromVA(b); + } + + auto &mm = MemoryManager::get(); + mm.getGraph().dump("graph.dot"); + + // Setup read transfer + dma->read(block[0], block[0].getSize()); + size_t cur = 0, next = 1; + while (true) { + dma->read(block[next], block[next].getSize()); + auto bytesRead = dma->readComplete(); + // Setup read transfer + + //auto valuesRead = bytesRead / sizeof(int32_t); + //logger->info("Read {} bytes", bytesRead); + + //for (size_t i = 0; i < valuesRead; i++) + // std::cerr << std::hex << mem[i] << ";"; + //std::cerr << std::endl; + + for (size_t i = 0; i*4 < bytesRead; i++) { + int32_t ival = mem[cur][i]; + float fval = *((float*)(&ival)); // cppcheck-suppress invalidPointerCast + //std::cerr << std::hex << ival << ","; + std::cerr << fval << std::endl; + /*int64_t ival = (int64_t)(mem[1] & 0xFFFF) << 48 | + (int64_t)(mem[1] & 0xFFFF0000) << 16 | + (int64_t)(mem[0] & 0xFFFF) << 16 | + (int64_t)(mem[0] & 0xFFFF0000) >> 16; + double dval = *((double*)(&ival)); + std::cerr << std::hex << ival << "," << dval << std::endl; + bytesRead -= 8;*/ + //logger->info("Read value: {}", dval); + } + cur = next; + next = (next + 1) % (sizeof(mem)/sizeof(mem[0])); } - cur = next; - next = (next + 1) % (sizeof(mem)/sizeof(mem[0])); } } catch (const RuntimeError &e) { logger->error("Error: {}", e.what()); diff --git a/fpga/src/villas-fpga-xbar-select.cpp b/fpga/src/villas-fpga-xbar-select.cpp deleted file mode 100644 index 5f165930f..000000000 --- a/fpga/src/villas-fpga-xbar-select.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/** Streaming data from STDIN/OUT to FPGA. - * - * @author Daniel Krebs - * @copyright 2017-2022, 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 -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace villas; - -static std::shared_ptr pciDevices; -static auto logger = villas::logging.get("cat"); - -int main(int argc, char* argv[]) -{ - // Command Line Parser - CLI::App app{"VILLASfpga xbar select"}; - - 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"); - app.parse(argc, argv); - - // Logging setup - spdlog::set_level(spdlog::level::debug); - fpga::setupColorHandling(); - - if (configFile.empty()) { - logger->error("No configuration file provided/ Please use -c/--config argument"); - return 1; - } - - 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; - } - - 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; - } - - for (auto aurora : aurora_channels) - aurora->dump(); - - // Configure Crossbar switch - // connect DINO to RTDS - //aurora_channels[0]->connect(aurora_channels[0]->getDefaultMasterPort(), aurora_channels[2]->getDefaultSlavePort()); - //aurora_channels[2]->connect(aurora_channels[2]->getDefaultMasterPort(), aurora_channels[0]->getDefaultSlavePort()); - // connect DINO to OPAL-RT - //aurora_channels[1]->connect(aurora_channels[1]->getDefaultMasterPort(), aurora_channels[2]->getDefaultSlavePort()); - //aurora_channels[2]->connect(aurora_channels[2]->getDefaultMasterPort(), aurora_channels[1]->getDefaultSlavePort()); - // connect OPAL-RT to RTDS - aurora_channels[0]->connect(aurora_channels[0]->getDefaultMasterPort(), aurora_channels[1]->getDefaultSlavePort()); - aurora_channels[1]->connect(aurora_channels[1]->getDefaultMasterPort(), aurora_channels[0]->getDefaultSlavePort()); - - } catch (const RuntimeError &e) { - logger->error("Error: {}", e.what()); - return -1; - } catch (const CLI::ParseError &e) { - return app.exit(e); - } - - return 0; -} diff --git a/fpga/src/villas-fpga-xbar-select.sh b/fpga/src/villas-fpga-xbar-select.sh new file mode 100644 index 000000000..b800e9873 --- /dev/null +++ b/fpga/src/villas-fpga-xbar-select.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright 2023 Niklas Eiling +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +CWD=$(dirname -- "$0") + +# currently connects RTDS and OPAL-RT +${CWD}/villas-fpga-cat -c ${CWD}/../../etc/fpgas.json --connect "0<->1" --no-dma