Commit a6e6ed39 authored by Daniel Krebs's avatar Daniel Krebs
Browse files

ips/rtds: add C++ version of RTDS IP

parent 10eca364
......@@ -196,6 +196,10 @@ protected:
getMasterAddrSpaceByInterface(const std::string& masterInterfaceName) const
{ return busMasterInterfaces.at(masterInterfaceName); }
template<typename T>
T readMemory(const std::string& block, uintptr_t address) const
{ return *(reinterpret_cast<T*>(getLocalAddr(block, address))); }
protected:
struct IrqPort {
int num;
......
/** Driver for AXI Stream wrapper around RTDS_InterfaceModule (rtds_axis )
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
* @license GNU General Public License (version 3)
......@@ -20,61 +21,58 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <stdint.h>
#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
}
/** @addtogroup fpga VILLASfpga
* @{
*/
#pragma once
#include <villas/fpga/ip_node.hpp>
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<std::string> 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";
};
REGISTER_PLUGIN(&p)
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
/** @} */
......@@ -13,6 +13,7 @@ set(SOURCES
ips/pcie.cpp
ips/dma.cpp
ips/bram.cpp
ips/rtds.cpp
kernel/kernel.c
kernel/pci.c
......
/** Driver for AXI Stream wrapper around RTDS_InterfaceModule (rtds_axis )
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
* @license GNU General Public License (version 3)
......@@ -21,14 +20,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#include <cstdint>
#pragma once
#include <villas/utils.h>
#include <villas/fpga/card.hpp>
#include <villas/fpga/ips/rtds.hpp>
/* 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 {
static RtdsFactory rtdsFactoryInstance;
void Rtds::dump()
{
/* Check RTDS_Axis registers */
const uint32_t sr = readMemory<uint32_t>(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<uint32_t>(registerMemory, RTDS_AXIS_CR_OFFSET));
logger->info("RTDS IRQ coalesc: {}", readMemory<uint32_t>(registerMemory, RTDS_AXIS_COALESC_OFFSET));
logger->info("RTDS IRQ version: {:#x}", readMemory<uint32_t>(registerMemory, RTDS_AXIS_VERSION_OFFSET));
logger->info("RTDS IRQ multi-rate: {}", readMemory<uint32_t>(registerMemory, RTDS_AXIS_MRATE));
const uint64_t timestepLow = readMemory<uint32_t>(registerMemory, RTDS_AXIS_TSCNT_LOW_OFFSET);
const uint64_t timestepHigh = readMemory<uint32_t>(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<uint16_t>(registerMemory, RTDS_AXIS_TS_PERIOD_OFFSET);
return (dt == 0xFFFF) ? 0.0 : (double) dt / RTDS_HZ;
}
double rtds_axis_dt(struct fpga_ip *c);
RtdsFactory::RtdsFactory() :
IpNodeFactory(getName())
{
}
/** @} */
} // namespace ip
} // namespace fpga
} // namespace villas
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