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

move formatting of printing to stdout to separate class and make in configurable

Signed-off-by: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
This commit is contained in:
Niklas Eiling 2023-01-09 14:12:32 +01:00
parent 498af9fd1c
commit ce1e8e28ce
2 changed files with 92 additions and 18 deletions

View file

@ -62,6 +62,87 @@ protected:
bool dmaLoopback;
};
class BufferedSampleFormatter {
public:
virtual void format(float value) = 0;
virtual void output(std::ostream& out)
{
out << buf.data() << std::flush;
clearBuf();
}
virtual void clearBuf()
{
for (size_t i = 0; i < bufSamples && buf[i*bufSampleSize] != '\0'; i++) {
buf[i*bufSampleSize] = '\0';
}
currentBufLoc = 0;
}
protected:
std::vector<char> buf;
const size_t bufSamples;
const size_t bufSampleSize;
size_t currentBufLoc;
BufferedSampleFormatter(const size_t bufSamples, const size_t bufSampleSize) :
buf(bufSamples*bufSampleSize+1), // Leave room for a final `\0'
bufSamples(bufSamples),
bufSampleSize(bufSampleSize),
currentBufLoc(0) {};
BufferedSampleFormatter() = delete;
BufferedSampleFormatter(const BufferedSampleFormatter&) = delete;
virtual char* nextBufPos()
{
return &buf[(currentBufLoc++)*bufSampleSize];
}
};
class BufferedSampleFormatterShort : public BufferedSampleFormatter {
public:
BufferedSampleFormatterShort(size_t bufSizeInSamples) :
BufferedSampleFormatter(bufSizeInSamples, formatStringSize) {};
virtual void format(float value) override
{
if (std::snprintf(nextBufPos(), formatStringSize+1, formatString, value) > (int)formatStringSize) {
throw RuntimeError("Output buffer too small");
}
}
protected:
static constexpr char formatString[] = "%7f\n";
static constexpr size_t formatStringSize = 9;
};
class BufferedSampleFormatterLong : public BufferedSampleFormatter {
public:
BufferedSampleFormatterLong(size_t bufSizeInSamples) :
BufferedSampleFormatter(bufSizeInSamples, formatStringSize),
sampleCnt(0) {};
virtual void format(float value) override
{
if (std::snprintf(nextBufPos(), formatStringSize+1, formatString, sampleCnt, value) > (int)formatStringSize) {
throw RuntimeError("Output buffer too small");
}
sampleCnt = (sampleCnt+1)%100000;
}
protected:
static constexpr char formatString[] = "%05zd: %7f\n";
static constexpr size_t formatStringSize = 16;
size_t sampleCnt;
};
std::unique_ptr<BufferedSampleFormatter> getBufferedSampleFormatter(const std::string &format, size_t bufSizeInSamples)
{
if (format == "long") {
return std::make_unique<BufferedSampleFormatterLong>(bufSizeInSamples);
} else if (format == "short") {
return std::make_unique<BufferedSampleFormatterShort>(bufSizeInSamples);
} else {
throw RuntimeError("Unknown output format '{}'", format);
}
}
} /* namespace fpga */
} /* namespace villas */

View file

@ -36,7 +36,8 @@ static std::shared_ptr<kernel::pci::DeviceList> pciDevices;
static auto logger = villas::logging.get("ctrl");
void readFromDmaToStdOut(std::shared_ptr<villas::fpga::ip::Dma> dma)
void readFromDmaToStdOut(std::shared_ptr<villas::fpga::ip::Dma> dma,
std::unique_ptr<fpga::BufferedSampleFormatter> formatter)
{
auto &alloc = villas::HostRam::getAllocator();
@ -56,33 +57,24 @@ void readFromDmaToStdOut(std::shared_ptr<villas::fpga::ip::Dma> dma)
size_t cur = 0, next = 1;
std::ios::sync_with_stdio(false);
size_t samplecnt = 0;
static const char outputfmt[] = "%05zd: %7f\n";
static const size_t outputfmtSize = 16;
char outputbuf[16][outputfmtSize] = {0};
size_t bytesRead;
// Setup read transfer
dma->read(*block[0], block[0]->getSize());
while (true) {
//logger->debug("Read from stream and write to address {:p}", *block[next]);
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());
bytesRead = dma->readComplete();
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::cout << samplecnt++ << ": " << fval << '\n';
if (std::snprintf(outputbuf[i], outputfmtSize+1, outputfmt, (samplecnt++%100000), fval) > (int)outputfmtSize) {
throw RuntimeError("Output buffer too small");
}
formatter->format(fval);
}
for (size_t i = 0; i < sizeof(outputbuf)/sizeof(outputbuf[0])-bytesRead/4; i++) {
outputbuf[i][0] = '\0';
}
std::cout << *outputbuf << std::flush;
formatter->output(std::cout);
cur = next;
next = (next + 1) % (sizeof(mem) / sizeof(mem[0]));
}
@ -104,6 +96,8 @@ int main(int argc, char* argv[])
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)");
app.parse(argc, argv);
@ -117,8 +111,6 @@ int main(int argc, char* argv[])
return 1;
}
auto card = fpga::setupFpgaCard(configFile, fpgaName);
std::vector<std::shared_ptr<fpga::ip::AuroraXilinx>> aurora_channels;
@ -149,7 +141,8 @@ int main(int argc, char* argv[])
parsedConnectString.configCrossBar(dma, aurora_channels);
if (!noDma) {
readFromDmaToStdOut(std::move(dma));
auto formatter = fpga::getBufferedSampleFormatter(outputFormat, 16);
readFromDmaToStdOut(std::move(dma), std::move(formatter));
}
} catch (const RuntimeError &e) {
logger->error("Error: {}", e.what());