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

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 <niklas.eiling@eonerc.rwth-aachen.de>
This commit is contained in:
Niklas Eiling 2023-01-04 17:11:57 +01:00
parent f5b0762b1a
commit a818bc0b64
8 changed files with 156 additions and 172 deletions

View file

@ -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}",

View file

@ -32,6 +32,10 @@ namespace fpga {
std::shared_ptr<fpga::PCIeCard>
setupFpgaCard(const std::string &configFile, const std::string &fpgaName);
void configCrossBarUsingConnectString(std::string connectString,
std::shared_ptr<villas::fpga::ip::Dma> dma,
std::vector<std::shared_ptr<fpga::ip::AuroraXilinx>>& aurora_channels);
void setupColorHandling();
} /* namespace fpga */

View file

@ -26,6 +26,7 @@
#include <string>
#include <algorithm>
#include <jansson.h>
#include <regex>
#include <CLI11.hpp>
#include <rang.hpp>
@ -48,6 +49,64 @@ using namespace villas;
static std::shared_ptr<kernel::pci::DeviceList> pciDevices;
static auto logger = villas::logging.get("streamer");
const std::shared_ptr<villas::fpga::ip::Node> portStringToStreamVertex(std::string &str,
std::shared_ptr<villas::fpga::ip::Dma> dma,
std::vector<std::shared_ptr<fpga::ip::AuroraXilinx>>& 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<villas::fpga::ip::Dma> dma,
std::vector<std::shared_ptr<fpga::ip::AuroraXilinx>>& 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

View file

@ -20,18 +20,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##############################################################################
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)

18
fpga/src/villas-fpga-cat.sh Executable file
View file

@ -0,0 +1,18 @@
#!/bin/bash
# Copyright 2023 Niklas Eiling <niklas.eiling@rwth-aachen.de>
#
# 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"

View file

@ -1,7 +1,9 @@
/** Streaming data from STDIN/OUT to FPGA.
*
* @author Daniel Krebs <github@daniel-krebs.net>
* @author Niklas Eiling <niklas.eiling@rwth-aachen.de>
* @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<kernel::pci::DeviceList> 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());

View file

@ -1,118 +0,0 @@
/** Streaming data from STDIN/OUT to FPGA.
*
* @author Daniel Krebs <github@daniel-krebs.net>
* @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 <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <csignal>
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <jansson.h>
#include <CLI11.hpp>
#include <rang.hpp>
#include <villas/exceptions.hpp>
#include <villas/log.hpp>
#include <villas/utils.hpp>
#include <villas/utils.hpp>
#include <villas/fpga/core.hpp>
#include <villas/fpga/card.hpp>
#include <villas/fpga/vlnv.hpp>
#include <villas/fpga/ips/dma.hpp>
#include <villas/fpga/ips/rtds.hpp>
#include <villas/fpga/ips/aurora_xilinx.hpp>
#include <villas/fpga/fpgaHelper.hpp>
using namespace villas;
static std::shared_ptr<kernel::pci::DeviceList> 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<std::shared_ptr<fpga::ip::AuroraXilinx>> 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<fpga::ip::AuroraXilinx>(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<fpga::ip::Dma>
(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;
}

View file

@ -0,0 +1,19 @@
#!/bin/bash
# Copyright 2023 Niklas Eiling <niklas.eiling@rwth-aachen.de>
#
# 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