mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
ips/rtds: add C++ version of RTDS IP
This commit is contained in:
parent
a93278b74e
commit
28143e7188
5 changed files with 133 additions and 90 deletions
|
@ -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;
|
||||
|
|
78
fpga/include/villas/fpga/ips/rtds.hpp
Normal file
78
fpga/include/villas/fpga/ips/rtds.hpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
/** 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)
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
/** @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";
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/** 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 {
|
||||
|
||||
double rtds_axis_dt(struct fpga_ip *c);
|
||||
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;
|
||||
}
|
||||
|
||||
RtdsFactory::RtdsFactory() :
|
||||
IpNodeFactory(getName())
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace ip
|
||||
} // namespace fpga
|
||||
} // namespace villas
|
|
@ -1,80 +0,0 @@
|
|||
/** Driver for AXI Stream wrapper around RTDS_InterfaceModule (rtds_axis )
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @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 <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
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_PLUGIN(&p)
|
Loading…
Add table
Reference in a new issue