Commit 57a2c50d authored by Daniel Krebs's avatar Daniel Krebs
Browse files

src: add streamer application for RTDS

parent e8956be8
set(SOURCES
bench-datamovers.c
bench-jitter.c
bench-latency.c
bench-memcpy.c
bench.c
fpga.c
)
add_executable(fpga ${SOURCES})
target_include_directories(fpga PUBLIC
../include/villas
../include
)
add_executable(streamer streamer.cpp)
target_link_libraries(fpga PUBLIC
target_link_libraries(streamer PUBLIC
villas-fpga
)
find_package(LAPACK)
if(LAPACK_FOUND)
target_sources(fpga PUBLIC bench-overruns.c)
target_link_libraries(fpga PUBLIC ${LAPACK_LIBRARIES})
target_include_directories(fpga PUBLIC ${LAPACK_INCLUDE_DIRS})
target_compile_definitions(fpga PUBLIC WITH_LAPACK)
endif()
include(GNUInstallDirs)
install(TARGETS fpga
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/static
)
......@@ -15,11 +15,185 @@
#include <villas/fpga/ip.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/fifo.hpp>
int main(int argc, const char* argv[])
using namespace villas;
static struct pci pci;
static auto logger = loggerGetOrCreate("streamer");
void setupColorHandling()
{
(void) argc;
cxxopts::Options options(argv[0], " - example command line options");
// Nice Control-C
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = [](int){
std::cout << std::endl << rang::style::reset << rang::fgB::red;
std::cout << "Control-C detected, exiting..." << rang::style::reset << std::endl;
std::exit(1); // will call the correct exit func, no unwinding of the stack though
};
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, nullptr);
// reset color if exiting not by signal
std::atexit([](){std::cout << rang::style::reset;});
}
fpga::PCIeCard&
setupFpgaCard(const std::string& configFile, const std::string& fpgaName)
{
if(pci_init(&pci) != 0) {
logger->error("Cannot initialize PCI");
exit(1);
}
auto vfioContainer = villas::VfioContainer::create();
/* Parse FPGA configuration */
FILE* f = fopen(configFile.c_str(), "r");
if(f == nullptr) {
logger->error("Cannot open config file: {}", configFile);
}
json_t* json = json_loadf(f, 0, nullptr);
if(json == nullptr) {
logger->error("Cannot parse JSON config");
fclose(f);
exit(1);
}
fclose(f);
json_t* fpgas = json_object_get(json, "fpgas");
if(fpgas == nullptr) {
logger->error("No section 'fpgas' found in config");
exit(1);
}
// get the FPGA card plugin
villas::Plugin* plugin = villas::Plugin::lookup(villas::Plugin::Type::FpgaCard, "");
if(plugin == nullptr) {
logger->error("No FPGA plugin found");
exit(1);
}
villas::fpga::PCIeCardFactory* fpgaCardPlugin =
dynamic_cast<villas::fpga::PCIeCardFactory*>(plugin);
// create all FPGA card instances using the corresponding plugin
auto cards = fpgaCardPlugin->make(fpgas, &pci, vfioContainer);
villas::fpga::PCIeCard* card = nullptr;
for(auto& fpgaCard : cards) {
if(fpgaCard->name == fpgaName) {
card = fpgaCard.get();
break;
}
}
if(card == nullptr) {
logger->error("FPGA card {} not found in config or not working", fpgaName);
exit(1);
}
// deallocate JSON config
// json_decref(json);
return *card;
}
int main(int argc, char* argv[])
{
/* Command Line Parser */
CLI::App app{"VILLASfpga data streamer"};
std::string configFile = "../etc/fpga.json";
app.add_option("-c,--config", configFile, "Configuration file")
->check(CLI::ExistingFile);
std::string fpgaName = "vc707";
app.add_option("--fpga", fpgaName, "Which FPGA to use");
try {
app.parse(argc, argv);
} catch (const CLI::ParseError &e) {
return app.exit(e);
}
/* Logging setup */
spdlog::set_level(spdlog::level::debug);
setupColorHandling();
fpga::PCIeCard& card = setupFpgaCard(configFile, fpgaName);
auto rtds = reinterpret_cast<fpga::ip::Rtds*>
(card.lookupIp(fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")));
auto dma = reinterpret_cast<fpga::ip::Dma*>
(card.lookupIp(fpga::Vlnv("xilinx.com:ip:axi_dma:")));
auto fifo = reinterpret_cast<fpga::ip::Fifo*>
(card.lookupIp(fpga::Vlnv("xilinx.com:ip:axi_fifo_mm_s:")));
if(rtds == nullptr) {
logger->error("No RTDS interface found on FPGA");
return 1;
}
if(dma == nullptr) {
logger->error("No DMA found on FPGA ");
return 1;
}
if(fifo == nullptr) {
logger->error("No Fifo found on FPGA ");
return 1;
}
rtds->dump();
rtds->connect(rtds->getMasterPort(rtds->masterPort),
dma->getSlavePort(dma->s2mmPort));
dma->connect(dma->getMasterPort(dma->mm2sPort),
rtds->getSlavePort(rtds->slavePort));
auto mem = villas::HostRam::allocate<int32_t>(0x100 / sizeof(int32_t));
while(true) {
dma->read(mem, mem.getSize());
const size_t bytesRead = dma->readComplete();
const size_t valuesRead = bytesRead / sizeof(int32_t);
for(size_t i = 0; i < valuesRead; i++) {
std::cerr << mem[i] << ";";
}
std::cerr << std::endl;
std::string line;
std::getline(std::cin, line);
auto values = villas::utils::tokenize(line, ";");
size_t memIdx = 0;
for(auto& value: values) {
if(value.empty()) continue;
const int32_t number = std::stoi(value);
mem[memIdx++] = number;
}
dma->write(mem, memIdx * sizeof(int32_t));
}
return 0;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment