mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
Merge pull request #62 from VILLASframework/new-plugin
New plugin registration mechanism
This commit is contained in:
commit
8abd9901b1
40 changed files with 321 additions and 488 deletions
|
@ -136,7 +136,7 @@ public:
|
|||
std::list<std::shared_ptr<PCIeCard>> make(json_t *json, std::shared_ptr<kernel::pci::DeviceList> pci, std::shared_ptr<kernel::vfio::Container> vc);
|
||||
|
||||
static
|
||||
PCIeCard* create()
|
||||
PCIeCard* make()
|
||||
{
|
||||
return new PCIeCard();
|
||||
}
|
||||
|
|
|
@ -112,7 +112,8 @@ public:
|
|||
card(nullptr)
|
||||
{ }
|
||||
|
||||
virtual ~Core() = default;
|
||||
virtual
|
||||
~Core() = default;
|
||||
|
||||
public:
|
||||
// Generic management interface for IPs
|
||||
|
@ -305,18 +306,6 @@ protected:
|
|||
void parse(Core &, json_t *)
|
||||
{ }
|
||||
|
||||
private:
|
||||
// Create a concrete IP instance
|
||||
virtual Core* create() = 0;
|
||||
|
||||
virtual
|
||||
void configurePollingMode(Core &, PollingMode)
|
||||
{ }
|
||||
|
||||
virtual
|
||||
Vlnv getCompatibleVlnv() const = 0;
|
||||
|
||||
protected:
|
||||
static
|
||||
Logger getStaticLogger()
|
||||
{
|
||||
|
@ -324,10 +313,51 @@ protected:
|
|||
}
|
||||
|
||||
private:
|
||||
virtual
|
||||
void configurePollingMode(Core &, PollingMode)
|
||||
{ }
|
||||
|
||||
virtual
|
||||
Vlnv getCompatibleVlnv() const = 0;
|
||||
|
||||
// Create a concrete IP instance
|
||||
virtual
|
||||
Core* make() const = 0;
|
||||
|
||||
static
|
||||
CoreFactory* lookup(const Vlnv &vlnv);
|
||||
};
|
||||
|
||||
template<typename T, const char *name, const char *desc, const char *vlnv>
|
||||
class CorePlugin : public CoreFactory {
|
||||
|
||||
public:
|
||||
virtual
|
||||
std::string getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
virtual
|
||||
std::string getDescription() const
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual
|
||||
Vlnv getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv(vlnv);
|
||||
}
|
||||
|
||||
// Create a concrete IP instance
|
||||
Core* make() const
|
||||
{
|
||||
return new T;
|
||||
};
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -66,33 +66,6 @@ private:
|
|||
static constexpr const char registerMemory[] = "reg0";
|
||||
};
|
||||
|
||||
class AuroraFactory : public NodeFactory {
|
||||
public:
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new Aurora;
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getName() const
|
||||
{
|
||||
return "Aurora";
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getDescription() const
|
||||
{
|
||||
return "Aurora 8B/10B and additional support modules, like an AXI4-Lite register interface.";
|
||||
}
|
||||
|
||||
virtual Vlnv
|
||||
getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv("acs.eonerc.rwth-aachen.de:user:aurora_axis:");
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -46,33 +46,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class AuroraXilinxFactory : public NodeFactory {
|
||||
public:
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new AuroraXilinx;
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getName() const
|
||||
{
|
||||
return "Aurora";
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getDescription() const
|
||||
{
|
||||
return "Xilinx Aurora 8B/10B.";
|
||||
}
|
||||
|
||||
virtual Vlnv
|
||||
getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv("xilinx.com:ip:aurora_8b10b:");
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -29,8 +29,11 @@ namespace villas {
|
|||
namespace fpga {
|
||||
namespace ip {
|
||||
|
||||
class BramFactory;
|
||||
|
||||
class Bram : public Core {
|
||||
friend class BramFactory;
|
||||
|
||||
public:
|
||||
|
||||
virtual
|
||||
|
@ -57,19 +60,12 @@ private:
|
|||
};
|
||||
|
||||
class BramFactory : public CoreFactory {
|
||||
|
||||
public:
|
||||
|
||||
void parse(Core &ip, json_t *cfg);
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new Bram;
|
||||
}
|
||||
|
||||
virtual
|
||||
std::string getName() const
|
||||
{
|
||||
return "Bram";
|
||||
return "bram";
|
||||
}
|
||||
|
||||
virtual
|
||||
|
@ -78,11 +74,22 @@ public:
|
|||
return "Block RAM";
|
||||
}
|
||||
|
||||
private:
|
||||
virtual
|
||||
Vlnv getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv("xilinx.com:ip:axi_bram_ctrl:");
|
||||
}
|
||||
|
||||
// Create a concrete IP instance
|
||||
Core* make() const
|
||||
{
|
||||
return new Bram;
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual
|
||||
void parse(Core &, json_t *) override;
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
|
|
50
fpga/include/villas/fpga/ips/dino.hpp
Normal file
50
fpga/include/villas/fpga/ips/dino.hpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
/** Driver for wrapper around Dino
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <svogel2@eonerc.rwth-aachen.de>
|
||||
* @copyright 2020-2022, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @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/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <villas/fpga/node.hpp>
|
||||
|
||||
namespace villas {
|
||||
namespace fpga {
|
||||
namespace ip {
|
||||
|
||||
class Dino : public Node {
|
||||
public:
|
||||
static constexpr const char* masterPort = "m_axis";
|
||||
static constexpr const char* slavePort = "s_axis";
|
||||
|
||||
const StreamVertex& getDefaultSlavePort() const
|
||||
{
|
||||
return getSlavePort(slavePort);
|
||||
}
|
||||
|
||||
const StreamVertex& getDefaultMasterPort() const
|
||||
{
|
||||
return getMasterPort(masterPort);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
|
@ -39,7 +39,9 @@ class Dma : public Node
|
|||
public:
|
||||
friend class DmaFactory;
|
||||
|
||||
virtual
|
||||
~Dma();
|
||||
|
||||
virtual
|
||||
bool init() override;
|
||||
|
||||
|
@ -151,18 +153,13 @@ private:
|
|||
MemoryBlock::UniquePtr sgRingRx;
|
||||
};
|
||||
|
||||
class DmaFactory : public NodeFactory {
|
||||
class DmaFactory : NodeFactory {
|
||||
|
||||
public:
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new Dma;
|
||||
}
|
||||
|
||||
virtual
|
||||
std::string getName() const
|
||||
{
|
||||
return "Dma";
|
||||
return "dma";
|
||||
}
|
||||
|
||||
virtual
|
||||
|
@ -171,17 +168,25 @@ public:
|
|||
return "Xilinx's AXI4 Direct Memory Access Controller";
|
||||
}
|
||||
|
||||
private:
|
||||
virtual
|
||||
Vlnv getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv("xilinx.com:ip:axi_dma:");
|
||||
}
|
||||
|
||||
// Create a concrete IP instance
|
||||
Core* make() const
|
||||
{
|
||||
return new Dma;
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual
|
||||
void parse(Core& ip, json_t* json) override;
|
||||
|
||||
virtual void
|
||||
configurePollingMode(Core& ip, PollingMode mode) override
|
||||
virtual
|
||||
void configurePollingMode(Core& ip, PollingMode mode) override
|
||||
{
|
||||
dynamic_cast<Dma&>(ip).polling = (mode == POLL);
|
||||
}
|
||||
|
|
|
@ -56,33 +56,6 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
class EMCFactory : public CoreFactory {
|
||||
public:
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new EMC;
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getName() const
|
||||
{
|
||||
return "ExternalMemoryController";
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getDescription() const
|
||||
{
|
||||
return "Xilinx's AXI External Memory Controller (EMC) ";
|
||||
}
|
||||
|
||||
virtual Vlnv
|
||||
getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv("xilinx.com:ip:axi_emc:");
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -63,65 +63,10 @@ private:
|
|||
XLlFifo xFifo;
|
||||
};
|
||||
|
||||
class FifoFactory : public NodeFactory {
|
||||
public:
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new Fifo;
|
||||
}
|
||||
|
||||
std::string
|
||||
getName() const
|
||||
{
|
||||
return "Fifo";
|
||||
}
|
||||
|
||||
std::string
|
||||
getDescription() const
|
||||
{
|
||||
return "Xilinx's AXI4 FIFO data mover";
|
||||
}
|
||||
|
||||
Vlnv getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv("xilinx.com:ip:axi_fifo_mm_s:");
|
||||
}
|
||||
};
|
||||
|
||||
class FifoData : public Node {
|
||||
friend class FifoDataFactory;
|
||||
};
|
||||
|
||||
class FifoDataFactory : public NodeFactory {
|
||||
public:
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new FifoData;
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getName() const
|
||||
{
|
||||
return "FifoData";
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getDescription() const
|
||||
{
|
||||
return "Xilinx's AXI4 data stream FIFO";
|
||||
}
|
||||
|
||||
virtual Vlnv
|
||||
getCompatibleVlnv() const
|
||||
{
|
||||
return {
|
||||
"xilinx.com:ip:axis_data_fifo:"
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace villas {
|
|||
namespace fpga {
|
||||
namespace ip {
|
||||
|
||||
class GeneralPurposeIO : public Core {
|
||||
class Gpio : public Core {
|
||||
public:
|
||||
|
||||
virtual
|
||||
|
@ -48,33 +48,6 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
class GeneralPurposeIOFactory : public CoreFactory {
|
||||
public:
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new GeneralPurposeIO;
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getName() const
|
||||
{
|
||||
return "GeneralPurposeIO";
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getDescription() const
|
||||
{
|
||||
return "Xilinx's AXI4 general purpose IO";
|
||||
}
|
||||
|
||||
virtual Vlnv
|
||||
getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv("xilinx.com:ip:axi_gpio:");
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -66,33 +66,6 @@ public:
|
|||
bool started;
|
||||
};
|
||||
|
||||
class Gpu2RtdsFactory : public NodeFactory {
|
||||
public:
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new Gpu2Rtds;
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getName() const
|
||||
{
|
||||
return "Gpu2Rtds";
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getDescription() const
|
||||
{
|
||||
return "HLS Gpu2Rtds IP";
|
||||
}
|
||||
|
||||
virtual Vlnv
|
||||
getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:");
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -150,33 +150,6 @@ protected:
|
|||
bool running;
|
||||
};
|
||||
|
||||
class HlsFactory : public CoreFactory {
|
||||
public:
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new Hls;
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getName() const
|
||||
{
|
||||
return "HighLevelSynthesis";
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getDescription() const
|
||||
{
|
||||
return "Xilinx's HLS IP Cores";
|
||||
}
|
||||
|
||||
virtual Vlnv
|
||||
getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv("acs.eonerc.rwth-aachen.de:hls:");
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -84,39 +84,6 @@ private:
|
|||
bool polling[maxIrqs];
|
||||
};
|
||||
|
||||
class InterruptControllerFactory : public CoreFactory {
|
||||
public:
|
||||
|
||||
static constexpr const char*
|
||||
getCompatibleVlnvString()
|
||||
{
|
||||
return "xilinx.com:module_ref:axi_pcie_intc:";
|
||||
}
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new InterruptController;
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getName() const
|
||||
{
|
||||
return "InterruptController";
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getDescription() const
|
||||
{
|
||||
return "Xilinx's programmable interrupt controller";
|
||||
}
|
||||
|
||||
virtual Vlnv
|
||||
getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv(getCompatibleVlnvString());
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -59,26 +59,13 @@ private:
|
|||
std::map<std::string, PciBar> pcieToAxiTranslations;
|
||||
};
|
||||
|
||||
class AxiPciExpressBridgeFactory : public CoreFactory {
|
||||
class AxiPciExpressBridgeFactory : CoreFactory {
|
||||
|
||||
public:
|
||||
|
||||
static constexpr
|
||||
const char* getCompatibleVlnvString()
|
||||
{
|
||||
return "xilinx.com:ip:axi_pcie:";
|
||||
}
|
||||
|
||||
void parse(Core &ip, json_t *cfg);
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new AxiPciExpressBridge;
|
||||
}
|
||||
|
||||
virtual
|
||||
std::string getName() const
|
||||
{
|
||||
return "AxiPciExpressBridge";
|
||||
return "pcie";
|
||||
}
|
||||
|
||||
virtual
|
||||
|
@ -87,11 +74,22 @@ public:
|
|||
return "Xilinx's AXI-PCIe Bridge";
|
||||
}
|
||||
|
||||
private:
|
||||
virtual
|
||||
Vlnv getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv(getCompatibleVlnvString());
|
||||
return Vlnv("xilinx.com:ip:axi_pcie:");
|
||||
}
|
||||
|
||||
// Create a concrete IP instance
|
||||
Core* make() const
|
||||
{
|
||||
return new AxiPciExpressBridge;
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual
|
||||
void parse(Core &, json_t *) override;
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace villas {
|
|||
namespace fpga {
|
||||
namespace ip {
|
||||
|
||||
class Rtds : public Node {
|
||||
class RtdsGtfpga : public Node {
|
||||
public:
|
||||
static constexpr const char* masterPort = "m_axis";
|
||||
static constexpr const char* slavePort = "s_axis";
|
||||
|
@ -65,32 +65,6 @@ private:
|
|||
static constexpr const char* irqCase = "irq_case";
|
||||
};
|
||||
|
||||
class RtdsFactory : public NodeFactory {
|
||||
public:
|
||||
Core* create()
|
||||
{
|
||||
return new Rtds;
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getName() const
|
||||
{
|
||||
return "rtds";
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getDescription() const
|
||||
{
|
||||
return "RTDS's AXI4-Stream - GTFPGA interface";
|
||||
}
|
||||
|
||||
virtual Vlnv
|
||||
getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:");
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -84,33 +84,6 @@ private:
|
|||
bool started;
|
||||
};
|
||||
|
||||
class Rtds2GpuFactory : public NodeFactory {
|
||||
public:
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new Rtds2Gpu;
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getName() const
|
||||
{
|
||||
return "Rtds2Gpu";
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
getDescription() const
|
||||
{
|
||||
return "HLS RTDS2GPU IP";
|
||||
}
|
||||
|
||||
virtual Vlnv
|
||||
getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:");
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -69,26 +69,13 @@ private:
|
|||
std::map<std::string, std::string> portMapping;
|
||||
};
|
||||
|
||||
class AxiStreamSwitchFactory : public NodeFactory {
|
||||
class AxiStreamSwitchFactory : NodeFactory {
|
||||
|
||||
public:
|
||||
|
||||
static constexpr
|
||||
const char* getCompatibleVlnvString()
|
||||
{
|
||||
return "xilinx.com:ip:axis_switch:";
|
||||
}
|
||||
|
||||
void parse(Core &ip, json_t *cfg);
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new AxiStreamSwitch;
|
||||
}
|
||||
|
||||
virtual
|
||||
std::string getName() const
|
||||
{
|
||||
return "AxiStreamSwitch";
|
||||
return "switch";
|
||||
}
|
||||
|
||||
virtual
|
||||
|
@ -97,11 +84,22 @@ public:
|
|||
return "Xilinx's AXI4-Stream switch";
|
||||
}
|
||||
|
||||
private:
|
||||
virtual
|
||||
Vlnv getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv(getCompatibleVlnvString());
|
||||
return Vlnv("xilinx.com:ip:axis_switch:");
|
||||
}
|
||||
|
||||
// Create a concrete IP instance
|
||||
Core* make() const
|
||||
{
|
||||
return new AxiStreamSwitch;
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual
|
||||
void parse(Core &, json_t *) override;
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
|
|
|
@ -79,33 +79,6 @@ private:
|
|||
XTmrCtr xTmr;
|
||||
};
|
||||
|
||||
class TimerFactory : public CoreFactory {
|
||||
public:
|
||||
|
||||
Core* create()
|
||||
{
|
||||
return new Timer;
|
||||
}
|
||||
|
||||
virtual
|
||||
std::string getName() const
|
||||
{
|
||||
return "Timer";
|
||||
}
|
||||
|
||||
virtual
|
||||
std::string getDescription() const
|
||||
{
|
||||
return "Xilinx's programmable timer / counter";
|
||||
}
|
||||
|
||||
virtual
|
||||
Vlnv getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv("xilinx.com:ip:axi_timer:");
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -142,8 +142,8 @@ public:
|
|||
bool connectLoopback();
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
connectInternal(const std::string &slavePort,
|
||||
virtual
|
||||
bool connectInternal(const std::string &slavePort,
|
||||
const std::string &masterPort);
|
||||
|
||||
private:
|
||||
|
@ -162,7 +162,39 @@ public:
|
|||
using CoreFactory::CoreFactory;
|
||||
|
||||
virtual
|
||||
void parse(Core &ip, json_t *cfg);
|
||||
void parse(Core &, json_t *);
|
||||
};
|
||||
|
||||
|
||||
template<typename T, const char *name, const char *desc, const char *vlnv>
|
||||
class NodePlugin : public NodeFactory {
|
||||
|
||||
public:
|
||||
virtual
|
||||
std::string getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
virtual
|
||||
std::string getDescription() const
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
|
||||
private:
|
||||
// Get a VLNV identifier for which this IP / Node type can be used.
|
||||
virtual
|
||||
Vlnv getCompatibleVlnv() const
|
||||
{
|
||||
return Vlnv(vlnv);
|
||||
}
|
||||
|
||||
// Create a concrete IP instance
|
||||
Core* make() const
|
||||
{
|
||||
return new T;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace ip */
|
||||
|
|
|
@ -27,18 +27,19 @@ set(SOURCES
|
|||
node.cpp
|
||||
fpgaHelper.cpp
|
||||
|
||||
ips/timer.cpp
|
||||
ips/switch.cpp
|
||||
ips/aurora_xilinx.cpp
|
||||
ips/aurora.cpp
|
||||
ips/bram.cpp
|
||||
ips/dino.cpp
|
||||
ips/dma.cpp
|
||||
ips/emc.cpp
|
||||
ips/fifo.cpp
|
||||
ips/gpio.cpp
|
||||
ips/intc.cpp
|
||||
ips/pcie.cpp
|
||||
ips/dma.cpp
|
||||
ips/bram.cpp
|
||||
ips/rtds.cpp
|
||||
ips/aurora.cpp
|
||||
ips/aurora_xilinx.cpp
|
||||
ips/gpio.cpp
|
||||
ips/switch.cpp
|
||||
ips/timer.cpp
|
||||
|
||||
ips/rtds2gpu/rtds2gpu.cpp
|
||||
ips/rtds2gpu/xrtds2gpu.c
|
||||
|
|
|
@ -73,7 +73,7 @@ std::list<std::shared_ptr<PCIeCard>> PCIeCardFactory::make(json_t *json, std::sh
|
|||
if (ret != 0)
|
||||
throw ConfigError(json_card, err, "", "Failed to parse card");
|
||||
|
||||
auto card = std::unique_ptr<PCIeCard>(create());
|
||||
auto card = std::unique_ptr<PCIeCard>(make());
|
||||
|
||||
// Populate generic properties
|
||||
card->name = std::string(card_name);
|
||||
|
|
|
@ -45,13 +45,12 @@ using namespace villas::fpga::ip;
|
|||
// first.
|
||||
static std::list<Vlnv>
|
||||
vlnvInitializationOrder = {
|
||||
Vlnv(AxiPciExpressBridgeFactory::getCompatibleVlnvString()),
|
||||
Vlnv(InterruptControllerFactory::getCompatibleVlnvString()),
|
||||
Vlnv(AxiStreamSwitchFactory::getCompatibleVlnvString()),
|
||||
Vlnv("xilinx.com:ip:axi_pcie:"),
|
||||
Vlnv("xilinx.com:module_ref:axi_pcie_intc:"),
|
||||
Vlnv("xilinx.com:ip:axis_switch:"),
|
||||
};
|
||||
|
||||
std::list<std::shared_ptr<Core>>
|
||||
CoreFactory::make(PCIeCard* card, json_t *json_ips)
|
||||
std::list<std::shared_ptr<Core>> CoreFactory::make(PCIeCard* card, json_t *json_ips)
|
||||
{
|
||||
// We only have this logger until we know the factory to build an IP with
|
||||
auto loggerStatic = getStaticLogger();
|
||||
|
@ -110,16 +109,15 @@ CoreFactory::make(PCIeCard* card, json_t *json_ips)
|
|||
// This is the magic part! Factories automatically register as a
|
||||
// plugin as soon as they are instantiated. If there are multiple
|
||||
// candidates, the first suitable factory will be used.
|
||||
CoreFactory* CoreFactory = lookup(id.getVlnv());
|
||||
|
||||
if (CoreFactory == nullptr) {
|
||||
auto* f = lookup(id.getVlnv());
|
||||
if (f == nullptr) {
|
||||
loggerStatic->warn("No plugin found to handle {}", id.getVlnv());
|
||||
continue;
|
||||
}
|
||||
else
|
||||
loggerStatic->debug("Using {} for IP {}", CoreFactory->getName(), id.getVlnv());
|
||||
loggerStatic->debug("Using {} for IP {}", f->getName(), id.getVlnv());
|
||||
|
||||
auto logger = CoreFactory->getLogger();
|
||||
auto logger = f->getLogger();
|
||||
|
||||
// Create new IP instance. Since this function is virtual, it will
|
||||
// construct the right, specialized type without knowing it here
|
||||
|
@ -127,11 +125,10 @@ CoreFactory::make(PCIeCard* card, json_t *json_ips)
|
|||
// If something goes wrong with initialization, the shared_ptr will
|
||||
// take care to desctruct the Core again as it is not pushed to
|
||||
// the list and will run out of scope.
|
||||
auto ip = std::unique_ptr<Core>(CoreFactory->create());
|
||||
auto ip = std::unique_ptr<Core>(f->make());
|
||||
|
||||
if (ip == nullptr) {
|
||||
logger->warn("Cannot create an instance of {}",
|
||||
CoreFactory->getName());
|
||||
logger->warn("Cannot create an instance of {}", f->getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -247,10 +244,10 @@ CoreFactory::make(PCIeCard* card, json_t *json_ips)
|
|||
}
|
||||
|
||||
// IP-specific setup via JSON config
|
||||
CoreFactory->parse(*ip, json_ip);
|
||||
f->parse(*ip, json_ip);
|
||||
|
||||
// Set polling mode
|
||||
CoreFactory->configurePollingMode(*ip, (card->polling ? PollingMode::POLL : PollingMode::IRQ));
|
||||
f->configurePollingMode(*ip, (card->polling ? PollingMode::POLL : PollingMode::IRQ));
|
||||
|
||||
// IP has been configured now
|
||||
configuredIps.push_back(std::move(ip));
|
||||
|
@ -306,8 +303,7 @@ CoreFactory::make(PCIeCard* card, json_t *json_ips)
|
|||
return initializedIps;
|
||||
}
|
||||
|
||||
void
|
||||
Core::dump()
|
||||
void Core::dump()
|
||||
{
|
||||
logger->info("IP: {}", *this);
|
||||
for (auto& [num, irq] : irqs) {
|
||||
|
@ -320,8 +316,7 @@ Core::dump()
|
|||
}
|
||||
}
|
||||
|
||||
CoreFactory*
|
||||
CoreFactory::lookup(const Vlnv &vlnv)
|
||||
CoreFactory* CoreFactory::lookup(const Vlnv &vlnv)
|
||||
{
|
||||
for (auto &ip : plugin::registry->lookup<CoreFactory>()) {
|
||||
if (ip->getCompatibleVlnv() == vlnv)
|
||||
|
@ -331,8 +326,7 @@ CoreFactory::lookup(const Vlnv &vlnv)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
uintptr_t
|
||||
Core::getLocalAddr(const MemoryBlockName &block, uintptr_t address) const
|
||||
uintptr_t Core::getLocalAddr(const MemoryBlockName &block, uintptr_t address) const
|
||||
{
|
||||
// Throws exception if block not present
|
||||
auto &translation = addressTranslations.at(block);
|
||||
|
@ -340,8 +334,7 @@ Core::getLocalAddr(const MemoryBlockName &block, uintptr_t address) const
|
|||
return translation.getLocalAddr(address);
|
||||
}
|
||||
|
||||
InterruptController*
|
||||
Core::getInterruptController(const std::string &interruptName) const
|
||||
InterruptController* Core::getInterruptController(const std::string &interruptName) const
|
||||
{
|
||||
try {
|
||||
const IrqPort irq = irqs.at(interruptName);
|
||||
|
|
|
@ -65,8 +65,6 @@
|
|||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
static AuroraFactory auroraFactoryInstance;
|
||||
|
||||
void Aurora::dump()
|
||||
{
|
||||
// Check Aurora AXI4 registers
|
||||
|
@ -112,3 +110,8 @@ void Aurora::resetFrameCounters()
|
|||
|
||||
writeMemory<uint32_t>(registerMemory, AURORA_AXIS_CR_OFFSET, cr);
|
||||
}
|
||||
|
||||
static char n[] = "aurora";
|
||||
static char d[] = "Aurora 8B/10B and additional support modules, like an AXI4-Lite register interface.";
|
||||
static char v[] = "acs.eonerc.rwth-aachen.de:user:aurora_axis:";
|
||||
static NodePlugin<Aurora, n, d, v> f;
|
||||
|
|
|
@ -28,4 +28,7 @@
|
|||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
static AuroraXilinxFactory auroraFactoryInstance;
|
||||
static char n[] = "aurora_xilinx";
|
||||
static char d[] = "Xilinx Aurora 8B/10B.";
|
||||
static char v[] = "xilinx.com:ip:aurora_8b10b:";
|
||||
static NodePlugin<AuroraXilinx, n, d, v> f;
|
||||
|
|
|
@ -23,10 +23,9 @@
|
|||
#include <villas/exceptions.hpp>
|
||||
#include <villas/fpga/ips/bram.hpp>
|
||||
|
||||
using namespace villas;
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
static BramFactory factory;
|
||||
|
||||
void BramFactory::parse(Core &ip, json_t* cfg)
|
||||
{
|
||||
CoreFactory::parse(ip, cfg);
|
||||
|
@ -49,3 +48,4 @@ bool Bram::init()
|
|||
return true;
|
||||
}
|
||||
|
||||
static BramFactory f;
|
||||
|
|
34
fpga/lib/ips/dino.cpp
Normal file
34
fpga/lib/ips/dino.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
/** Driver for wrapper around standard Xilinx Aurora (xilinx.com:ip:aurora_8b10b)
|
||||
*
|
||||
* @author Steffen Vogel <post@steffenvogel.de>
|
||||
* @copyright 2017-2022, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @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 <cstdint>
|
||||
|
||||
#include <villas/utils.hpp>
|
||||
|
||||
#include <villas/fpga/ips/dino.hpp>
|
||||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
static char n[] = "dino";
|
||||
static char d[] = "Analog and Digital IO";
|
||||
static char v[] = "xilinx.com:module_ref:dino:";
|
||||
static NodePlugin<Dino, n, d, v> f;
|
|
@ -37,9 +37,6 @@
|
|||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
// Instantiate factory to make available to plugin infrastructure
|
||||
static DmaFactory factory;
|
||||
|
||||
bool Dma::init()
|
||||
{
|
||||
// Check if configJson has been called
|
||||
|
@ -672,3 +669,5 @@ void DmaFactory::parse(Core &ip, json_t *cfg)
|
|||
|
||||
dma.configDone = true;
|
||||
}
|
||||
|
||||
static DmaFactory f;
|
||||
|
|
|
@ -27,11 +27,7 @@
|
|||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
// Instantiate factory to make available to plugin infrastructure
|
||||
static EMCFactory factory;
|
||||
|
||||
bool
|
||||
EMC::init()
|
||||
bool EMC::init()
|
||||
{
|
||||
int ret;
|
||||
const uintptr_t base = getBaseAddr(registerMemory);
|
||||
|
@ -57,8 +53,7 @@ EMC::init()
|
|||
return XFlash_IsReady(&xflash);
|
||||
}
|
||||
|
||||
bool
|
||||
EMC::read(uint32_t offset, uint32_t length, uint8_t *data)
|
||||
bool EMC::read(uint32_t offset, uint32_t length, uint8_t *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -79,8 +74,7 @@ EMC::read(uint32_t offset, uint32_t length, uint8_t *data)
|
|||
|
||||
// objcopy -I ihex -O binary somefile.mcs somefile.bin
|
||||
|
||||
bool
|
||||
EMC::flash(uint32_t offset, const std::string &filename)
|
||||
bool EMC::flash(uint32_t offset, const std::string &filename)
|
||||
{
|
||||
bool result;
|
||||
uint32_t length;
|
||||
|
@ -107,8 +101,7 @@ EMC::flash(uint32_t offset, const std::string &filename)
|
|||
}
|
||||
|
||||
// Based on xilflash_readwrite_example.c
|
||||
bool
|
||||
EMC::flash(uint32_t offset, uint32_t length, uint8_t *data)
|
||||
bool EMC::flash(uint32_t offset, uint32_t length, uint8_t *data)
|
||||
{
|
||||
int ret = XST_FAILURE;
|
||||
uint32_t start = offset;
|
||||
|
@ -164,3 +157,8 @@ EMC::flash(uint32_t offset, uint32_t length, uint8_t *data)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
static char n[] = "emc";
|
||||
static char d[] = "Xilinx's AXI External Memory Controller";
|
||||
static char v[] = "xilinx.com:ip:axi_emc:";
|
||||
static CorePlugin<EMC, n, d, v> f;
|
||||
|
|
|
@ -33,10 +33,6 @@
|
|||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
// Instantiate factory to make available to plugin infrastructure
|
||||
static FifoFactory factory;
|
||||
static FifoDataFactory factoryData;
|
||||
|
||||
bool Fifo::init()
|
||||
{
|
||||
XLlFifo_Config fifo_cfg;
|
||||
|
@ -109,3 +105,12 @@ size_t Fifo::read(void *buf, size_t len)
|
|||
return nextlen;
|
||||
}
|
||||
|
||||
static char n1[] = "fifo";
|
||||
static char d1[] = "Xilinx's AXI4 FIFO data mover";
|
||||
static char v1[] = "xilinx.com:ip:axi_fifo_mm_s:";
|
||||
static NodePlugin<Fifo, n1, d1, v1> p1;
|
||||
|
||||
static char n2[] = "fifo_data";
|
||||
static char d2[] = "Xilinx's AXI4 data stream FIFO";
|
||||
static char v2[] = "xilinx.com:ip:axis_data_fifo:";
|
||||
static NodePlugin<FifoData, n2, d2, v2> p2;
|
||||
|
|
|
@ -26,14 +26,15 @@
|
|||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
// Instantiate factory to make available to plugin infrastructure
|
||||
static GeneralPurposeIOFactory factory;
|
||||
|
||||
bool
|
||||
GeneralPurposeIO::init()
|
||||
Gpio::init()
|
||||
{
|
||||
//const uintptr_t base = getBaseAddr(registerMemory);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static char n[] = "gpio";
|
||||
static char d[] = "Xilinx's AXI4 general purpose IO";
|
||||
static char v[] = "xilinx.com:ip:axi_gpio:";
|
||||
static CorePlugin<Gpio, n, d, v> f;
|
||||
|
|
|
@ -33,9 +33,6 @@
|
|||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
// Instantiate factory to make available to plugin infrastructure
|
||||
static InterruptControllerFactory factory;
|
||||
|
||||
InterruptController::~InterruptController()
|
||||
{
|
||||
card->vfioDevice->pciMsiDeinit(this->efds);
|
||||
|
@ -167,3 +164,7 @@ InterruptController::waitForInterrupt(int irq)
|
|||
}
|
||||
}
|
||||
|
||||
static char n[] = "intc";
|
||||
static char d[] = "Xilinx's programmable interrupt controller";
|
||||
static char v[] = "xilinx.com:module_ref:axi_pcie_intc:";
|
||||
static CorePlugin<InterruptController, n, d, v> f;
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
static AxiPciExpressBridgeFactory factory;
|
||||
|
||||
bool
|
||||
AxiPciExpressBridge::init()
|
||||
{
|
||||
|
@ -162,3 +160,5 @@ AxiPciExpressBridgeFactory::parse(Core &ip, json_t *cfg)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AxiPciExpressBridgeFactory p;
|
||||
|
|
|
@ -53,9 +53,7 @@
|
|||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
static RtdsFactory rtdsFactoryInstance;
|
||||
|
||||
void Rtds::dump()
|
||||
void RtdsGtfpga::dump()
|
||||
{
|
||||
// Check RTDS_Axis registers
|
||||
const uint32_t sr = readMemory<uint32_t>(registerMemory, RTDS_AXIS_SR_OFFSET);
|
||||
|
@ -81,9 +79,13 @@ void Rtds::dump()
|
|||
logger->info("RTDS timestep period: {:.3f} us", getDt() * 1e6);
|
||||
}
|
||||
|
||||
double Rtds::getDt()
|
||||
double RtdsGtfpga::getDt()
|
||||
{
|
||||
const auto dt = readMemory<uint16_t>(registerMemory, RTDS_AXIS_TS_PERIOD_OFFSET);
|
||||
return (dt == 0xFFFF) ? 0.0 : (double) dt / RTDS_HZ;
|
||||
}
|
||||
|
||||
static char n[] = "rtds_gtfpga";
|
||||
static char d[] = "RTDS's AXI4-Stream - GTFPGA interface";
|
||||
static char v[] = "acs.eonerc.rwth-aachen.de:user:rtds_axis:";
|
||||
static NodePlugin<RtdsGtfpga, n, d, v> f;
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
static Gpu2RtdsFactory factory;
|
||||
|
||||
bool Gpu2Rtds::init()
|
||||
{
|
||||
Hls::init();
|
||||
|
@ -125,3 +123,7 @@ Gpu2Rtds::getMaxFrameSize()
|
|||
// logger->info(" Seq. number: {}", (int) doorbell.seq_nr);
|
||||
//}
|
||||
|
||||
static char n[] = "gpu2rtds";
|
||||
static char d[] = "HLS Gpu2Rtds IP";
|
||||
static char v[] = "acs.eonerc.rwth-aachen.de:hls:gpu2rtds:";
|
||||
static NodePlugin<Gpu2Rtds, n, d, v> p;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <villas/fpga/ips/rtds2gpu.hpp>
|
||||
|
||||
using namespace villas::fpga::ip;
|
||||
static Rtds2GpuFactory factory;
|
||||
|
||||
bool Rtds2Gpu::init()
|
||||
{
|
||||
|
@ -77,8 +76,7 @@ bool Rtds2Gpu::startOnce(const MemoryBlock &mem, size_t frameSize, size_t dataOf
|
|||
return start();
|
||||
}
|
||||
|
||||
bool
|
||||
Rtds2Gpu::updateStatus()
|
||||
bool Rtds2Gpu::updateStatus()
|
||||
{
|
||||
if (not XRtds2gpu_Get_status_vld(&xInstance))
|
||||
return false;
|
||||
|
@ -88,8 +86,7 @@ Rtds2Gpu::updateStatus()
|
|||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
Rtds2Gpu::getMaxFrameSize()
|
||||
size_t Rtds2Gpu::getMaxFrameSize()
|
||||
{
|
||||
XRtds2gpu_Set_frame_size(&xInstance, 0);
|
||||
|
||||
|
@ -100,8 +97,7 @@ Rtds2Gpu::getMaxFrameSize()
|
|||
return status.max_frame_size;
|
||||
}
|
||||
|
||||
void
|
||||
Rtds2Gpu::dumpDoorbell(uint32_t doorbellRegister) const
|
||||
void Rtds2Gpu::dumpDoorbell(uint32_t doorbellRegister) const
|
||||
{
|
||||
auto &doorbell = reinterpret_cast<reg_doorbell_t&>(doorbellRegister);
|
||||
|
||||
|
@ -111,3 +107,7 @@ Rtds2Gpu::dumpDoorbell(uint32_t doorbellRegister) const
|
|||
logger->info(" Seq. number: {}", (int) doorbell.seq_nr);
|
||||
}
|
||||
|
||||
static char n[] = "Rtds2Gpu";
|
||||
static char d[] = "HLS RTDS2GPU IP";
|
||||
static char v[] = "acs.eonerc.rwth-aachen.de:hls:rtds2gpu:";
|
||||
static NodePlugin<Rtds2Gpu, n, d, v> f;
|
||||
|
|
|
@ -33,8 +33,6 @@ namespace villas {
|
|||
namespace fpga {
|
||||
namespace ip {
|
||||
|
||||
static AxiStreamSwitchFactory factory;
|
||||
|
||||
bool AxiStreamSwitch::init()
|
||||
{
|
||||
if (XAxisScr_CfgInitialize(&xSwitch, &xConfig, getBaseAddr(registerMemory)) != XST_SUCCESS) {
|
||||
|
@ -150,6 +148,8 @@ void AxiStreamSwitchFactory::parse(Core &ip, json_t *cfg)
|
|||
axiSwitch.xConfig.MaxNumSI = num_si;
|
||||
}
|
||||
|
||||
static AxiStreamSwitchFactory f;
|
||||
|
||||
} /* namespace ip */
|
||||
} /* namespace fpga */
|
||||
} /* namespace villas */
|
||||
|
|
|
@ -32,9 +32,6 @@
|
|||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
// Instantiate factory to make available to plugin infrastructure
|
||||
static TimerFactory factory;
|
||||
|
||||
bool Timer::init()
|
||||
{
|
||||
XTmrCtr_Config xtmr_cfg;
|
||||
|
@ -77,3 +74,8 @@ uint32_t Timer::remaining()
|
|||
{
|
||||
return XTmrCtr_GetValue(&xTmr, 0);
|
||||
}
|
||||
|
||||
static char n[] = "timer";
|
||||
static char d[] = "Xilinx's programmable timer / counter";
|
||||
static char v[] = "xilinx.com:ip:axi_timer:";
|
||||
static CorePlugin<Timer, n, d, v> f;
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
|
||||
using namespace villas::fpga::ip;
|
||||
|
||||
StreamGraph
|
||||
Node::streamGraph;
|
||||
StreamGraph Node::streamGraph;
|
||||
|
||||
void NodeFactory::parse(Core &ip, json_t *cfg)
|
||||
{
|
||||
|
|
|
@ -46,12 +46,12 @@ Test(fpga, rtds, .description = "RTDS")
|
|||
{
|
||||
auto logger = villas::logging.get("unit-test:rtds");
|
||||
|
||||
std::list<villas::fpga::ip::Rtds*> rtdsIps;
|
||||
std::list<villas::fpga::ip::RtdsGtfpga*> rtdsIps;
|
||||
std::list<villas::fpga::ip::Dma*> dmaIps;
|
||||
|
||||
for (auto &ip : state.cards.front()->ips) {
|
||||
if (*ip == villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")) {
|
||||
auto rtds = reinterpret_cast<villas::fpga::ip::Rtds*>(ip.get());
|
||||
auto rtds = reinterpret_cast<villas::fpga::ip::RtdsGtfpga*>(ip.get());
|
||||
rtdsIps.push_back(rtds);
|
||||
}
|
||||
|
||||
|
|
2
fpga/thirdparty/libxil
vendored
2
fpga/thirdparty/libxil
vendored
|
@ -1 +1 @@
|
|||
Subproject commit b2912955266a6fe8f4f869bf0207497607744d63
|
||||
Subproject commit 33ea5a25dc0f525199aff5f2a3b97312ed9472ab
|
Loading…
Add table
Reference in a new issue