mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
first port to C++ of plugin and fpga ip infrastructure
This commit is contained in:
parent
f0c089f719
commit
5d4040aded
9 changed files with 731 additions and 68 deletions
128
fpga/include/villas/fpga/ip.hpp
Normal file
128
fpga/include/villas/fpga/ip.hpp
Normal file
|
@ -0,0 +1,128 @@
|
|||
/** Interlectual Property component.
|
||||
*
|
||||
* This class represents a module within the FPGA.
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @author Daniel Krebs <github@daniel-krebs.net>
|
||||
* @copyright 2017, 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/>.
|
||||
*********************************************************************************/
|
||||
|
||||
/** @addtogroup fpga VILLASfpga
|
||||
* @{
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "fpga/vlnv.hpp"
|
||||
|
||||
#include "plugin.hpp"
|
||||
#include "card.h"
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace villas {
|
||||
|
||||
//enum fpga_ip_types {
|
||||
// FPGA_IP_TYPE_DM_DMA, /**< A datamover IP exchanges streaming data between the FPGA and the CPU. */
|
||||
// FPGA_IP_TYPE_DM_FIFO, /**< A datamover IP exchanges streaming data between the FPGA and the CPU. */
|
||||
// FPGA_IP_TYPE_MODEL, /**< A model IP simulates a system on the FPGA. */
|
||||
// FPGA_IP_TYPE_MATH, /**< A math IP performs some kind of mathematical operation on the streaming data */
|
||||
// FPGA_IP_TYPE_MISC, /**< Other IP components like timer, counters, interrupt conctrollers or routing. */
|
||||
// FPGA_IP_TYPE_INTERFACE /**< A interface IP connects the FPGA to another system or controller. */
|
||||
//} type;
|
||||
|
||||
|
||||
class FpgaIpFactory;
|
||||
|
||||
class FpgaIp {
|
||||
public:
|
||||
|
||||
friend FpgaIpFactory;
|
||||
|
||||
FpgaIp() : card(nullptr), baseaddr(0), irq(-1), port(-1) {}
|
||||
virtual ~FpgaIp() {}
|
||||
|
||||
// IPs can implement this interface
|
||||
virtual bool check() { return true; }
|
||||
virtual bool start() { return true; }
|
||||
virtual bool stop() { return true; }
|
||||
virtual bool reset() { return true; }
|
||||
virtual void dump()
|
||||
{
|
||||
info("IP %s: vlnv=%s baseaddr=%#jx, irq=%d, port=%d",
|
||||
name.c_str(), vlnv.toString().c_str(), baseaddr, irq, port);
|
||||
}
|
||||
|
||||
protected:
|
||||
uintptr_t
|
||||
getBaseaddr() const
|
||||
{
|
||||
assert(card != nullptr);
|
||||
return reinterpret_cast<uintptr_t>(card->map) + this->baseaddr;
|
||||
}
|
||||
|
||||
protected:
|
||||
// populated by FpgaIpFactory
|
||||
struct fpga_card *card; /**< FPGA card this IP is instantiated on */
|
||||
std::string name; /**< Name defined in JSON config */
|
||||
FpgaVlnv vlnv; /**< VLNV defined in JSON config */
|
||||
uintptr_t baseaddr; /**< The baseadress of this FPGA IP component */
|
||||
int irq; /**< The interrupt number of the FPGA IP component. */
|
||||
int port; /**< The port of the AXI4-Stream switch to which this FPGA IP component is connected. */
|
||||
};
|
||||
|
||||
|
||||
class FpgaIpFactory : public Plugin {
|
||||
public:
|
||||
FpgaIpFactory()
|
||||
{ pluginType = Plugin::Type::FpgaIp; }
|
||||
|
||||
/// Returns a running and checked FPGA IP
|
||||
static FpgaIp* make(struct fpga_card* card, json_t *json, std::string name);
|
||||
|
||||
private:
|
||||
/// Create a concrete IP instance
|
||||
virtual FpgaIp* create() = 0;
|
||||
|
||||
/// Configure IP instance from JSON config
|
||||
virtual bool configureJson(FpgaIp* ip, json_t *json) = 0;
|
||||
|
||||
virtual FpgaVlnv getCompatibleVlnv() const = 0;
|
||||
virtual std::string getName() const = 0;
|
||||
virtual std::string getDescription() const = 0;
|
||||
|
||||
private:
|
||||
static FpgaIpFactory*
|
||||
lookup(const FpgaVlnv& vlnv);
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace villas
|
88
fpga/include/villas/fpga/ips/intc.hpp
Normal file
88
fpga/include/villas/fpga/ips/intc.hpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
/** AXI-PCIe Interrupt controller
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @author Daniel Krebs <github@daniel-krebs.net>
|
||||
* @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 "fpga/ip.hpp"
|
||||
#include <xilinx/xintc.h>
|
||||
|
||||
namespace villas {
|
||||
|
||||
class InterruptController : public FpgaIp
|
||||
{
|
||||
public:
|
||||
using IrqMaskType = uint32_t;
|
||||
static constexpr int maxIrqs = 32;
|
||||
|
||||
~InterruptController();
|
||||
|
||||
bool start();
|
||||
|
||||
int enableInterrupt(IrqMaskType mask, bool polling);
|
||||
int disableInterrupt(IrqMaskType mask);
|
||||
uint64_t waitForInterrupt(int irq);
|
||||
|
||||
private:
|
||||
struct Interrupt {
|
||||
int eventFd; /**< Event file descriptor */
|
||||
int number; /**< Interrupt number from /proc/interrupts */
|
||||
bool polling; /**< Polled or not */
|
||||
};
|
||||
|
||||
int num_irqs; /**< Number of available MSI vectors */
|
||||
int efds[maxIrqs];
|
||||
int nos[maxIrqs];
|
||||
bool polling[maxIrqs];
|
||||
// Interrupt irqs[maxIrqs]; /**< State of available interrupts */
|
||||
};
|
||||
|
||||
|
||||
|
||||
class InterruptControllerFactory : public FpgaIpFactory {
|
||||
public:
|
||||
|
||||
FpgaIp* create()
|
||||
{ return new InterruptController; }
|
||||
|
||||
std::string
|
||||
getName() const
|
||||
{ return "InterruptController"; }
|
||||
|
||||
std::string
|
||||
getDescription() const
|
||||
{ return "Xilinx's programmable interrupt controller"; }
|
||||
|
||||
FpgaVlnv getCompatibleVlnv() const
|
||||
{ return FpgaVlnv("acs.eonerc.rwth-aachen.de:user:axi_pcie_intc:"); }
|
||||
|
||||
bool configureJson(FpgaIp* ip, json_t *json);
|
||||
};
|
||||
|
||||
} // namespace villas
|
||||
|
||||
/** @} */
|
86
fpga/include/villas/fpga/vlnv.hpp
Normal file
86
fpga/include/villas/fpga/vlnv.hpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
/** Vendor, Library, Name, Version (VLNV) tag.
|
||||
*
|
||||
* @file
|
||||
* @author Daniel Krebs <github@daniel-krebs.net>
|
||||
* @copyright 2017, 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/>.
|
||||
*********************************************************************************/
|
||||
|
||||
/** @addtogroup fpga VILLASfpga
|
||||
* @{
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
namespace villas {
|
||||
|
||||
class FpgaVlnv {
|
||||
public:
|
||||
|
||||
static constexpr char delimiter = ':';
|
||||
static constexpr char wildcard[] = "*";
|
||||
|
||||
FpgaVlnv() :
|
||||
vendor(""), library(""), name(""), version("") {}
|
||||
|
||||
FpgaVlnv(std::string s) {
|
||||
parseFromString(s);
|
||||
}
|
||||
|
||||
std::string
|
||||
toString() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
std::string string;
|
||||
|
||||
stream << *this;
|
||||
stream >> string;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const FpgaVlnv& other) const;
|
||||
|
||||
friend std::ostream&
|
||||
operator<< (std::ostream& stream, const FpgaVlnv& vlnv)
|
||||
{
|
||||
return stream
|
||||
<< (vlnv.vendor.empty() ? "*" : vlnv.vendor) << ":"
|
||||
<< (vlnv.library.empty() ? "*" : vlnv.library) << ":"
|
||||
<< (vlnv.name.empty() ? "*" : vlnv.name) << ":"
|
||||
<< (vlnv.version.empty() ? "*" : vlnv.version);
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
parseFromString(std::string vlnv);
|
||||
|
||||
std::string vendor;
|
||||
std::string library;
|
||||
std::string name;
|
||||
std::string version;
|
||||
};
|
||||
|
||||
} // namespace villas
|
||||
|
||||
/** _FPGA_VLNV_HPP_ @} */
|
81
fpga/include/villas/plugin.hpp
Normal file
81
fpga/include/villas/plugin.hpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
/** Loadable / plugin support.
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @author Daniel Krebs <github@daniel-krebs.net>
|
||||
* @copyright 2017, 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 <list>
|
||||
#include <string>
|
||||
#include <jansson.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace villas {
|
||||
|
||||
class Plugin {
|
||||
public:
|
||||
|
||||
enum class Type {
|
||||
Unknown,
|
||||
FpgaIp,
|
||||
};
|
||||
|
||||
Plugin();
|
||||
virtual ~Plugin();
|
||||
|
||||
// each plugin is a singleton, so copying is not allowed
|
||||
Plugin(Plugin const&) = delete;
|
||||
void operator=(Plugin const&) = delete;
|
||||
|
||||
int load();
|
||||
int unload();
|
||||
|
||||
virtual int parse(json_t *cfg);
|
||||
virtual void dump();
|
||||
|
||||
/** Find registered and loaded plugin with given name and type. */
|
||||
static Plugin *
|
||||
lookup(Type type, std::string name);
|
||||
|
||||
static std::list<Plugin*>
|
||||
lookup(Type type);
|
||||
|
||||
// check if this makes sense! (no intermediate plugins)
|
||||
bool
|
||||
operator==(const Plugin& other) const;
|
||||
|
||||
Type pluginType;
|
||||
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string path;
|
||||
void *handle;
|
||||
|
||||
enum state state;
|
||||
|
||||
private:
|
||||
using PluginList = std::list<Plugin *>;
|
||||
static std::list<Plugin *> pluginList;
|
||||
};
|
||||
|
||||
} // namespace villas
|
|
@ -1,6 +1,6 @@
|
|||
set(SOURCES
|
||||
ip.c
|
||||
vlnv.c
|
||||
ip.cpp
|
||||
vlnv.cpp
|
||||
card.c
|
||||
|
||||
ips/timer.c
|
||||
|
@ -17,7 +17,7 @@ set(SOURCES
|
|||
kernel/pci.c
|
||||
kernel/vfio.c
|
||||
|
||||
plugin.c
|
||||
plugin.cpp
|
||||
utils.c
|
||||
list.c
|
||||
log.c
|
||||
|
|
95
fpga/lib/ip.cpp
Normal file
95
fpga/lib/ip.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
/** FPGA IP component.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2017, 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 "log_config.h"
|
||||
#include "log.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#include "fpga/ip.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace villas {
|
||||
|
||||
|
||||
FpgaIpFactory* FpgaIpFactory::lookup(const FpgaVlnv &vlnv)
|
||||
{
|
||||
for(auto& ip : Plugin::lookup(Plugin::Type::FpgaIp)) {
|
||||
FpgaIpFactory* fpgaIpFactory = dynamic_cast<FpgaIpFactory *>(ip);
|
||||
|
||||
if(fpgaIpFactory->getCompatibleVlnv() == vlnv)
|
||||
return fpgaIpFactory;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FpgaIp *FpgaIpFactory::make(fpga_card *card, json_t *json, std::string name)
|
||||
{
|
||||
// extract VLNV from JSON
|
||||
const char* vlnv_raw;
|
||||
if(json_unpack(json, "{ s: s }", "vlnv", &vlnv_raw) != 0)
|
||||
error("IP '%s' has no entry 'vlnv'", name.c_str());
|
||||
|
||||
// find the appropriate factory that can create the specified VLNV
|
||||
// Note:
|
||||
// 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.
|
||||
FpgaVlnv vlnv(vlnv_raw);
|
||||
FpgaIpFactory* fpgaIpFactory = lookup(vlnv);
|
||||
|
||||
if(fpgaIpFactory == nullptr) {
|
||||
error("No ip factory registered to handle VLNV '%s'", vlnv.toString().c_str());
|
||||
} else {
|
||||
info("Using %s for IP %s", fpgaIpFactory->getName().c_str(), vlnv.toString().c_str());
|
||||
}
|
||||
|
||||
// create new IP instance
|
||||
FpgaIp* ip = fpgaIpFactory->create();
|
||||
|
||||
// setup generic IP type properties
|
||||
ip->card = card;
|
||||
ip->name = name;
|
||||
ip->vlnv = vlnv;
|
||||
|
||||
// extract some optional properties
|
||||
int ret = json_unpack(json, "{ s?: i, s?: i, s?: i }",
|
||||
"baseaddr", &ip->baseaddr,
|
||||
"irq", &ip->irq,
|
||||
"port", &ip->port);
|
||||
if(ret != 0)
|
||||
error("Problem while parsing JSON");
|
||||
|
||||
// IP-specific setup via JSON config
|
||||
fpgaIpFactory->configureJson(ip, json);
|
||||
|
||||
if(not ip->start())
|
||||
error("Cannot start IP");
|
||||
|
||||
if(not ip->check())
|
||||
error("Checking IP failed");
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
} // namespace villas
|
|
@ -24,40 +24,37 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "plugin.h"
|
||||
#include "plugin.hpp"
|
||||
|
||||
#include "kernel/vfio.h"
|
||||
#include "kernel/kernel.h"
|
||||
|
||||
#include "fpga/ip.h"
|
||||
#include "fpga/card.h"
|
||||
#include "fpga/ips/intc.h"
|
||||
#include "fpga/ips/intc.hpp"
|
||||
|
||||
int intc_start(struct fpga_ip *c)
|
||||
namespace villas {
|
||||
|
||||
InterruptController::~InterruptController()
|
||||
{
|
||||
int ret;
|
||||
vfio_pci_msi_deinit(&card->vfio_device , this->efds);
|
||||
}
|
||||
|
||||
struct fpga_card *f = c->card;
|
||||
struct intc *intc = (struct intc *) c->_vd;
|
||||
bool InterruptController::start()
|
||||
{
|
||||
const uintptr_t base = getBaseaddr();
|
||||
|
||||
uintptr_t base = (uintptr_t) f->map + c->baseaddr;
|
||||
num_irqs = vfio_pci_msi_init(&card->vfio_device, efds);
|
||||
if (num_irqs < 0)
|
||||
return false;
|
||||
|
||||
if (c != f->intc)
|
||||
error("There can be only one interrupt controller per FPGA");
|
||||
|
||||
intc->num_irqs = vfio_pci_msi_init(&f->vfio_device, intc->efds);
|
||||
if (intc->num_irqs < 0)
|
||||
return -1;
|
||||
|
||||
ret = vfio_pci_msi_find(&f->vfio_device, intc->nos);
|
||||
if (ret)
|
||||
return -2;
|
||||
if(vfio_pci_msi_find(&card->vfio_device, nos) != 0)
|
||||
return false;
|
||||
|
||||
/* For each IRQ */
|
||||
for (int i = 0; i < intc->num_irqs; i++) {
|
||||
for (int i = 0; i < num_irqs; i++) {
|
||||
/* Pin to core */
|
||||
ret = kernel_irq_setaffinity(intc->nos[i], f->affinity, NULL);
|
||||
if (ret)
|
||||
if(kernel_irq_setaffinity(nos[i], card->affinity, NULL) !=0)
|
||||
serror("Failed to change affinity of VFIO-MSI interrupt");
|
||||
|
||||
/* Setup vector */
|
||||
|
@ -72,26 +69,14 @@ int intc_start(struct fpga_ip *c)
|
|||
|
||||
debug(4, "FPGA: enabled interrupts");
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int intc_destroy(struct fpga_ip *c)
|
||||
int
|
||||
InterruptController::enableInterrupt(InterruptController::IrqMaskType mask, bool polling)
|
||||
{
|
||||
struct fpga_card *f = c->card;
|
||||
struct intc *intc = (struct intc *) c->_vd;
|
||||
|
||||
vfio_pci_msi_deinit(&f->vfio_device, intc->efds);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intc_enable(struct fpga_ip *c, uint32_t mask, int flags)
|
||||
{
|
||||
struct fpga_card *f = c->card;
|
||||
struct intc *intc = (struct intc *) c->_vd;
|
||||
|
||||
uint32_t ier, imr;
|
||||
uintptr_t base = (uintptr_t) f->map + c->baseaddr;
|
||||
const uintptr_t base = getBaseaddr();
|
||||
|
||||
/* Current state of INTC */
|
||||
ier = XIntc_In32(base + XIN_IER_OFFSET);
|
||||
|
@ -100,12 +85,12 @@ int intc_enable(struct fpga_ip *c, uint32_t mask, int flags)
|
|||
/* Clear pending IRQs */
|
||||
XIntc_Out32(base + XIN_IAR_OFFSET, mask);
|
||||
|
||||
for (int i = 0; i < intc->num_irqs; i++) {
|
||||
for (int i = 0; i < num_irqs; i++) {
|
||||
if (mask & (1 << i))
|
||||
intc->flags[i] = flags;
|
||||
this->polling[i] = polling;
|
||||
}
|
||||
|
||||
if (flags & INTC_POLLING) {
|
||||
if (polling) {
|
||||
XIntc_Out32(base + XIN_IMR_OFFSET, imr & ~mask);
|
||||
XIntc_Out32(base + XIN_IER_OFFSET, ier & ~mask);
|
||||
}
|
||||
|
@ -118,31 +103,29 @@ int intc_enable(struct fpga_ip *c, uint32_t mask, int flags)
|
|||
debug(3, "New imr = %#x", XIntc_In32(base + XIN_IMR_OFFSET));
|
||||
debug(3, "New isr = %#x", XIntc_In32(base + XIN_ISR_OFFSET));
|
||||
|
||||
debug(8, "FPGA: Interupt enabled: mask=%#x flags=%#x", mask, flags);
|
||||
debug(8, "FPGA: Interupts enabled: mask=%#x polling=%d", mask, polling);
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int intc_disable(struct fpga_ip *c, uint32_t mask)
|
||||
int
|
||||
InterruptController::disableInterrupt(InterruptController::IrqMaskType mask)
|
||||
{
|
||||
struct fpga_card *f = c->card;
|
||||
|
||||
uintptr_t base = (uintptr_t) f->map + c->baseaddr;
|
||||
const uintptr_t base = getBaseaddr();
|
||||
uint32_t ier = XIntc_In32(base + XIN_IER_OFFSET);
|
||||
|
||||
XIntc_Out32(base + XIN_IER_OFFSET, ier & ~mask);
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t intc_wait(struct fpga_ip *c, int irq)
|
||||
uint64_t InterruptController::waitForInterrupt(int irq)
|
||||
{
|
||||
struct fpga_card *f = c->card;
|
||||
struct intc *intc = (struct intc *) c->_vd;
|
||||
assert(irq < maxIrqs);
|
||||
|
||||
uintptr_t base = (uintptr_t) f->map + c->baseaddr;
|
||||
const uintptr_t base = getBaseaddr();
|
||||
|
||||
if (intc->flags[irq] & INTC_POLLING) {
|
||||
if (this->polling[irq]) {
|
||||
uint32_t isr, mask = 1 << irq;
|
||||
|
||||
do {
|
||||
|
@ -156,7 +139,7 @@ uint64_t intc_wait(struct fpga_ip *c, int irq)
|
|||
}
|
||||
else {
|
||||
uint64_t cnt;
|
||||
ssize_t ret = read(intc->efds[irq], &cnt, sizeof(cnt));
|
||||
ssize_t ret = read(efds[irq], &cnt, sizeof(cnt));
|
||||
if (ret != sizeof(cnt))
|
||||
return 0;
|
||||
|
||||
|
@ -164,17 +147,11 @@ uint64_t intc_wait(struct fpga_ip *c, int irq)
|
|||
}
|
||||
}
|
||||
|
||||
static struct plugin p = {
|
||||
.name = "Xilinx's programmable interrupt controller",
|
||||
.description = "",
|
||||
.type = PLUGIN_TYPE_FPGA_IP,
|
||||
.ip = {
|
||||
.vlnv = { "acs.eonerc.rwth-aachen.de", "user", "axi_pcie_intc", NULL },
|
||||
.type = FPGA_IP_TYPE_MISC,
|
||||
.start = intc_start,
|
||||
.destroy = intc_destroy,
|
||||
.size = sizeof(struct intc)
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_PLUGIN(&p)
|
||||
bool InterruptControllerFactory::configureJson(FpgaIp *ip, json_t *json)
|
||||
{
|
||||
// parse json and configure instance here
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace villas
|
||||
|
|
139
fpga/lib/plugin.cpp
Normal file
139
fpga/lib/plugin.cpp
Normal file
|
@ -0,0 +1,139 @@
|
|||
/** Loadable / plugin support.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2017, 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 <dlfcn.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <iostream>
|
||||
|
||||
#include "plugin.hpp"
|
||||
|
||||
|
||||
namespace villas {
|
||||
|
||||
// list of all registered plugins
|
||||
Plugin::PluginList Plugin::pluginList;
|
||||
|
||||
|
||||
Plugin::Plugin() :
|
||||
name(""),
|
||||
description(""),
|
||||
path(""),
|
||||
pluginType(Plugin::Type::Unknown),
|
||||
state(STATE_INITIALIZED)
|
||||
{
|
||||
// push to global plugin list
|
||||
pluginList.push_back(this);
|
||||
}
|
||||
|
||||
Plugin::~Plugin()
|
||||
{
|
||||
// clean from global plugin list
|
||||
pluginList.remove(this);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Plugin::parse(json_t *cfg)
|
||||
{
|
||||
const char *path;
|
||||
|
||||
path = json_string_value(cfg);
|
||||
if (!path)
|
||||
return -1;
|
||||
|
||||
this->path = std::string(path);
|
||||
this->state = STATE_PARSED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Plugin::load()
|
||||
{
|
||||
assert(this->state == STATE_PARSED);
|
||||
assert(not this->path.empty());
|
||||
|
||||
this->handle = dlopen(this->path.c_str(), RTLD_NOW);
|
||||
|
||||
if (this->handle == nullptr)
|
||||
return -1;
|
||||
|
||||
this->state = STATE_LOADED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Plugin::unload()
|
||||
{
|
||||
int ret;
|
||||
|
||||
assert(this->state == STATE_LOADED);
|
||||
|
||||
ret = dlclose(this->handle);
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
|
||||
this->state = STATE_UNLOADED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Plugin::dump()
|
||||
{
|
||||
std::cout << " - " << this->name << ": " << this->description << std::endl;
|
||||
}
|
||||
|
||||
Plugin*
|
||||
Plugin::lookup(Plugin::Type type, std::string name)
|
||||
{
|
||||
for(auto& p : pluginList) {
|
||||
if(p->pluginType == type and p->name == name)
|
||||
return p;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::list<Plugin*>
|
||||
Plugin::lookup(Plugin::Type type)
|
||||
{
|
||||
std::list<Plugin*> list;
|
||||
for(auto& p : pluginList) {
|
||||
if(p->pluginType == type)
|
||||
list.push_back(p);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
bool
|
||||
Plugin::operator==(const Plugin &other) const
|
||||
{
|
||||
return (this->pluginType == other.pluginType) and (this->name == other.name);
|
||||
}
|
||||
|
||||
} // namespace villas
|
69
fpga/lib/vlnv.cpp
Normal file
69
fpga/lib/vlnv.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
/** Vendor, Library, Name, Version (VLNV) tag
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2017, 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 <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fpga/vlnv.hpp"
|
||||
#include "fpga/ip.hpp"
|
||||
|
||||
namespace villas {
|
||||
|
||||
bool
|
||||
FpgaVlnv::operator==(const FpgaVlnv &other) const
|
||||
{
|
||||
// if a field is empty, it means wildcard matching everything
|
||||
const bool vendorWildcard = vendor.empty() or other.vendor.empty();
|
||||
const bool libraryWildcard = library.empty() or other.library.empty();
|
||||
const bool nameWildcard = name.empty() or other.name.empty();
|
||||
const bool versionWildcard = version.empty() or other.version.empty();
|
||||
|
||||
const bool vendorMatch = vendorWildcard or vendor == other.vendor;
|
||||
const bool libraryMatch = libraryWildcard or library == other.library;
|
||||
const bool nameMatch = nameWildcard or name == other.name;
|
||||
const bool versionMatch = versionWildcard or version == other.version;
|
||||
|
||||
return vendorMatch and libraryMatch and nameMatch and versionMatch;
|
||||
}
|
||||
|
||||
void
|
||||
FpgaVlnv::parseFromString(std::string vlnv)
|
||||
{
|
||||
// tokenize by delimiter
|
||||
std::stringstream sstream(vlnv);
|
||||
std::getline(sstream, vendor, delimiter);
|
||||
std::getline(sstream, library, delimiter);
|
||||
std::getline(sstream, name, delimiter);
|
||||
std::getline(sstream, version, delimiter);
|
||||
|
||||
// represent wildcard internally as empty string
|
||||
if(vendor == wildcard) vendor = "";
|
||||
if(library == wildcard) library = "";
|
||||
if(name == wildcard) name = "";
|
||||
if(version == wildcard) version = "";
|
||||
}
|
||||
|
||||
|
||||
} // namespace villas
|
Loading…
Add table
Reference in a new issue