diff --git a/fpga/include/villas/fpga/ip.hpp b/fpga/include/villas/fpga/ip.hpp index 0e60a8dea..36ded39ed 100644 --- a/fpga/include/villas/fpga/ip.hpp +++ b/fpga/include/villas/fpga/ip.hpp @@ -196,6 +196,10 @@ protected: getMasterAddrSpaceByInterface(const std::string& masterInterfaceName) const { return busMasterInterfaces.at(masterInterfaceName); } + template + T readMemory(const std::string& block, uintptr_t address) const + { return *(reinterpret_cast(getLocalAddr(block, address))); } + protected: struct IrqPort { int num; diff --git a/fpga/include/villas/fpga/ips/rtds.hpp b/fpga/include/villas/fpga/ips/rtds.hpp new file mode 100644 index 000000000..aff27601c --- /dev/null +++ b/fpga/include/villas/fpga/ips/rtds.hpp @@ -0,0 +1,78 @@ +/** Driver for AXI Stream wrapper around RTDS_InterfaceModule (rtds_axis ) + * + * @file + * @author Steffen Vogel + * @copyright 2017, 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 . + *********************************************************************************/ + +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once + +#include + +namespace villas { +namespace fpga { +namespace ip { + +class Rtds : public IpNode { +public: + static constexpr const char* masterPort = "m_axis"; + static constexpr const char* slavePort = "s_axis"; + + void dump(); + double getDt(); + + std::list getMemoryBlocks() const + { return { registerMemory }; } + +private: + static constexpr const char registerMemory[] = "reg0"; + static constexpr const char* irqTs = "irq_ts"; + static constexpr const char* irqOverflow = "irq_overflow"; + static constexpr const char* irqCase = "irq_case"; +}; + + +class RtdsFactory : public IpNodeFactory { +public: + RtdsFactory(); + + IpCore* create() + { return new Rtds; } + + std::string + getName() const + { return "Rtds"; } + + std::string + getDescription() const + { return "RTDS's AXI4-Stream - GTFPGA interface"; } + + Vlnv getCompatibleVlnv() const + { return {"acs.eonerc.rwth-aachen.de:user:rtds_axis:"}; } +}; + +} // namespace ip +} // namespace fpga +} // namespace villas + +/** @} */ diff --git a/fpga/lib/CMakeLists.txt b/fpga/lib/CMakeLists.txt index 3dcbbc8ea..eea93a1c9 100644 --- a/fpga/lib/CMakeLists.txt +++ b/fpga/lib/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES ips/pcie.cpp ips/dma.cpp ips/bram.cpp + ips/rtds.cpp kernel/kernel.c kernel/pci.c diff --git a/fpga/include/villas/fpga/ips/rtds_axis.h b/fpga/lib/ips/rtds.cpp similarity index 56% rename from fpga/include/villas/fpga/ips/rtds_axis.h rename to fpga/lib/ips/rtds.cpp index 52f1f49d4..66ced6823 100644 --- a/fpga/include/villas/fpga/ips/rtds_axis.h +++ b/fpga/lib/ips/rtds.cpp @@ -1,6 +1,5 @@ /** Driver for AXI Stream wrapper around RTDS_InterfaceModule (rtds_axis ) * - * @file * @author Steffen Vogel * @copyright 2017, Steffen Vogel * @license GNU General Public License (version 3) @@ -21,14 +20,13 @@ * along with this program. If not, see . *********************************************************************************/ -/** @addtogroup fpga VILLASfpga - * @{ - */ +#include -#pragma once +#include + +#include +#include -/* Forward declarations */ -struct ip; #define RTDS_HZ 100000000 // 100 MHz @@ -55,8 +53,50 @@ struct ip; /* Control register bits */ #define RTDS_AXIS_CR_DISABLE_LINK 0 /**< Disable SFP TX when set */ -void rtds_axis_dump(struct fpga_ip *c); +namespace villas { +namespace fpga { +namespace ip { -double rtds_axis_dt(struct fpga_ip *c); +static RtdsFactory rtdsFactoryInstance; -/** @} */ + +void Rtds::dump() +{ + /* Check RTDS_Axis registers */ + const uint32_t sr = readMemory(registerMemory, RTDS_AXIS_SR_OFFSET); + + logger->info("RTDS AXI Stream interface details:"); + logger->info("RTDS status: {:#x}", sr); + logger->info(" Card detected: {}", sr & RTDS_AXIS_SR_CARDDETECTED ? CLR_GRN("yes") : CLR_RED("no")); + logger->info(" Link up: {}", sr & RTDS_AXIS_SR_LINKUP ? CLR_GRN("yes") : CLR_RED("no")); + logger->info(" TX queue full: {}", sr & RTDS_AXIS_SR_TX_FULL ? CLR_RED("yes") : CLR_GRN("no")); + logger->info(" TX in progress: {}", sr & RTDS_AXIS_SR_TX_INPROGRESS ? CLR_YEL("yes") : "no"); + logger->info(" Case running: {}", sr & RTDS_AXIS_SR_CASE_RUNNING ? CLR_GRN("yes") : CLR_RED("no")); + + logger->info("RTDS control: {:#x}", readMemory(registerMemory, RTDS_AXIS_CR_OFFSET)); + logger->info("RTDS IRQ coalesc: {}", readMemory(registerMemory, RTDS_AXIS_COALESC_OFFSET)); + logger->info("RTDS IRQ version: {:#x}", readMemory(registerMemory, RTDS_AXIS_VERSION_OFFSET)); + logger->info("RTDS IRQ multi-rate: {}", readMemory(registerMemory, RTDS_AXIS_MRATE)); + + const uint64_t timestepLow = readMemory(registerMemory, RTDS_AXIS_TSCNT_LOW_OFFSET); + const uint64_t timestepHigh = readMemory(registerMemory, RTDS_AXIS_TSCNT_HIGH_OFFSET); + const uint64_t timestep = (timestepHigh << 32) | timestepLow; + + logger->info("RTDS timestep counter: {}", timestep); + logger->info("RTDS timestep period: {:.3f} us", getDt() * 1e6); +} + +double Rtds::getDt() +{ + const auto dt = readMemory(registerMemory, RTDS_AXIS_TS_PERIOD_OFFSET); + return (dt == 0xFFFF) ? 0.0 : (double) dt / RTDS_HZ; +} + +RtdsFactory::RtdsFactory() : + IpNodeFactory(getName()) +{ +} + +} // namespace ip +} // namespace fpga +} // namespace villas diff --git a/fpga/lib/ips/rtds_axis.c b/fpga/lib/ips/rtds_axis.c deleted file mode 100644 index 5b9137759..000000000 --- a/fpga/lib/ips/rtds_axis.c +++ /dev/null @@ -1,80 +0,0 @@ -/** Driver for AXI Stream wrapper around RTDS_InterfaceModule (rtds_axis ) - * - * @author Steffen Vogel - * @copyright 2017, 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 "log.h" -#include "utils.h" -#include "plugin.h" - -#include "fpga/ip.h" -#include "fpga/card.h" -#include "fpga/ips/rtds_axis.h" - -void rtds_axis_dump(struct fpga_ip *c) -{ - /* Check RTDS_Axis registers */ - uint32_t *regs = (uint32_t *) (c->card->map + c->baseaddr); - - uint32_t sr = regs[RTDS_AXIS_SR_OFFSET/4]; - info("RTDS AXI Stream interface details"); - { INDENT - info("RTDS status: %#08x", sr); - { INDENT - info("Card detected: %s", sr & RTDS_AXIS_SR_CARDDETECTED ? CLR_GRN("yes") : CLR_RED("no")); - info("Link up: %s", sr & RTDS_AXIS_SR_LINKUP ? CLR_GRN("yes") : CLR_RED("no")); - info("TX queue full: %s", sr & RTDS_AXIS_SR_TX_FULL ? CLR_RED("yes") : CLR_GRN("no")); - info("TX in progress: %s", sr & RTDS_AXIS_SR_TX_INPROGRESS ? CLR_YEL("yes") : "no"); - info("Case running: %s", sr & RTDS_AXIS_SR_CASE_RUNNING ? CLR_GRN("yes") : CLR_RED("no")); - } - - info("RTDS control: %#08x", regs[RTDS_AXIS_CR_OFFSET/4]); - info("RTDS IRQ coalesc: %u", regs[RTDS_AXIS_COALESC_OFFSET/4]); - info("RTDS IRQ version: %#06x", regs[RTDS_AXIS_VERSION_OFFSET/4]); - info("RTDS IRQ multi-rate: %u", regs[RTDS_AXIS_MRATE/4]); - - info("RTDS timestep counter: %lu", (uint64_t) regs[RTDS_AXIS_TSCNT_LOW_OFFSET/4] | (uint64_t) regs[RTDS_AXIS_TSCNT_HIGH_OFFSET/4] << 32); - info("RTDS timestep period: %.3f uS", rtds_axis_dt(c) * 1e6); - } -} - -double rtds_axis_dt(struct fpga_ip *c) -{ - uint32_t *regs = (uint32_t *) (c->card->map + c->baseaddr); - uint16_t dt = regs[RTDS_AXIS_TS_PERIOD_OFFSET/4]; - - return (dt == 0xFFFF) ? -1.0 : (double) dt / RTDS_HZ; -} - -static struct plugin p = { - .name = "RTDS's AXI4-Stream - GTFPGA interface", - .description = "", - .type = PLUGIN_TYPE_FPGA_IP, - .ip = { - .vlnv = { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL }, - .type = FPGA_IP_TYPE_INTERFACE, - .dump = rtds_axis_dump, - .size = 0 - } -}; - -REGISTER_PLUGIN(&p)