diff --git a/CMakeLists.txt b/CMakeLists.txt index 263529558..b333790f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,7 +97,7 @@ endif() set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig:/usr/local/lib64/pkgconfig:/usr/local/share/pkgconfig:/usr/lib64/pkgconfig") -pkg_check_modules(JANSSON IMPORTED_TARGET REQUIRED jansson>=2.9) +pkg_check_modules(JANSSON IMPORTED_TARGET REQUIRED jansson>=2.13) pkg_check_modules(LIBWEBSOCKETS IMPORTED_TARGET REQUIRED libwebsockets>=3.1.0) pkg_check_modules(PROTOBUF IMPORTED_TARGET protobuf>=2.6.0) pkg_check_modules(PROTOBUFC IMPORTED_TARGET libprotobuf-c>=1.1.0) @@ -118,12 +118,11 @@ pkg_check_modules(UUID IMPORTED_TARGET REQUIRED uuid>=2.23) pkg_check_modules(CGRAPH IMPORTED_TARGET libcgraph>=2.30) pkg_check_modules(GVC IMPORTED_TARGET libgvc>=2.30) pkg_check_modules(LIBUSB IMPORTED_TARGET libusb-1.0>=1.0.23) -pkg_check_modules(XIL IMPORTED_TARGET libxil) pkg_check_modules(NANOMSG IMPORTED_TARGET nanomsg) if(NOT NANOMSG_FOUND) pkg_check_modules(NANOMSG IMPORTED_TARGET libnanomsg>=1.0.0) endif() -pkg_check_modules(RE IMPORTED_TARGET re>=0.5.6) +pkg_check_modules(RE IMPORTED_TARGET re>=2.9.0) if(NOT RE_FOUND) pkg_check_modules(RE IMPORTED_TARGET libre>=0.5.6) endif() @@ -156,7 +155,7 @@ cmake_dependent_option(WITH_API "Build with remote control API" cmake_dependent_option(WITH_CLIENTS "Build client applications" ON "TOPLEVEL_PROJECT" OFF) cmake_dependent_option(WITH_CONFIG "Build with support for libconfig configuration syntax" ON "LIBCONFIG_FOUND" OFF) cmake_dependent_option(WITH_DOC "Build documentation" ON "TOPLEVEL_PROJECT" OFF) -cmake_dependent_option(WITH_FPGA "Build with support for VILLASfpga" ON "XIL_FOUND; FOUND_SUBMODULE_FPGA" OFF) +cmake_dependent_option(WITH_FPGA "Build with support for VILLASfpga" ON "FOUND_SUBMODULE_FPGA" OFF) cmake_dependent_option(WITH_GO "Build with Go" ON "GO" OFF) cmake_dependent_option(WITH_GRAPHVIZ "Build with Graphviz" ON "CGRAPH_FOUND; GVC_FOUND" OFF) cmake_dependent_option(WITH_HOOKS "Build with support for processing hook plugins" ON "" OFF) diff --git a/common b/common index 950857f1d..729b877a4 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 950857f1d792e2dad81d6e1f2e5b2d8cab60fd71 +Subproject commit 729b877a405b3bd80205fa1c54bfedbf2f030dc2 diff --git a/etc/examples/nodes/fpga.conf b/etc/examples/nodes/fpga.conf index 3551d5e2a..5066d4d49 100644 --- a/etc/examples/nodes/fpga.conf +++ b/etc/examples/nodes/fpga.conf @@ -4,18 +4,31 @@ logging = { fpgas = { vc707 = { - id = "10ee:7022" + # Card identification + id = "10ee:7021" + # slot = "88:00.0" + do_reset = true - ips = "@include ../etc/examples/nodes/vc707_ips.conf" + ips = "/global/projects/villas/fpga/software/etc/vc707-xbar-pcie/vc707-xbar-pcie.json" + + paths = ( + { + from = "aurora_8b10b_ch2" + to = "aurora_8b10b_ch3" + + reverse = true + } + ) } } nodes = { dma_0 = { type = "fpga", + fpga = "vc707" + target = "" - card = "vc707" datamover = "dma_0" use_irqs = false } @@ -24,10 +37,11 @@ nodes = { paths = ( { in = "dma_0" - out = [ ] hooks = ( - { type = "print" } + { + type = "print" + } ) } ) diff --git a/etc/examples/nodes/vc707_ips.conf b/etc/examples/nodes/vc707_ips.conf deleted file mode 100644 index fef945750..000000000 --- a/etc/examples/nodes/vc707_ips.conf +++ /dev/null @@ -1,253 +0,0 @@ -{ - "timer_0_axi_timer_0": { - "vlnv": "xilinx.com:ip:axi_timer:2.0", - "irqs": { - "generateout0": "pcie_0_axi_pcie_intc_0:0" - } - }, - "hier_0_axis_data_fifo_1": { - "ports": [ - { - "role": "master", - "name": "AXIS", - "target": "hier_0_axis_interconnect_0_axis_interconnect_0_xbar:S04_AXIS" - }, - { - "role": "slave", - "name": "AXIS", - "target": "hier_0_axis_interconnect_0_axis_interconnect_0_xbar:M04_AXIS" - } - ], - "vlnv": "xilinx.com:ip:axis_data_fifo:2.0" - }, - "hier_0_axis_interconnect_0_axis_interconnect_0_xbar": { - "ports": [ - { - "role": "slave", - "name": "S00_AXIS", - "target": "hier_0_aurora_axis_0:m_axis" - }, - { - "role": "master", - "name": "M00_AXIS", - "target": "hier_0_aurora_axis_0:s_axis" - }, - { - "role": "slave", - "name": "S01_AXIS", - "target": "hier_0_axi_dma_axi_dma_0:MM2S" - }, - { - "role": "master", - "name": "M01_AXIS", - "target": "hier_0_axi_dma_axi_dma_0:S2MM" - }, - { - "role": "slave", - "name": "S02_AXIS", - "target": "hier_0_axi_fifo_mm_s_0:STR_TXD" - }, - { - "role": "master", - "name": "M02_AXIS", - "target": "hier_0_axi_fifo_mm_s_0:STR_RXD" - }, - { - "role": "slave", - "name": "S03_AXIS", - "target": "hier_0_axis_data_fifo_0:AXIS" - }, - { - "role": "master", - "name": "M03_AXIS", - "target": "hier_0_axis_data_fifo_0:AXIS" - }, - { - "role": "slave", - "name": "S04_AXIS", - "target": "hier_0_axis_data_fifo_1:AXIS" - }, - { - "role": "master", - "name": "M04_AXIS", - "target": "hier_0_axis_data_fifo_1:AXIS" - } - ], - "num_ports": 5, - "vlnv": "xilinx.com:ip:axis_switch:1.1" - }, - "hier_0_axis_data_fifo_0": { - "ports": [ - { - "role": "master", - "name": "AXIS", - "target": "hier_0_axis_interconnect_0_axis_interconnect_0_xbar:S03_AXIS" - }, - { - "role": "slave", - "name": "AXIS", - "target": "hier_0_axis_interconnect_0_axis_interconnect_0_xbar:M03_AXIS" - } - ], - "vlnv": "xilinx.com:ip:axis_data_fifo:2.0" - }, - "hier_0_aurora_axis_0": { - "ports": [ - { - "role": "master", - "name": "m_axis", - "target": "hier_0_axis_interconnect_0_axis_interconnect_0_xbar:S00_AXIS" - }, - { - "role": "slave", - "name": "s_axis", - "target": "hier_0_axis_interconnect_0_axis_interconnect_0_xbar:M00_AXIS" - } - ], - "vlnv": "acs.eonerc.rwth-aachen.de:user:aurora_axis:1.16" - }, - "pcie_0_axi_reset_0": { - "vlnv": "xilinx.com:ip:axi_gpio:2.0" - }, - "hier_0_axi_fifo_mm_s_0": { - "ports": [ - { - "role": "master", - "name": "STR_TXD", - "target": "hier_0_axis_interconnect_0_axis_interconnect_0_xbar:S02_AXIS" - }, - { - "role": "slave", - "name": "STR_RXD", - "target": "hier_0_axis_interconnect_0_axis_interconnect_0_xbar:M02_AXIS" - } - ], - "vlnv": "xilinx.com:ip:axi_fifo_mm_s:4.2", - "irqs": { - "interrupt": "pcie_0_axi_pcie_intc_0:1" - } - }, - "hier_0_axi_dma_axi_dma_0": { - "ports": [ - { - "role": "master", - "name": "MM2S", - "target": "hier_0_axis_interconnect_0_axis_interconnect_0_xbar:S01_AXIS" - }, - { - "role": "slave", - "name": "S2MM", - "target": "hier_0_axis_interconnect_0_axis_interconnect_0_xbar:M01_AXIS" - } - ], - "vlnv": "xilinx.com:ip:axi_dma:7.1", - "memory-view": { - "M_AXI_MM2S": { - "pcie_0_axi_pcie_0": { - "BAR0": { - "highaddr": 4294967295, - "size": 4294967296, - "baseaddr": 0 - } - } - }, - "M_AXI_S2MM": { - "pcie_0_axi_pcie_0": { - "BAR0": { - "highaddr": 4294967295, - "size": 4294967296, - "baseaddr": 0 - } - } - } - }, - "irqs": { - "s2mm_introut": "pcie_0_axi_pcie_intc_0:3", - "mm2s_introut": "pcie_0_axi_pcie_intc_0:2" - } - }, - "pcie_0_axi_pcie_intc_0": { - "vlnv": "acs.eonerc.rwth-aachen.de:user:axi_pcie_intc:1.4" - }, - "pcie_0_axi_pcie_0": { - "vlnv": "xilinx.com:ip:axi_pcie:2.9", - "memory-view": { - "M_AXI": { - "timer_0_axi_timer_0": { - "Reg": { - "highaddr": 20479, - "size": 4096, - "baseaddr": 16384 - } - }, - "hier_0_axi_fifo_mm_s_0": { - "Mem0": { - "highaddr": 40959, - "size": 8192, - "baseaddr": 32768 - }, - "Mem1": { - "highaddr": 57343, - "size": 8192, - "baseaddr": 49152 - } - }, - "pcie_0_axi_pcie_0": { - "CTL0": { - "highaddr": 536870911, - "size": 268435456, - "baseaddr": 268435456 - } - }, - "hier_0_aurora_axis_0": { - "reg0": { - "highaddr": 12287, - "size": 4096, - "baseaddr": 8192 - } - }, - "pcie_0_axi_reset_0": { - "Reg": { - "highaddr": 32767, - "size": 4096, - "baseaddr": 28672 - } - }, - "hier_0_axis_interconnect_0_axis_interconnect_0_xbar": { - "Reg": { - "highaddr": 24575, - "size": 4096, - "baseaddr": 20480 - } - }, - "hier_0_axi_dma_axi_dma_0": { - "Reg": { - "highaddr": 16383, - "size": 4096, - "baseaddr": 12288 - } - }, - "pcie_0_axi_pcie_intc_0": { - "reg0": { - "highaddr": 8191, - "size": 4096, - "baseaddr": 4096 - } - } - } - }, - "pcie_bars": { - "BAR0": { - "translation": 0 - } - }, - "axi_bars": { - "BAR0": { - "highaddr": 4294967295, - "size": 4294967296, - "translation": 0, - "baseaddr": 0 - } - } - } -} diff --git a/fpga b/fpga index 0a225cd3e..05581018b 160000 --- a/fpga +++ b/fpga @@ -1 +1 @@ -Subproject commit 0a225cd3e15296372e71aae7983debdb4508d75d +Subproject commit 05581018b85fad8202a5604ce62c0d80d77a0eb5 diff --git a/include/villas/node.hpp b/include/villas/node.hpp index 77fc2d407..afecf46c0 100644 --- a/include/villas/node.hpp +++ b/include/villas/node.hpp @@ -411,14 +411,12 @@ public: return 0; } - bool - isInternal() const + bool isInternal() const { return getFlags() & (int) Flags::INTERNAL; } - bool - isHidden() const + bool isHidden() const { return isInternal() || getFlags() & (int) Flags::HIDDEN; } @@ -461,14 +459,14 @@ public: return vectorize; } - virtual std::string - getName() const + virtual + std::string getName() const { return name; } - virtual std::string - getDescription() const + virtual + std::string getDescription() const { return desc; } diff --git a/include/villas/nodes/fpga.hpp b/include/villas/nodes/fpga.hpp index 06486f6ca..d0e1ba693 100644 --- a/include/villas/nodes/fpga.hpp +++ b/include/villas/nodes/fpga.hpp @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include @@ -19,15 +20,12 @@ namespace villas { namespace node { -/* Forward declarations */ -class NodeCompat; - -using namespace villas; - #define FPGA_DMA_VLNV #define FPGA_AURORA_VLNV "acs.eonerc.rwth-aachen.de:user:aurora_axis:" -struct fpga_node { +class FpgaNode : public Node { + +protected: int irqFd; int coalesce; bool polling; @@ -37,41 +35,82 @@ struct fpga_node { std::shared_ptr dma; std::shared_ptr intf; - struct { - struct { - MemoryAccessor i; - MemoryAccessor f; - } accessor; - MemoryBlock::Ptr block; - } in, out; + std::unique_ptr blockRx; + std::unique_ptr blockTx; // Config only std::string cardName; std::string intfName; std::string dmaName; + +protected: + virtual + int _read(Sample *smps[], unsigned cnt); + + virtual + int _write(Sample *smps[], unsigned cnt); + +public: + FpgaNode(const std::string &name = ""); + + virtual + ~FpgaNode(); + + virtual + int parse(json_t *cfg, const uuid_t sn_uuid); + + virtual + const std::string & getDetails(); + + virtual + int check(); + + virtual + int prepare(); + + virtual + std::vector getPollFDs(); }; -int fpga_type_start(SuperNode *sn); -int fpga_type_stop(); +class FpgaNodeFactory : public NodeFactory { -int fpga_init(NodeCompat *n); +public: + using NodeFactory::NodeFactory; -int fpga_destroy(NodeCompat *n); + virtual + Node * make() + { + auto *n = new FpgaNode; -int fpga_parse(NodeCompat *n, json_t *json); + init(n); -char * fpga_print(NodeCompat *n); + return n; + } -int fpga_check(NodeCompat *n); + virtual + int getFlags() const + { + return (int) NodeFactory::Flags::SUPPORTS_READ | + (int) NodeFactory::Flags::SUPPORTS_WRITE | + (int) NodeFactory::Flags::SUPPORTS_POLL; + } -int fpga_prepare(NodeCompat *n); + virtual + std::string getName() const + { + return "fpga"; + } -int fpga_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt); + virtual + std::string getDescription() const + { + return "VILLASfpga"; + } -int fpga_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt); - -int fpga_poll_fds(NodeCompat *n, int fds[]); + virtual + int start(SuperNode *sn); +}; } /* namespace node */ } /* namespace villas */ diff --git a/include/villas/pool.hpp b/include/villas/pool.hpp index a32fe9d09..46f4dea31 100644 --- a/include/villas/pool.hpp +++ b/include/villas/pool.hpp @@ -33,7 +33,6 @@ struct Pool { struct CQueue queue; /**< The queue which is used to keep track of free blocks */ }; -#define INLINE static inline __attribute__((unused)) #define pool_buffer(p) ((char *) (p) + (p)->buffer_off) /** Initiazlize a pool @@ -56,29 +55,16 @@ int pool_destroy(struct Pool *p) __attribute__ ((warn_unused_result)); * This number can be smaller than the requested \p cnt blocks * in case the pool currently holds less than \p cnt blocks. */ -INLINE ssize_t pool_get_many(struct Pool *p, void *blocks[], size_t cnt) -{ - return queue_pull_many(&p->queue, blocks, cnt); -} +ssize_t pool_get_many(struct Pool *p, void *blocks[], size_t cnt); /** Push \p cnt values which are giving by the array values to the stack. */ -INLINE ssize_t pool_put_many(struct Pool *p, void *blocks[], size_t cnt) -{ - return queue_push_many(&p->queue, blocks, cnt); -} +ssize_t pool_put_many(struct Pool *p, void *blocks[], size_t cnt); /** Get a free memory block from pool. */ -INLINE void * pool_get(struct Pool *p) -{ - void *ptr; - return queue_pull(&p->queue, &ptr) == 1 ? ptr : nullptr; -} +void * pool_get(struct Pool *p); /** Release a memory block back to the pool. */ -INLINE int pool_put(struct Pool *p, void *buf) -{ - return queue_push(&p->queue, buf); -} +int pool_put(struct Pool *p, void *buf); } /* namespace node */ } /* namespace villas */ diff --git a/lib/config.cpp b/lib/config.cpp index 5a6d62d0e..2c2e8a699 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -353,7 +353,7 @@ json_t * Config::expandIncludes(json_t *in) if (!incl) incl = other; else if (json_is_object(incl) && json_is_object(other)) { - ret = json_object_update(incl, other); + ret = json_object_update_recursive(incl, other); if (ret) throw ConfigError(str, "Can not mix object and array-typed include files"); } diff --git a/lib/nodes/exec.cpp b/lib/nodes/exec.cpp index 6174aeb84..d5f11541b 100644 --- a/lib/nodes/exec.cpp +++ b/lib/nodes/exec.cpp @@ -181,13 +181,13 @@ int ExecNode::_write(struct Sample * smps[], unsigned cnt) const std::string & ExecNode::getDetails() { - std::string wd = working_dir; - if (wd.empty()) { - char buf[128]; - wd = getcwd(buf, sizeof(buf)); - } - if (details.empty()) { + std::string wd = working_dir; + if (wd.empty()) { + char buf[128]; + wd = getcwd(buf, sizeof(buf)); + } + details = fmt::format("exec={}, shell={}, flush={}, #environment={}, #arguments={}, working_dir={}", command, shell ? "yes" : "no", diff --git a/lib/nodes/fpga.cpp b/lib/nodes/fpga.cpp index 838ed971d..027b883f3 100644 --- a/lib/nodes/fpga.cpp +++ b/lib/nodes/fpga.cpp @@ -20,20 +20,19 @@ #include #include +#include #include #include #include using namespace villas; using namespace villas::node; +using namespace villas::fpga; using namespace villas::utils; -/* Forward declartions */ -static struct NodeCompatType p; - /* Global state */ -static fpga::PCIeCard::List cards; -static std::map dmaMap; +static fpga::Card::List cards; +static std::map dmaMap; static std::shared_ptr pciDevices; static std::shared_ptr vfioContainer; @@ -41,260 +40,166 @@ static std::shared_ptr vfioContainer; using namespace villas; using namespace villas::node; -int villas::node::fpga_type_start(SuperNode *sn) +FpgaNode::FpgaNode(const std::string &name) : + Node(name), + irqFd(-1), + coalesce(0), + polling(true) +{ } + +FpgaNode::~FpgaNode() +{ } + +int FpgaNode::parse(json_t *cfg, const uuid_t sn_uuid) { - vfioContainer = kernel::vfio::Container::create(); - pciDevices = std::make_shared(); - - // get the FPGA card plugin - auto pcieCardPlugin = plugin::registry->lookup("pcie"); - if (!pcieCardPlugin) - throw RuntimeError("No FPGA PCIe plugin found"); - - json_t *json = sn->getConfig(); - json_t *fpgas = json_object_get(json, "fpgas"); - if (!fpgas) - throw ConfigError(json, "node-config-fpgas", "No section 'fpgas' found in config"); - - // create all FPGA card instances using the corresponding plugin - auto pcieCards = pcieCardPlugin->make(fpgas, pciDevices, vfioContainer); - - cards.splice(cards.end(), pcieCards); - - return 0; -} - -int villas::node::fpga_type_stop() -{ - vfioContainer.reset(); // TODO: is this the proper way? - - return 0; -} - -int villas::node::fpga_init(NodeCompat *n) -{ - auto *f = n->getData(); - - f->coalesce = 0; - f->irqFd = -1; - f->polling = true; - - new (&f->cardName) std::string(); - new (&f->dmaName) std::string(); - new (&f->intfName) std::string(); - - new (&f->card) std::shared_ptr(); - - new (&f->dma) std::shared_ptr(); - new (&f->intf) std::shared_ptr(); - - new (&f->in.block) std::unique_ptr(); - new (&f->out.block) std::unique_ptr(); - - return 0; -} - -int villas::node::fpga_destroy(NodeCompat *n) -{ - auto *f = n->getData(); - - // using maiptr = MemoryAccessor; - // using mafptr = MemoryAccessor; - using mbptr = MemoryBlock::Ptr; - using cptr = std::shared_ptr; - using nptr = std::shared_ptr; - using dptr = std::shared_ptr; - using sptr = std::string; - - f->cardName.~sptr(); - f->dmaName.~sptr(); - f->intfName.~sptr(); - - f->card.~cptr(); - - f->dma.~dptr(); - f->intf.~nptr(); - - f->in.block.~mbptr(); - f->out.block.~mbptr(); - - return 0; -} - -int villas::node::fpga_parse(NodeCompat *n, json_t *json) -{ - int ret; - auto *f = n->getData(); + int ret = Node::parse(cfg, sn_uuid); + if (ret) + return ret; json_error_t err; const char *card = nullptr; const char *intf = nullptr; const char *dma = nullptr; - int polling = f->polling; + int poll = polling; - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s, s?: i, s?: b }", + ret = json_unpack_ex(cfg, &err, 0, "{ s?: s, s?: s, s?: s, s?: i, s?: b }", "card", &card, "interface", &intf, "dma", &dma, - "coalesce", &f->coalesce, + "coalesce", &coalesce, "polling", &polling ); if (ret) - throw ConfigError(json, err, "node-config-node-fpga"); + throw ConfigError(cfg, err, "node-config-fpga", "Failed to parse configuration of node {}", *this); if (card) - f->cardName = card; + cardName = card; if (intf) - f->intfName = intf; + intfName = intf; if (dma) - f->dmaName = dma; + dmaName = dma; - f->polling = polling; // cast int to bool + polling = poll; // cast int to bool return 0; } -char * villas::node::fpga_print(NodeCompat *n) +const std::string & FpgaNode::getDetails() { - auto *f = n->getData(); + if (details.empty()) { + auto &name = card ? card->name : cardName; - return strf("fpga=%s, dma=%s, if=%s, polling=%s, coalesce=%d", - f->card->name.c_str(), - f->dma->getInstanceName().c_str(), - f->polling ? "yes" : "no", - f->coalesce - ); + details = fmt::format("fpga={}, dma={}, if={}, polling={}, coalesce={}", + name, + dma->getInstanceName(), + polling ? "yes" : "no", + coalesce + ); + } + + return details; } -int villas::node::fpga_prepare(NodeCompat *n) +int FpgaNode::check() { - int ret; - auto *f = n->getData(); + return 0; +} - // Select first FPGA card - auto it = f->cardName.empty() +int FpgaNode::prepare() +{ + auto it = cardName.empty() ? cards.begin() - : std::find_if(cards.begin(), cards.end(), [f](const fpga::PCIeCard::Ptr &c) { - return c->name == f->cardName; + : std::find_if(cards.begin(), cards.end(), [this](const fpga::Card::Ptr &c) { + return c->name == cardName; }); if (it == cards.end()) - throw ConfigError(json_object_get(n->getConfig(), "fpga"), "node-config-node-fpga-card", "Invalid FPGA card name: {}", f->cardName); + throw ConfigError(json_object_get(config, "fpga"), "node-config-fpga-card", "Invalid FPGA card name: {}", cardName); - f->card = *it; + card = *it; - // Select interface IP core - auto intf = f->intfName.empty() - ? f->card->lookupIp(fpga::Vlnv(FPGA_AURORA_VLNV)) - : f->card->lookupIp(f->intfName); + auto intfCore = intfName.empty() + ? card->lookupIp(fpga::Vlnv(FPGA_AURORA_VLNV)) + : card->lookupIp(intfName); + if (!intfCore) + throw ConfigError(config, "node-config-fpga-interface", "There is no interface IP with the name: {}", intfName); + + intf = std::dynamic_pointer_cast(intfCore); if (!intf) - throw ConfigError(n->getConfig(), "node-config-node-fpga-interface", "There is no interface IP with the name: {}", f->intfName); - - f->intf = std::dynamic_pointer_cast(intf); - if (!f->intf) throw RuntimeError("The IP {} is not a interface", *intf); - // Select DMA IP core - auto dma = f->dmaName.empty() - ? f->card->lookupIp(fpga::Vlnv(FPGA_DMA_VLNV)) - : f->card->lookupIp(f->dmaName); - if (!dma) - throw ConfigError(n->getConfig(), "node-config-node-fpga-dma", "There is no DMA IP with the name: {}", f->dmaName); + auto dmaCore = dmaName.empty() + ? card->lookupIp(fpga::Vlnv(FPGA_DMA_VLNV)) + : card->lookupIp(dmaName); + if (!dmaCore) + throw ConfigError(config, "node-config-fpga-dma", "There is no DMA IP with the name: {}", dmaName); - f->dma = std::dynamic_pointer_cast(dma); - if (!f->dma) + dma = std::dynamic_pointer_cast(dmaCore); + if (!dma) throw RuntimeError("The IP {} is not a DMA controller", *dma); - ret = f->intf->connect(*(f->dma), true); + int ret = intf->connect(*(dma), true); if (ret) - throw RuntimeError("Failed to connect: {} -> {}", - *(f->intf), *(f->dma) - ); + throw RuntimeError("Failed to connect: {} -> {}", *(intf), *(dma)); auto &alloc = HostDmaRam::getAllocator(); - f->in.block = std::move(alloc.allocateBlock(0x100 / sizeof(int32_t))); - f->out.block = std::move(alloc.allocateBlock(0x100 / sizeof(int32_t))); + auto memRx = alloc.allocate(0x100 / sizeof(int32_t)); + auto memTx = alloc.allocate(0x100 / sizeof(int32_t)); - f->in.accessor.i = MemoryAccessor(*f->in.block); - f->in.accessor.f = MemoryAccessor(*f->in.block); + blockRx = std::unique_ptr(&memRx.getMemoryBlock()); + blockTx = std::unique_ptr(&memTx.getMemoryBlock()); - f->out.accessor.i = MemoryAccessor(*f->out.block); - f->out.accessor.f = MemoryAccessor(*f->out.block); + dma->makeAccesibleFromVA(*blockRx); + dma->makeAccesibleFromVA(*blockTx); - f->dma->makeAccesibleFromVA(*f->in.block); - f->dma->makeAccesibleFromVA(*f->out.block); + // Show some debugging infos + auto &mm = MemoryManager::get(); - f->dma->dump(); - f->intf->dump(); - MemoryManager::get().getGraph().dump(); + dma->dump(); + intf->dump(); + mm.getGraph().dump(); - return 0; + return Node::prepare(); } -int villas::node::fpga_read(NodeCompat *n, struct Sample * const smps[], unsigned cnt) +int FpgaNode::_read(Sample *smps[], unsigned cnt) { unsigned read; - auto *f = n->getData(); - struct Sample *smp = smps[0]; + Sample *smp = smps[0]; assert(cnt == 1); - f->dma->read(*f->in.block.get(), f->in.block->getSize()); // TODO: calc size - const size_t bytesRead = f->dma->readComplete(); + dma->read(*blockRx, blockRx->getSize()); // TODO: calc size + const size_t bytesRead = dma->readComplete(); read = bytesRead / sizeof(int32_t); - for (unsigned i = 0; i < MIN(read, smp->capacity); i++) { - auto sig = n->getInputSignals(false)->getByIndex(i); + auto mem = MemoryAccessor(*blockRx); - switch (sig->type) { - case SignalType::INTEGER: - smp->data[i].i = f->in.accessor.i[i]; - break; + for (unsigned i = 0; i < MIN(read, smp->capacity); i++) + smp->data[i].i = mem[i]; - case SignalType::FLOAT: - smp->data[i].f = f->in.accessor.f[i]; - break; - - default: {} - } - } - - smp->signals = n->getInputSignals(false); - smp->length = bytesRead / sizeof(uint32_t); - smp->flags = (int) SampleFlags::HAS_DATA; + smp->signals = in.signals; return read; } -int villas::node::fpga_write(NodeCompat *n, struct Sample * const smps[], unsigned cnt) +int FpgaNode::_write(Sample *smps[], unsigned cnt) { int written; - auto *f = n->getData(); - struct Sample *smp = smps[0]; + Sample *smp = smps[0]; assert(cnt == 1); - for (unsigned i = 0; i < smps[0]->length; i++) { - auto sig = smp->signals->getByIndex(i); + auto mem = MemoryAccessor(*blockTx); - switch (sig->type) { - case SignalType::INTEGER: - f->out.accessor.i[i] = smps[0]->data[i].i; - break; + for (unsigned i = 0; i < smps[0]->length; i++) + mem[i] = smps[0]->data[i].i; - case SignalType::FLOAT: - f->out.accessor.f[i] = smps[0]->data[i].f; - break; - - default: {} - } - } - - bool state = f->dma->write(*f->out.block.get(), smp->length * sizeof(int32_t)); + bool state = dma->write(*blockTx, smp->length * sizeof(int32_t)); if (!state) return -1; @@ -303,36 +208,37 @@ int villas::node::fpga_write(NodeCompat *n, struct Sample * const smps[], unsign return written; } -int villas::node::fpga_poll_fds(NodeCompat *n, int fds[]) +std::vector FpgaNode::getPollFDs() { - auto *f = n->getData(); + std::vector fds; - if (f->polling) - return 0; - else { - fds[0] = f->irqFd; + if (!polling) + fds.push_back(irqFd); - return 1; /* The number of file descriptors which have been set in fds */ - } + return fds; } -__attribute__((constructor(110))) -static void register_plugin() { - p.name = "fpga"; - p.description = "Communicate with VILLASfpga Xilinx FPGA boards"; - p.vectorize = 1; - p.size = sizeof(struct fpga_node); - p.type.start = fpga_type_start; - p.type.stop = fpga_type_stop; - p.init = fpga_init; - p.destroy = fpga_destroy; - p.prepare = fpga_prepare; - p.parse = fpga_parse; - p.print = fpga_print; - p.read = fpga_read; - p.write = fpga_write; - p.poll_fds = fpga_poll_fds; +int FpgaNodeFactory::start(SuperNode *sn) +{ + vfioContainer = std::make_shared(); + pciDevices = std::make_shared(); - static NodeCompatFactory ncp(&p); + // Get the FPGA card plugin + auto pcieCardPlugin = plugin::registry->lookup("pcie"); + if (!pcieCardPlugin) + throw RuntimeError("No FPGA PCIe plugin found"); + + json_t *json_cfg = sn->getConfig(); + json_t *json_fpgas = json_object_get(json_cfg, "fpgas"); + if (!json_fpgas) + throw ConfigError(json_cfg, "node-config-fpgas", "No section 'fpgas' found in config"); + + // Create all FPGA card instances using the corresponding plugin + auto piceCards = fpga::PCIeCardFactory::make(json_fpgas, pciDevices, vfioContainer); + + cards.splice(cards.end(), piceCards); + + return 0; } +static FpgaNodeFactory p; diff --git a/lib/nodes/rtp.cpp b/lib/nodes/rtp.cpp index 6718c28f7..f44eb1fab 100644 --- a/lib/nodes/rtp.cpp +++ b/lib/nodes/rtp.cpp @@ -15,6 +15,7 @@ #include extern "C" { + #include #include #include #include @@ -548,7 +549,7 @@ retry: mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); mbuf_set_pos(r->send_mb, RTP_HEADER_SIZE); /* Send dataset */ - ret = rtp_send(r->rs, &r->out.saddr_rtp, false, false, RTP_PACKET_TYPE, ts, r->send_mb); + ret = rtp_send(r->rs, &r->out.saddr_rtp, false, false, RTP_PACKET_TYPE, ts, 0, r->send_mb); if (ret) throw RuntimeError("Error from rtp_send, reason: {}", ret); @@ -564,22 +565,6 @@ int villas::node::rtp_poll_fds(NodeCompat *n, int fds[]) return 1; } -int villas::node::rtp_netem_fds(NodeCompat *n, int fds[]) -{ - auto *r = n->getData(); - - int m = 0; - struct udp_sock *rtp = (struct udp_sock *) rtp_sock(r->rs); - struct udp_sock *rtcp = (struct udp_sock *) rtcp_sock(r->rs); - - fds[m++] = udp_sock_fd(rtp, AF_INET); - - if (r->rtcp.enabled) - fds[m++] = udp_sock_fd(rtcp, AF_INET); - - return m; -} - __attribute__((constructor(110))) static void register_plugin() { p.name = "rtp"; @@ -602,5 +587,4 @@ static void register_plugin() { p.write = rtp_write; p.reverse = rtp_reverse; p.poll_fds = rtp_poll_fds; - p.netem_fds = rtp_netem_fds; } diff --git a/lib/pool.cpp b/lib/pool.cpp index 696693fd0..011101ea4 100644 --- a/lib/pool.cpp +++ b/lib/pool.cpp @@ -62,3 +62,24 @@ int villas::node::pool_destroy(struct Pool *p) return ret; } + +ssize_t villas::node::pool_get_many(struct Pool *p, void *blocks[], size_t cnt) +{ + return queue_pull_many(&p->queue, blocks, cnt); +} + +ssize_t villas::node::pool_put_many(struct Pool *p, void *blocks[], size_t cnt) +{ + return queue_push_many(&p->queue, blocks, cnt); +} + +void * villas::node::pool_get(struct Pool *p) +{ + void *ptr; + return queue_pull(&p->queue, &ptr) == 1 ? ptr : nullptr; +} + +int villas::node::pool_put(struct Pool *p, void *buf) +{ + return queue_push(&p->queue, buf); +} diff --git a/packaging/deps.sh b/packaging/deps.sh index dca16833e..c305755a6 100644 --- a/packaging/deps.sh +++ b/packaging/deps.sh @@ -16,21 +16,6 @@ MAKE_OPTS+="--jobs=${MAKE_THREADS}" git config --global http.postBuffer 524288000 git config --global core.compression 0 -if [ -n "${PACKAGE}" ]; then - TARGET="package" - CMAKE_OPTS+=" -DCPACK_GENERATOR=RPM" - - # Prepare rpmbuild dir - mkdir -p ~/rpmbuild/SOURCES - mkdir -p rpms - - dnf -y install \ - xmlto \ - systemd-devel -else - TARGET="install" -fi - DIR=$(mktemp -d) pushd ${DIR} @@ -42,22 +27,18 @@ if ! pkg-config "criterion >= 2.3.1" && \ mkdir -p Criterion/build pushd Criterion/build cmake ${CMAKE_OPTS} .. - if [ -z "${PACKAGE}" ]; then - make ${MAKE_OPTS} install - fi + make ${MAKE_OPTS} install popd fi # Build & Install libjansson -if ! pkg-config "jansson >= 2.7" && \ +if ! pkg-config "jansson >= 2.13" && \ [ -z "${SKIP_JANSSON}" ]; then git clone ${GIT_OPTS} --branch v2.14 https://github.com/akheron/jansson pushd jansson autoreconf -i ./configure ${CONFIGURE_OPTS} - if [ -z "${PACKAGE}" ]; then - make ${MAKE_OPTS} install - fi + make ${MAKE_OPTS} install popd fi @@ -71,10 +52,8 @@ if ! ( pkg-config "lua >= 5.1" || \ ) && [ -z "${SKIP_LUA}" ]; then wget http://www.lua.org/ftp/lua-5.3.6.tar.gz -O - | tar -xz pushd lua-5.3.6 - if [ -z "${PACKAGE}" ]; then - make ${MAKE_OPTS} MYCFLAGS=-fPIC linux - make ${MAKE_OPTS} MYCFLAGS=-fPIC install - fi + make ${MAKE_OPTS} MYCFLAGS=-fPIC linux + make ${MAKE_OPTS} MYCFLAGS=-fPIC install popd fi @@ -89,7 +68,7 @@ if ! pkg-config "libmosquitto >= 1.4.15" && \ -DWITH_APPS=OFF \ -DDOCUMENTATION=OFF \ ${CMAKE_OPTS} .. - make ${MAKE_OPTS} ${TARGET} + make ${MAKE_OPTS} install popd fi @@ -100,7 +79,7 @@ if ! pkg-config "librabbitmq >= 0.8.0" && \ mkdir -p rabbitmq-c/build pushd rabbitmq-c/build cmake ${CMAKE_OPTS} .. - make ${MAKE_OPTS} ${TARGET} + make ${MAKE_OPTS} install popd fi @@ -114,7 +93,7 @@ if ! pkg-config "libzmq >= 2.2.0" && \ -DZMQ_BUILD_TESTS=OFF \ -DENABLE_CPACK=OFF \ ${CMAKE_OPTS} .. - make ${MAKE_OPTS} ${TARGET} + make ${MAKE_OPTS} install popd fi @@ -124,13 +103,7 @@ if [ -z "${SKIP_ETHERLAB}" ]; then pushd ethercat ./bootstrap ./configure --enable-userlib=yes --enable-kernel=no ${CONFIGURE_OPTS} - if [ -z "${PACKAGE}" ]; then - make ${MAKE_OPTS} ${TARGET} - else - wget https://etherlab.org/download/ethercat/ethercat-1.5.2.tar.bz2 - cp ethercat-1.5.2.tar.bz2 ~/rpmbuild/SOURCES - rpmbuild -ba ethercat.spec - fi + make ${MAKE_OPTS} install popd fi @@ -141,10 +114,7 @@ if ! pkg-config "libiec61850 >= 1.3.1" && \ mkdir -p libiec61850/build pushd libiec61850/build cmake ${CMAKE_OPTS} .. - make ${MAKE_OPTS} ${TARGET} - if [ -n "${PACKAGE}" ]; then - cp libiec61850/build/*.rpm rpms - fi + make ${MAKE_OPTS} install popd fi @@ -155,10 +125,7 @@ if ! pkg-config "lib60870 >= 2.3.1" && \ mkdir -p lib60870/build pushd lib60870/build cmake ${CMAKE_OPTS} ../lib60870-C - make ${MAKE_OPTS} ${TARGET} - if [ -n "${PACKAGE}" ]; then - cp lib60870/build/*.rpm rpms - fi + make ${MAKE_OPTS} install popd fi @@ -171,7 +138,7 @@ if ! pkg-config "rdkafka >= 1.5.0" && \ cmake -DRDKAFKA_BUILD_TESTS=OFF \ -DRDKAFKA_BUILD_EXAMPLES=OFF \ ${CMAKE_OPTS} .. - make ${MAKE_OPTS} ${TARGET} + make ${MAKE_OPTS} install popd fi @@ -183,7 +150,7 @@ if ! ( pkg-config "libcgraph >= 2.30" && \ mkdir -p graphviz/build pushd graphviz/build cmake ${CMAKE_OPTS} .. - make ${MAKE_OPTS} ${TARGET} + make ${MAKE_OPTS} install popd fi @@ -196,13 +163,7 @@ if ! pkg-config "libuldaq >= 1.2.0" && \ ./configure \ --disable-examples \ ${CONFIGURE_OPTS} - if [ -z "${PACKAGE}" ]; then - make ${MAKE_OPTS} install - else - make dist - cp fedora/uldaq_ldconfig.patch libuldaq-1.2.0.tar.gz ~/rpmbuild/SOURCES - rpmbuild -ba fedora/uldaq.spec - fi + make ${MAKE_OPTS} install popd fi @@ -216,9 +177,7 @@ if ! ( pkg-config "libnl-3.0 >= 3.2.25" && \ ./configure \ --enable-cli=no \ ${CONFIGURE_OPTS} - if [ -z "${PACKAGE}" ]; then - make ${MAKE_OPTS} install - fi + make ${MAKE_OPTS} install popd fi @@ -232,9 +191,7 @@ if ! pkg-config "libconfig >= 1.4.9" && \ --disable-tests \ --disable-examples \ --disable-doc - if [ -z "${PACKAGE}" ]; then - make ${MAKE_OPTS} install - fi + make ${MAKE_OPTS} install popd fi @@ -247,28 +204,16 @@ if ! pkg-config "comedilib >= 0.11.0" && \ ./configure \ --disable-docbook \ ${CONFIGURE_OPTS} - if [ -z "${PACKAGE}" ]; then - make ${MAKE_OPTS} install - else - touch doc/pdf/comedilib.pdf # skip build of PDF which is broken.. - make dist - cp comedilib-0.12.0.tar.gz ~/rpmbuild/SOURCES - rpmbuild -ba comedilib.spec - fi + make ${MAKE_OPTS} install popd fi # Build & Install libre -if ! pkg-config "libre >= 0.5.6" && \ +if ! pkg-config "libre >= 2.9.0" && \ [ -z "${SKIP_LIBRE}" ]; then - git clone ${GIT_OPTS} --branch v0.6.1 https://github.com/creytiv/re.git + git clone ${GIT_OPTS} --branch v2.9.0 https://github.com/baresip/re.git pushd re - if [ -z "${PACKAGE}" ]; then - make ${MAKE_OPTS} install - else - tar --transform 's|^\.|re-0.6.1|' -czvf ~/rpmbuild/SOURCES/re-0.6.1.tar.gz . - rpmbuild -ba rpm/re.spec - fi + make ${MAKE_OPTS} install popd fi @@ -284,9 +229,7 @@ if ! pkg-config "nanomsg >= 1.0.0" && \ -DNN_ENABLE_DOC=OFF \ -DNN_ENABLE_COVERAGE=OFF \ ${CMAKE_OPTS} .. - if [ -z "${PACKAGE}" ]; then - make ${MAKE_OPTS} install - fi + make ${MAKE_OPTS} install popd fi @@ -297,9 +240,7 @@ if ! pkg-config "libxil >= 1.0.0" && \ mkdir -p libxil/build pushd libxil/build cmake ${CMAKE_OPTS} .. - if [ -z "${PACKAGE}" ]; then - make ${MAKE_OPTS} install - fi + make ${MAKE_OPTS} install popd fi @@ -312,7 +253,7 @@ if ! pkg-config "hiredis>1.0.0" && \ cmake -DDISABLE_TESTS=ON \ -DENABLE_SSL=ON \ ${CMAKE_OPTS} .. - make ${MAKE_OPTS} ${TARGET} + make ${MAKE_OPTS} install popd fi @@ -329,7 +270,7 @@ if [ -z "${SKIP_REDISPP}" -a -z "${SKIP_REDIS}" ]; then -DREDIS_PLUS_PLUS_BUILD_STATIC=OFF \ -DREDIS_PLUS_PLUS_CXX_STANDARD=17 \ ${REDISPP_CMAKE_OPTS} ${CMAKE_OPTS} .. - make ${MAKE_OPTS} ${TARGET} VERBOSE=1 + make ${MAKE_OPTS} install VERBOSE=1 popd fi @@ -342,10 +283,7 @@ if ! pkg-config "fmt >= 6.1.2" && \ cmake -DBUILD_SHARED_LIBS=1 \ -DFMT_TEST=OFF \ ${CMAKE_OPTS} .. - make ${MAKE_OPTS} ${TARGET} - if [ -n "${PACKAGE}" ]; then - cp fmt/build/*.rpm rpms - fi + make ${MAKE_OPTS} install popd fi @@ -360,10 +298,7 @@ if ! pkg-config "spdlog >= 1.8.2" && \ -DSPDLOG_BUILD_SHARED=ON \ -DSPDLOG_BUILD_TESTS=OFF \ ${CMAKE_OPTS} .. - make ${MAKE_OPTS} ${TARGET} - if [ -n "${PACKAGE}" ]; then - cp spdlog/build/*.rpm rpms - fi + make ${MAKE_OPTS} install popd fi @@ -378,18 +313,14 @@ if ! pkg-config "libwebsockets >= 3.1.0" && \ -DLWS_WITHOUT_EXTENSIONS=OFF \ -DLWS_WITH_SERVER_STATUS=ON \ ${CMAKE_OPTS} .. - make ${MAKE_OPTS} ${TARGET} + make ${MAKE_OPTS} install popd fi -if [ -n "${PACKAGE}" ]; then - cp ~/rpmbuild/RPMS/x86_64/*.rpm rpms -fi - popd rm -rf ${DIR} # Update linker cache -if [ -z "${PACKAGE}" -a -z "${SKIP_LDCONFIG}" ]; then +if [ -z "${SKIP_LDCONFIG}" ]; then ldconfig fi diff --git a/tests/unit/queue.cpp b/tests/unit/queue.cpp index 9f37e8b07..422703b3d 100644 --- a/tests/unit/queue.cpp +++ b/tests/unit/queue.cpp @@ -79,7 +79,7 @@ static void * producer(void *ctx) /* Wait for global start signal */ while (p->start == 0) - pthread_yield(); + sched_yield(); /* Wait for a random time */ for (size_t i = 0; i != nops; i += 1) @@ -89,7 +89,7 @@ static void * producer(void *ctx) for (intptr_t count = 0; count < p->iter_count; count++) { do { ret = queue_push(&p->queue, (void *) count); - pthread_yield(); + sched_yield(); } while (ret != 1); } @@ -106,7 +106,7 @@ static void * consumer(void *ctx) /* Wait for global start signal */ while (p->start == 0) - pthread_yield(); + sched_yield(); /* Wait for a random time */ for (size_t i = 0; i != nops; i += 1) @@ -138,7 +138,7 @@ void * producer_consumer(void *ctx) /* Wait for global start signal */ while (p->start == 0) - pthread_yield(); + sched_yield(); /* Wait for a random time */ for (size_t i = 0; i != nops; i += 1) @@ -150,13 +150,13 @@ void * producer_consumer(void *ctx) for (intptr_t i = 0; i < p->batch_size; i++) { void *ptr = (void *) (iter * p->batch_size + i); while (!queue_push(&p->queue, ptr)) - pthread_yield(); /* queue full, let other threads proceed */ + sched_yield(); /* queue full, let other threads proceed */ } for (intptr_t i = 0; i < p->batch_size; i++) { void *ptr; while (!queue_pull(&p->queue, &ptr)) - pthread_yield(); /* queue empty, let other threads proceed */ + sched_yield(); /* queue empty, let other threads proceed */ } } @@ -172,7 +172,7 @@ void * producer_consumer_many(void *ctx) /* Wait for global start signal */ while (p->start == 0) - pthread_yield(); + sched_yield(); /* Wait for a random time */ for (size_t i = 0; i != nops; i += 1) @@ -190,14 +190,14 @@ void * producer_consumer_many(void *ctx) do { pushed += queue_push_many(&p->queue, &ptrs[pushed], p->batch_size - pushed); if (pushed != p->batch_size) - pthread_yield(); /* queue full, let other threads proceed */ + sched_yield(); /* queue full, let other threads proceed */ } while (pushed < p->batch_size); int pulled = 0; do { pulled += queue_pull_many(&p->queue, &ptrs[pulled], p->batch_size - pulled); if (pulled != p->batch_size) - pthread_yield(); /* queue empty, let other threads proceed */ + sched_yield(); /* queue empty, let other threads proceed */ } while (pulled < p->batch_size); }