mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
move more of the switch configuration boilerplate into ConnectString
Signed-off-by: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
This commit is contained in:
parent
147725daef
commit
b2fcfeaa67
5 changed files with 237 additions and 183 deletions
|
@ -84,11 +84,21 @@ public:
|
|||
return *portsMaster.at(name);
|
||||
}
|
||||
|
||||
const std::map<std::string, std::shared_ptr<StreamVertex>> &getMasterPorts() const
|
||||
{
|
||||
return portsMaster;
|
||||
}
|
||||
|
||||
const StreamVertex& getSlavePort(const std::string &name) const
|
||||
{
|
||||
return *portsSlave.at(name);
|
||||
}
|
||||
|
||||
const std::map<std::string, std::shared_ptr<StreamVertex>> &getSlavePorts() const
|
||||
{
|
||||
return portsSlave;
|
||||
}
|
||||
|
||||
bool connect(const StreamVertex &from, const StreamVertex &to);
|
||||
bool connect(const StreamVertex &from, const StreamVertex &to, bool reverse)
|
||||
{
|
||||
|
|
|
@ -20,34 +20,39 @@ setupFpgaCard(const std::string &configFile, const std::string &fpgaName);
|
|||
int createCards(json_t *config, std::list<std::shared_ptr<fpga::Card>> &cards,
|
||||
std::filesystem::path &searchPath);
|
||||
|
||||
std::shared_ptr<std::vector<std::shared_ptr<fpga::ip::Node>>>
|
||||
getAuroraChannels(std::shared_ptr<fpga::Card> card);
|
||||
|
||||
void setupColorHandling();
|
||||
|
||||
class ConnectString {
|
||||
public:
|
||||
ConnectString(std::string& connectString, int maxPortNum = 7);
|
||||
|
||||
void parseString(std::string& connectString);
|
||||
int portStringToInt(std::string &str) const;
|
||||
void configCrossBar(std::shared_ptr<villas::fpga::ip::Dma> dma,
|
||||
std::vector<std::shared_ptr<villas::fpga::ip::Node>>
|
||||
&switch_channels) const;
|
||||
|
||||
enum class ConnectType { AURORA, DMA, DINO, LOOPBACK };
|
||||
ConnectString(std::string &connectString, int maxPortNum = 7);
|
||||
void parseString(std::string &connectString);
|
||||
int portStringToInt(std::string &str) const;
|
||||
void configCrossBar(std::shared_ptr<villas::fpga::Card> card) const;
|
||||
bool isBidirectional() const { return bidirectional; };
|
||||
bool isDmaLoopback() const { return dmaLoopback; };
|
||||
bool isSrcStdin() const { return srcIsStdin; };
|
||||
bool isDstStdout() const { return dstIsStdout; };
|
||||
int getSrcAsInt() const { return srcAsInt; };
|
||||
int getDstAsInt() const { return dstAsInt; };
|
||||
bool isDmaLoopback() const { return srcType == ConnectType::LOOPBACK; };
|
||||
bool isSrcStdin() const { return srcType == ConnectType::DMA; };
|
||||
bool isDstStdout() const { return dstType == ConnectType::DMA; };
|
||||
int getSrcAsInt() const { return srcAsInt; };
|
||||
int getDstAsInt() const { return dstAsInt; };
|
||||
static std::string connectTypeToString(ConnectType type) {
|
||||
static const std::string connectTypeStrings[] = {"aurora", "dma", "dino",
|
||||
"loopback"};
|
||||
return connectTypeStrings[(int)type];
|
||||
}
|
||||
|
||||
protected:
|
||||
villas::Logger log;
|
||||
int maxPortNum;
|
||||
bool bidirectional;
|
||||
bool invert;
|
||||
int srcAsInt;
|
||||
int dstAsInt;
|
||||
bool srcIsStdin;
|
||||
bool dstIsStdout;
|
||||
bool dmaLoopback;
|
||||
villas::Logger log;
|
||||
int maxPortNum;
|
||||
bool bidirectional;
|
||||
bool invert;
|
||||
ConnectType srcType;
|
||||
ConnectType dstType;
|
||||
int srcAsInt;
|
||||
int dstAsInt;
|
||||
};
|
||||
|
||||
class BufferedSampleFormatter {
|
||||
|
|
|
@ -37,71 +37,51 @@ struct villasfpga_memory_t {
|
|||
|
||||
villasfpga_handle villasfpga_init(const char *configFile)
|
||||
{
|
||||
std::string fpgaName = "vc707";
|
||||
std::string connectStr = "3<->pipe";
|
||||
std::string outputFormat = "short";
|
||||
bool dumpGraph = false;
|
||||
bool dumpAuroraChannels = true;
|
||||
try {
|
||||
// Logging setup
|
||||
logging.setLevel(spdlog::level::debug);
|
||||
fpga::setupColorHandling();
|
||||
std::string fpgaName = "vc707";
|
||||
std::string connectStr = "3<->pipe";
|
||||
std::string outputFormat = "short";
|
||||
bool dumpGraph = false;
|
||||
bool dumpAuroraChannels = true;
|
||||
try {
|
||||
// Logging setup
|
||||
logging.setLevel(spdlog::level::debug);
|
||||
fpga::setupColorHandling();
|
||||
|
||||
if (configFile == nullptr || configFile[0] == '\0') {
|
||||
logger->error("No configuration file provided/ Please use -c/--config argument");
|
||||
return nullptr;
|
||||
}
|
||||
if (configFile == nullptr || configFile[0] == '\0') {
|
||||
logger->error(
|
||||
"No configuration file provided/ Please use -c/--config argument");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto handle = new villasfpga_handle_t;
|
||||
handle->card = fpga::setupFpgaCard(configFile, fpgaName);
|
||||
auto handle = new villasfpga_handle_t;
|
||||
handle->card = fpga::setupFpgaCard(configFile, fpgaName);
|
||||
|
||||
std::vector<std::shared_ptr<fpga::ip::Node>> switch_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::Node>(
|
||||
handle->card->lookupIp(id));
|
||||
if (aurora == nullptr) {
|
||||
logger->error("No Aurora interface found on FPGA");
|
||||
return nullptr;
|
||||
}
|
||||
if (dumpGraph) {
|
||||
auto &mm = MemoryManager::get();
|
||||
mm.getGraph().dump("graph.dot");
|
||||
}
|
||||
|
||||
switch_channels.push_back(aurora);
|
||||
}
|
||||
if (dumpAuroraChannels) {
|
||||
auto aurora_channels = getAuroraChannels(handle->card);
|
||||
for (auto aurora : *aurora_channels)
|
||||
aurora->dump();
|
||||
}
|
||||
|
||||
handle->dma = std::dynamic_pointer_cast<fpga::ip::Dma>
|
||||
(handle->card->lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:")));
|
||||
if (handle->dma == nullptr) {
|
||||
logger->error("No DMA found on FPGA ");
|
||||
return nullptr;
|
||||
}
|
||||
// Configure Crossbar switch
|
||||
const fpga::ConnectString parsedConnectString(connectStr);
|
||||
parsedConnectString.configCrossBar(handle->card);
|
||||
|
||||
if (dumpGraph) {
|
||||
auto &mm = MemoryManager::get();
|
||||
mm.getGraph().dump("graph.dot");
|
||||
}
|
||||
|
||||
if (dumpAuroraChannels) {
|
||||
for (auto aurora : switch_channels)
|
||||
aurora->dump();
|
||||
}
|
||||
|
||||
// Configure Crossbar switch
|
||||
const fpga::ConnectString parsedConnectString(connectStr);
|
||||
parsedConnectString.configCrossBar(handle->dma,
|
||||
switch_channels);
|
||||
|
||||
return handle;
|
||||
} catch (const RuntimeError &e) {
|
||||
logger->error("Error: {}", e.what());
|
||||
return nullptr;
|
||||
} catch (const std::exception &e) {
|
||||
logger->error("Error: {}", e.what());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
logger->error("Unknown error");
|
||||
return nullptr;
|
||||
}
|
||||
return handle;
|
||||
} catch (const RuntimeError &e) {
|
||||
logger->error("Error: {}", e.what());
|
||||
return nullptr;
|
||||
} catch (const std::exception &e) {
|
||||
logger->error("Error: {}", e.what());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
logger->error("Unknown error");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void villasfpga_destroy(villasfpga_handle handle)
|
||||
|
|
|
@ -23,80 +23,106 @@
|
|||
#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/core.hpp>
|
||||
#include <villas/fpga/ips/aurora_xilinx.hpp>
|
||||
#include <villas/fpga/ips/dino.hpp>
|
||||
#include <villas/fpga/ips/dma.hpp>
|
||||
#include <villas/fpga/ips/rtds.hpp>
|
||||
#include <villas/fpga/ips/aurora_xilinx.hpp>
|
||||
#include <villas/fpga/utils.hpp>
|
||||
#include <villas/fpga/vlnv.hpp>
|
||||
|
||||
using namespace villas;
|
||||
|
||||
static auto logger = villas::logging.get("streamer");
|
||||
|
||||
fpga::ConnectString::ConnectString(std::string& connectString, int maxPortNum) :
|
||||
log(villas::logging.get("ConnectString")),
|
||||
maxPortNum(maxPortNum),
|
||||
bidirectional(false),
|
||||
invert(false),
|
||||
srcAsInt(-1),
|
||||
dstAsInt(-1),
|
||||
srcIsStdin(false),
|
||||
dstIsStdout(false),
|
||||
dmaLoopback(false)
|
||||
{
|
||||
parseString(connectString);
|
||||
std::shared_ptr<std::vector<std::shared_ptr<fpga::ip::Node>>>
|
||||
fpga::getAuroraChannels(std::shared_ptr<fpga::Card> card) {
|
||||
auto aurora_channels =
|
||||
std::make_shared<std::vector<std::shared_ptr<fpga::ip::Node>>>();
|
||||
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<fpga::ip::Node>(card->lookupIp(id));
|
||||
if (aurora == nullptr) {
|
||||
logger->error("No Aurora interface found on FPGA");
|
||||
throw std::runtime_error("No Aurora interface found on FPGA");
|
||||
}
|
||||
|
||||
aurora_channels->push_back(aurora);
|
||||
}
|
||||
return aurora_channels;
|
||||
}
|
||||
|
||||
fpga::ConnectString::ConnectString(std::string &connectString, int maxPortNum)
|
||||
: log(villas::logging.get("ConnectString")), maxPortNum(maxPortNum),
|
||||
bidirectional(false), invert(false), srcType(ConnectType::LOOPBACK),
|
||||
dstType(ConnectType::LOOPBACK), srcAsInt(-1), dstAsInt(-1) {
|
||||
parseString(connectString);
|
||||
}
|
||||
|
||||
void fpga::ConnectString::parseString(std::string& connectString)
|
||||
{
|
||||
if (connectString.empty())
|
||||
return;
|
||||
if (connectString.empty())
|
||||
return;
|
||||
|
||||
if (connectString == "loopback") {
|
||||
logger->info("Connecting loopback");
|
||||
srcIsStdin = true;
|
||||
dstIsStdout = true;
|
||||
bidirectional = true;
|
||||
dmaLoopback = true;
|
||||
return;
|
||||
}
|
||||
if (connectString == "loopback") {
|
||||
logger->info("Connecting loopback");
|
||||
srcType = ConnectType::LOOPBACK;
|
||||
dstType = ConnectType::LOOPBACK;
|
||||
bidirectional = true;
|
||||
return;
|
||||
}
|
||||
static const std::regex regex("([0-9]+|stdin|stdout|pipe|dma|dino)([<\\->]+)("
|
||||
"[0-9]+|stdin|stdout|pipe|dma|dino)");
|
||||
std::smatch match;
|
||||
|
||||
static const std::regex regex(
|
||||
"([0-9]+)([<\\->]+)([0-9]+|stdin|stdout|pipe|dma)");
|
||||
std::smatch match;
|
||||
if (!std::regex_match(connectString, match, regex) || match.size() != 4) {
|
||||
logger->error("Invalid connect string: {}", connectString);
|
||||
throw std::runtime_error("Invalid connect string");
|
||||
}
|
||||
|
||||
if (!std::regex_match(connectString, match, regex) ||
|
||||
match.size() != 4) {
|
||||
logger->error("Invalid connect string: {}", connectString);
|
||||
throw std::runtime_error("Invalid connect string");
|
||||
}
|
||||
if (match[2] == "<->") {
|
||||
bidirectional = true;
|
||||
} else if (match[2] == "<-") {
|
||||
invert = true;
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
std::string srcStr = (invert ? match[3] : match[1]);
|
||||
std::string dstStr = (invert ? match[1] : match[3]);
|
||||
|
||||
srcAsInt = portStringToInt(srcStr);
|
||||
dstAsInt = portStringToInt(dstStr);
|
||||
if (srcAsInt == -1) {
|
||||
srcIsStdin = true;
|
||||
dstIsStdout = bidirectional;
|
||||
}
|
||||
if (dstAsInt == -1) {
|
||||
dstIsStdout = true;
|
||||
srcIsStdin = bidirectional;
|
||||
}
|
||||
srcAsInt = portStringToInt(srcStr);
|
||||
dstAsInt = portStringToInt(dstStr);
|
||||
if (srcAsInt == -1) {
|
||||
if (srcStr == "dino") {
|
||||
srcType = ConnectType::DINO;
|
||||
} else if (srcStr == "dma" || srcStr == "pipe" || srcStr == "stdin" ||
|
||||
srcStr == "stdout") {
|
||||
srcType = ConnectType::DMA;
|
||||
} else {
|
||||
throw std::runtime_error("Invalid source type");
|
||||
}
|
||||
} else {
|
||||
srcType = ConnectType::AURORA;
|
||||
}
|
||||
if (dstAsInt == -1) {
|
||||
if (dstStr == "dino") {
|
||||
dstType = ConnectType::DINO;
|
||||
} else if (dstStr == "dma" || dstStr == "pipe" || dstStr == "stdin" ||
|
||||
dstStr == "stdout") {
|
||||
dstType = ConnectType::DMA;
|
||||
} else {
|
||||
throw std::runtime_error("Invalid destination type");
|
||||
}
|
||||
} else {
|
||||
dstType = ConnectType::AURORA;
|
||||
}
|
||||
}
|
||||
|
||||
int fpga::ConnectString::portStringToInt(std::string &str) const
|
||||
{
|
||||
if (str == "stdin" || str == "stdout" || str == "pipe" || str == "dma") {
|
||||
if (str == "stdin" || str == "stdout" || str == "pipe" || str == "dma" ||
|
||||
str == "dino") {
|
||||
return -1;
|
||||
} else {
|
||||
const int port = std::stoi(str);
|
||||
|
@ -111,35 +137,70 @@ int fpga::ConnectString::portStringToInt(std::string &str) const
|
|||
|
||||
// parses a string like "1->2" or "1<->stdout" and configures the crossbar accordingly
|
||||
void fpga::ConnectString::configCrossBar(
|
||||
std::shared_ptr<villas::fpga::ip::Dma> dma,
|
||||
std::vector<std::shared_ptr<fpga::ip::Node>> &switch_channels) const {
|
||||
if (dmaLoopback) {
|
||||
std::shared_ptr<villas::fpga::Card> card) const {
|
||||
|
||||
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 ");
|
||||
throw std::runtime_error("No DMA found on FPGA");
|
||||
}
|
||||
|
||||
if (isDmaLoopback()) {
|
||||
log->info("Configuring DMA loopback");
|
||||
dma->connectLoopback();
|
||||
return;
|
||||
}
|
||||
|
||||
auto aurora_channels = getAuroraChannels(card);
|
||||
|
||||
auto dinoDac = std::dynamic_pointer_cast<fpga::ip::DinoDac>(
|
||||
card->lookupIp(fpga::Vlnv("xilinx.com:module_ref:dinoif_dac:")));
|
||||
if (dinoDac == nullptr) {
|
||||
logger->error("No Dino DAC found on FPGA ");
|
||||
throw std::runtime_error("No Dino DAC found on FPGA");
|
||||
}
|
||||
|
||||
auto dinoAdc = std::dynamic_pointer_cast<fpga::ip::DinoAdc>(
|
||||
card->lookupIp(fpga::Vlnv("xilinx.com:module_ref:dinoif_fast:")));
|
||||
if (dinoAdc == nullptr) {
|
||||
logger->error("No Dino ADC found on FPGA ");
|
||||
throw std::runtime_error("No Dino ADC found on FPGA");
|
||||
}
|
||||
|
||||
log->info("Connecting {} to {}, {}directional",
|
||||
(srcAsInt == -1 ? "stdin" : std::to_string(srcAsInt)),
|
||||
(dstAsInt == -1 ? "stdout" : std::to_string(dstAsInt)),
|
||||
(srcAsInt == -1 ? connectTypeToString(srcType)
|
||||
: std::to_string(srcAsInt)),
|
||||
(dstAsInt == -1 ? connectTypeToString(dstType)
|
||||
: std::to_string(dstAsInt)),
|
||||
(bidirectional ? "bi" : "uni"));
|
||||
|
||||
std::shared_ptr<fpga::ip::Node> src;
|
||||
std::shared_ptr<fpga::ip::Node> dest;
|
||||
if (srcIsStdin) {
|
||||
if (srcType == ConnectType::DINO) {
|
||||
src = dinoAdc;
|
||||
} else if (srcType == ConnectType::DMA) {
|
||||
src = dma;
|
||||
} else {
|
||||
src = switch_channels[srcAsInt];
|
||||
src = (*aurora_channels)[srcAsInt];
|
||||
}
|
||||
|
||||
if (dstIsStdout) {
|
||||
if (dstType == ConnectType::DINO) {
|
||||
dest = dinoDac;
|
||||
} else if (dstType == ConnectType::DMA) {
|
||||
dest = dma;
|
||||
} else {
|
||||
dest = switch_channels[dstAsInt];
|
||||
dest = (*aurora_channels)[dstAsInt];
|
||||
}
|
||||
|
||||
src->connect(src->getDefaultMasterPort(), dest->getDefaultSlavePort());
|
||||
if (bidirectional) {
|
||||
if (srcType == ConnectType::DINO) {
|
||||
src = dinoDac;
|
||||
}
|
||||
if (dstType == ConnectType::DINO) {
|
||||
dest = dinoAdc;
|
||||
}
|
||||
dest->connect(dest->getDefaultMasterPort(), src->getDefaultSlavePort());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <villas/fpga/ips/dma.hpp>
|
||||
#include <villas/fpga/ips/i2c.hpp>
|
||||
#include <villas/fpga/ips/rtds.hpp>
|
||||
#include <villas/fpga/ips/switch.hpp>
|
||||
#include <villas/fpga/utils.hpp>
|
||||
#include <villas/fpga/vlnv.hpp>
|
||||
|
||||
|
@ -212,60 +213,57 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
auto card = fpga::setupFpgaCard(configFile, fpgaName);
|
||||
|
||||
std::vector<std::shared_ptr<fpga::ip::Node>> switch_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<fpga::ip::Node>(card->lookupIp(id));
|
||||
if (aurora == nullptr) {
|
||||
logger->error("No Aurora interface found on FPGA");
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch_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;
|
||||
}
|
||||
|
||||
if (dumpGraph) {
|
||||
auto &mm = MemoryManager::get();
|
||||
mm.getGraph().dump("graph.dot");
|
||||
}
|
||||
|
||||
if (dumpAuroraChannels) {
|
||||
for (auto aurora : switch_channels)
|
||||
auto aurora_channels = getAuroraChannels(card);
|
||||
for (auto aurora : *aurora_channels)
|
||||
aurora->dump();
|
||||
}
|
||||
bool dstIsStdout = false;
|
||||
bool srcIsStdin = false;
|
||||
bool writeToStdout = false;
|
||||
bool readFromStdin = false;
|
||||
// Configure Crossbar switch
|
||||
for (std::string str : connectStr) {
|
||||
const fpga::ConnectString parsedConnectString(str);
|
||||
parsedConnectString.configCrossBar(dma, switch_channels);
|
||||
dstIsStdout = dstIsStdout || parsedConnectString.isDstStdout();
|
||||
srcIsStdin = srcIsStdin || parsedConnectString.isSrcStdin();
|
||||
parsedConnectString.configCrossBar(card);
|
||||
if (parsedConnectString.isSrcStdin()) {
|
||||
readFromStdin = true;
|
||||
if (parsedConnectString.isBidirectional()) {
|
||||
writeToStdout = true;
|
||||
}
|
||||
}
|
||||
if (parsedConnectString.isDstStdout()) {
|
||||
writeToStdout = true;
|
||||
if (parsedConnectString.isBidirectional()) {
|
||||
readFromStdin = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (writeToStdout || readFromStdin) {
|
||||
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 ");
|
||||
throw std::runtime_error("No DMA found on FPGA");
|
||||
}
|
||||
std::unique_ptr<std::thread> stdInThread = nullptr;
|
||||
if (!noDma && writeToStdout) {
|
||||
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<std::thread>(readFromDmaToStdOut, dma,
|
||||
std::move(formatter));
|
||||
}
|
||||
if (!noDma && readFromStdin) {
|
||||
writeToDmaFromStdIn(dma);
|
||||
}
|
||||
|
||||
std::unique_ptr<std::thread> 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<std::thread>(readFromDmaToStdOut, dma,
|
||||
std::move(formatter));
|
||||
}
|
||||
if (!noDma && srcIsStdin) {
|
||||
writeToDmaFromStdIn(dma);
|
||||
}
|
||||
|
||||
if (stdInThread) {
|
||||
stdInThread->join();
|
||||
if (stdInThread) {
|
||||
stdInThread->join();
|
||||
}
|
||||
}
|
||||
} catch (const RuntimeError &e) {
|
||||
logger->error("Error: {}", e.what());
|
||||
|
|
Loading…
Add table
Reference in a new issue