From 5d4040adedbc85c8017b85d092db797aa0b3a2f8 Mon Sep 17 00:00:00 2001 From: daniel-k Date: Tue, 5 Dec 2017 17:49:27 +0100 Subject: [PATCH] first port to C++ of plugin and fpga ip infrastructure --- fpga/include/villas/fpga/ip.hpp | 128 ++++++++++++++++++++++++ fpga/include/villas/fpga/ips/intc.hpp | 88 ++++++++++++++++ fpga/include/villas/fpga/vlnv.hpp | 86 ++++++++++++++++ fpga/include/villas/plugin.hpp | 81 +++++++++++++++ fpga/lib/CMakeLists.txt | 6 +- fpga/lib/ip.cpp | 95 ++++++++++++++++++ fpga/lib/ips/intc.cpp | 107 ++++++++------------ fpga/lib/plugin.cpp | 139 ++++++++++++++++++++++++++ fpga/lib/vlnv.cpp | 69 +++++++++++++ 9 files changed, 731 insertions(+), 68 deletions(-) create mode 100644 fpga/include/villas/fpga/ip.hpp create mode 100644 fpga/include/villas/fpga/ips/intc.hpp create mode 100644 fpga/include/villas/fpga/vlnv.hpp create mode 100644 fpga/include/villas/plugin.hpp create mode 100644 fpga/lib/ip.cpp create mode 100644 fpga/lib/plugin.cpp create mode 100644 fpga/lib/vlnv.cpp diff --git a/fpga/include/villas/fpga/ip.hpp b/fpga/include/villas/fpga/ip.hpp new file mode 100644 index 000000000..0ed4bdca1 --- /dev/null +++ b/fpga/include/villas/fpga/ip.hpp @@ -0,0 +1,128 @@ +/** Interlectual Property component. + * + * This class represents a module within the FPGA. + * + * @file + * @author Steffen Vogel + * @author Daniel Krebs + * @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 . + *********************************************************************************/ + +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once + +#include +#include + +#include "common.h" + +#include "log.h" +#include "utils.h" + +#include "fpga/vlnv.hpp" + +#include "plugin.hpp" +#include "card.h" + +#include + +#include + +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(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 diff --git a/fpga/include/villas/fpga/ips/intc.hpp b/fpga/include/villas/fpga/ips/intc.hpp new file mode 100644 index 000000000..1facaa38c --- /dev/null +++ b/fpga/include/villas/fpga/ips/intc.hpp @@ -0,0 +1,88 @@ +/** AXI-PCIe Interrupt controller + * + * @file + * @author Steffen Vogel + * @author Daniel Krebs + * @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 "fpga/ip.hpp" +#include + +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 + +/** @} */ diff --git a/fpga/include/villas/fpga/vlnv.hpp b/fpga/include/villas/fpga/vlnv.hpp new file mode 100644 index 000000000..c089ce4e9 --- /dev/null +++ b/fpga/include/villas/fpga/vlnv.hpp @@ -0,0 +1,86 @@ +/** Vendor, Library, Name, Version (VLNV) tag. + * + * @file + * @author Daniel Krebs + * @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 . + *********************************************************************************/ + +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once + +#include +#include +#include + +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_ @} */ diff --git a/fpga/include/villas/plugin.hpp b/fpga/include/villas/plugin.hpp new file mode 100644 index 000000000..1691c15ff --- /dev/null +++ b/fpga/include/villas/plugin.hpp @@ -0,0 +1,81 @@ +/** Loadable / plugin support. + * + * @file + * @author Steffen Vogel + * @author Daniel Krebs + * @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 . + *********************************************************************************/ + +#pragma once + +#include +#include +#include + +#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 + 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; + static std::list pluginList; +}; + +} // namespace villas diff --git a/fpga/lib/CMakeLists.txt b/fpga/lib/CMakeLists.txt index 77eeb70ff..e13b43edd 100644 --- a/fpga/lib/CMakeLists.txt +++ b/fpga/lib/CMakeLists.txt @@ -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 diff --git a/fpga/lib/ip.cpp b/fpga/lib/ip.cpp new file mode 100644 index 000000000..d573ef03d --- /dev/null +++ b/fpga/lib/ip.cpp @@ -0,0 +1,95 @@ +/** FPGA IP component. + * + * @author Steffen Vogel + * @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 . + *********************************************************************************/ + +#include "log_config.h" +#include "log.h" +#include "plugin.h" + +#include "fpga/ip.hpp" + +#include + +namespace villas { + + +FpgaIpFactory* FpgaIpFactory::lookup(const FpgaVlnv &vlnv) +{ + for(auto& ip : Plugin::lookup(Plugin::Type::FpgaIp)) { + FpgaIpFactory* fpgaIpFactory = dynamic_cast(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 diff --git a/fpga/lib/ips/intc.cpp b/fpga/lib/ips/intc.cpp index 7fcf109d6..d17a2c9a1 100644 --- a/fpga/lib/ips/intc.cpp +++ b/fpga/lib/ips/intc.cpp @@ -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 diff --git a/fpga/lib/plugin.cpp b/fpga/lib/plugin.cpp new file mode 100644 index 000000000..309314da7 --- /dev/null +++ b/fpga/lib/plugin.cpp @@ -0,0 +1,139 @@ +/** Loadable / plugin support. + * + * @author Steffen Vogel + * @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 . + *********************************************************************************/ + +#include +#include + +#include +#include +#include + +#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::lookup(Plugin::Type type) +{ + std::list 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 diff --git a/fpga/lib/vlnv.cpp b/fpga/lib/vlnv.cpp new file mode 100644 index 000000000..b9b007ce4 --- /dev/null +++ b/fpga/lib/vlnv.cpp @@ -0,0 +1,69 @@ +/** Vendor, Library, Name, Version (VLNV) tag + * + * @author Steffen Vogel + * @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 . + *********************************************************************************/ + +#include +#include + +#include +#include + +#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