diff --git a/fpga/include/villas/fpga/card.h b/fpga/include/villas/fpga/card.h deleted file mode 100644 index f352fb081..000000000 --- a/fpga/include/villas/fpga/card.h +++ /dev/null @@ -1,103 +0,0 @@ -/** FPGA card - * - * This class represents a FPGA device. - * - * @file - * @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 . - *********************************************************************************/ - -/** @addtogroup fpga VILLASfpga - * @{ - */ - -#pragma once - -#include - -#include "common.h" -#include "kernel/pci.h" -#include "kernel/vfio.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Forward declarations */ -struct fpga_ip; -struct vfio_container; - -struct fpga_card { - char *name; /**< The name of the FPGA card */ - - enum state state; /**< The state of this FPGA card. */ - - struct pci *pci; - struct pci_device filter; /**< Filter for PCI device. */ - - struct vfio_container *vfio_container; - struct vfio_device vfio_device; /**< VFIO device handle. */ - - int do_reset; /**< Reset VILLASfpga during startup? */ - int affinity; /**< Affinity for MSI interrupts */ - - struct list ips; /**< List of IP components on FPGA. */ - - char *map; /**< PCI BAR0 mapping for register access */ - - size_t maplen; - size_t dmalen; - - /* Some IP cores are special and referenced here */ - struct fpga_ip *intc; - struct fpga_ip *reset; - struct fpga_ip *sw; -}; - -/** Initialize FPGA card and its IP components. */ -int fpga_card_init(struct fpga_card *c, struct pci *pci, struct vfio_container *vc); - -/** Parse configuration of FPGA card including IP cores from config. */ -int fpga_card_parse(struct fpga_card *c, json_t *cfg, const char *name); - -int fpga_card_parse_list(struct list *l, json_t *cfg); - -/** Check if the FPGA card configuration is plausible. */ -int fpga_card_check(struct fpga_card *c); - -/** Start FPGA card. */ -int fpga_card_start(struct fpga_card *c); - -/** Stop FPGA card. */ -int fpga_card_stop(struct fpga_card *c); - -/** Destroy FPGA card. */ -int fpga_card_destroy(struct fpga_card *c); - -/** Dump details of FPGA card to stdout. */ -void fpga_card_dump(struct fpga_card *c); - -/** Reset the FPGA to a known state */ -int fpga_card_reset(struct fpga_card *c); - -#ifdef __cplusplus -} -#endif - -/** @} */ diff --git a/fpga/include/villas/fpga/ip.h b/fpga/include/villas/fpga/ip.h deleted file mode 100644 index b6723043d..000000000 --- a/fpga/include/villas/fpga/ip.h +++ /dev/null @@ -1,126 +0,0 @@ -/** Interlectual Property component. - * - * This class represents a module within the FPGA. - * - * @file - * @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 . - *********************************************************************************/ - -/** @addtogroup fpga VILLASfpga - * @{ - */ - -#pragma once - -#include - -#include "common.h" - -#include "fpga/vlnv.h" - -#include "fpga/ips/dma.h" -#include "fpga/ips/switch.h" -#include "fpga/ips/fifo.h" -#include "fpga/ips/rtds_axis.h" -#include "fpga/ips/timer.h" -#include "fpga/ips/model.h" -#include "fpga/ips/dft.h" -#include "fpga/ips/intc.h" - -#ifdef __cplusplus -extern "C" { -#endif - -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. */ -}; - -struct fpga_ip_type { - struct fpga_vlnv vlnv; - - enum fpga_ip_types type; - - int (*init)(struct fpga_ip *c); - int (*parse)(struct fpga_ip *c, json_t *cfg); - int (*check)(struct fpga_ip *c); - int (*start)(struct fpga_ip *c); - int (*stop)(struct fpga_ip *c); - int (*destroy)(struct fpga_ip *c); - int (*reset)(struct fpga_ip *c); - void (*dump)(struct fpga_ip *c); - - size_t size; /**< Amount of memory which should be reserved for struct fpga_ip::_vd */ -}; - -struct fpga_ip { - char *name; /**< Name of the FPGA IP component. */ - struct fpga_vlnv vlnv; /**< The Vendor, Library, Name, Version tag of the FPGA IP component. */ - - enum state state; /**< The current state of the FPGA IP component. */ - - struct fpga_ip_type *_vt; /**< Vtable containing FPGA IP type function pointers. */ - void *_vd; /**< Virtual data (used by struct fpga_ip::_vt functions) */ - - uintptr_t baseaddr; /**< The baseadress of this FPGA IP component */ - uintptr_t baseaddr_axi4; /**< Used by AXI4 FIFO DM */ - - int port; /**< The port of the AXI4-Stream switch to which this FPGA IP component is connected. */ - int irq; /**< The interrupt number of the FPGA IP component. */ - - struct fpga_card *card; /**< The FPGA to which this IP instance belongs to. */ -}; - -/** Initialize IP core. */ -int fpga_ip_init(struct fpga_ip *c, struct fpga_ip_type *vt); - -/** Parse IP core configuration from configuration file */ -int fpga_ip_parse(struct fpga_ip *c, json_t *cfg, const char *name); - -/** Check configuration of IP core. */ -int fpga_ip_check(struct fpga_ip *c); - -/** Start IP core. */ -int fpga_ip_start(struct fpga_ip *c); - -/** Stop IP core. */ -int fpga_ip_stop(struct fpga_ip *c); - -/** Release dynamic memory allocated by this IP core. */ -int fpga_ip_destroy(struct fpga_ip *c); - -/** Dump details about this IP core to stdout. */ -void fpga_ip_dump(struct fpga_ip *c); - -/** Reset IP component to its initial state. */ -int fpga_ip_reset(struct fpga_ip *c); - -/** Find a registered FPGA IP core type with the given VLNV identifier. */ -struct fpga_ip_type * fpga_ip_type_lookup(const char *vstr); - -#ifdef __cplusplus -} -#endif - -/** @} */ diff --git a/fpga/include/villas/fpga/ips/dma.h b/fpga/include/villas/fpga/ips/dma.h deleted file mode 100644 index 7a13fb903..000000000 --- a/fpga/include/villas/fpga/ips/dma.h +++ /dev/null @@ -1,88 +0,0 @@ -/** DMA related helper functions. - * - * These functions present a simpler interface to Xilinx' DMA driver (XAxiDma_*). - * - * @file - * @author Steffen Vogel - * @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 -#include -#include - -#include - -/* Forward declarations */ -struct fpga_ip; - -#define FPGA_DMA_BASEADDR 0x00000000 -#define FPGA_DMA_BOUNDARY 0x1000 -#define FPGA_DMA_BD_OFFSET 0xC0000000 -#define FPGA_DMA_BD_SIZE (32 << 20) // 32 MB - -#define XAXIDMA_SR_SGINCL_MASK 0x00000008 - -struct dma_mem { - char *base_virt; - char *base_phys; - size_t len; -}; - -struct dma { - XAxiDma inst; - - struct dma_mem bd; -}; - -struct ip; - -int dma_mem_split(struct dma_mem *o, struct dma_mem *a, struct dma_mem *b); - -int dma_alloc(struct fpga_ip *c, struct dma_mem *mem, size_t len, int flags); -int dma_free(struct fpga_ip *c, struct dma_mem *mem); - -int dma_write(struct fpga_ip *c, char *buf, size_t len); -int dma_read(struct fpga_ip *c, char *buf, size_t len); -int dma_read_complete(struct fpga_ip *c, char **buf, size_t *len); -int dma_write_complete(struct fpga_ip *c, char **buf, size_t *len); - -int dma_sg_write(struct fpga_ip *c, char *buf, size_t len); -int dma_sg_read(struct fpga_ip *c, char *buf, size_t len); - -int dma_sg_write_complete(struct fpga_ip *c, char **buf, size_t *len); -int dma_sg_read_complete(struct fpga_ip *c, char **buf, size_t *len); - -int dma_simple_read(struct fpga_ip *c, char *buf, size_t len); -int dma_simple_write(struct fpga_ip *c, char *buf, size_t len); - -int dma_simple_read_complete(struct fpga_ip *c, char **buf, size_t *len); -int dma_simple_write_complete(struct fpga_ip *c, char **buf, size_t *len); - -int dma_ping_pong(struct fpga_ip *c, char *src, char *dst, size_t len); - -int dma_start(struct fpga_ip *c); - -/** @} */ diff --git a/fpga/include/villas/fpga/ips/fifo.h b/fpga/include/villas/fpga/ips/fifo.h deleted file mode 100644 index 4724c1ac5..000000000 --- a/fpga/include/villas/fpga/ips/fifo.h +++ /dev/null @@ -1,52 +0,0 @@ -/** FIFO related helper functions - * - * These functions present a simpler interface to Xilinx' FIFO driver (XLlFifo_*) - * - * @file - * @author Steffen Vogel - * @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 - -#include -#include - -struct fifo { - XLlFifo inst; - - uint32_t baseaddr_axi4; -}; - -/* Forward declarations */ -struct ip; - -int fifo_start(struct fpga_ip *c); - -ssize_t fifo_write(struct fpga_ip *c, char *buf, size_t len); - -ssize_t fifo_read(struct fpga_ip *c, char *buf, size_t len); - -/** @} */ diff --git a/fpga/include/villas/fpga/ips/intc.h b/fpga/include/villas/fpga/ips/intc.h deleted file mode 100644 index bb7d44739..000000000 --- a/fpga/include/villas/fpga/ips/intc.h +++ /dev/null @@ -1,56 +0,0 @@ -/** AXI-PCIe Interrupt controller - * - * @file - * @author Steffen Vogel - * @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 - -enum intc_flags { - INTC_ENABLED = (1 << 0), - INTC_POLLING = (1 << 1) -}; - -struct intc { - int num_irqs; /**< Number of available MSI vectors */ - - int efds[32]; /**< Event FDs */ - int nos[32]; /**< Interrupt numbers from /proc/interrupts */ - - int flags[32]; /**< Mask of intc_flags */ -}; - -int intc_init(struct fpga_ip *c); - -int intc_destroy(struct fpga_ip *c); - -int intc_enable(struct fpga_ip *c, uint32_t mask, int poll); - -int intc_disable(struct fpga_ip *c, uint32_t mask); - -uint64_t intc_wait(struct fpga_ip *c, int irq); - -/** @} */ diff --git a/fpga/include/villas/fpga/ips/switch.h b/fpga/include/villas/fpga/ips/switch.h deleted file mode 100644 index 7fcf08fa6..000000000 --- a/fpga/include/villas/fpga/ips/switch.h +++ /dev/null @@ -1,67 +0,0 @@ -/** AXI Stream interconnect related helper functions - * - * These functions present a simpler interface to Xilinx' AXI Stream switch driver (XAxis_Switch_*) - * - * @file - * @author Steffen Vogel - * @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 -#include - -#include "list.h" - -/* Forward declarations */ -struct ip; - -struct sw_path { - const char *in; - const char *out; -}; - -struct sw { - XAxis_Switch inst; - - int num_ports; - struct list paths; -}; - -struct ip; - -int switch_start(struct fpga_ip *c); - -/** Initialize paths which have been parsed by switch_parse() */ -int switch_init_paths(struct fpga_ip *c); - -int switch_destroy(struct fpga_ip *c); - -int switch_parse(struct fpga_ip *c, json_t *cfg); - -int switch_connect(struct fpga_ip *c, struct fpga_ip *mi, struct fpga_ip *si); - -int switch_disconnect(struct fpga_ip *c, struct fpga_ip *mi, struct fpga_ip *si); - -/** @} */ diff --git a/fpga/include/villas/fpga/ips/timer.h b/fpga/include/villas/fpga/ips/timer.h deleted file mode 100644 index 31fac741e..000000000 --- a/fpga/include/villas/fpga/ips/timer.h +++ /dev/null @@ -1,43 +0,0 @@ -/** Timer related helper functions - * - * These functions present a simpler interface to Xilinx' Timer Counter driver (XTmrCtr_*) - * - * @file - * @author Steffen Vogel - * @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 - -/* Forward declarations */ -struct fpga_ip; - -struct timer { - XTmrCtr inst; -}; - -int timer_start(struct fpga_ip *c); - -/** @} */ diff --git a/fpga/include/villas/fpga/vlnv.h b/fpga/include/villas/fpga/vlnv.h deleted file mode 100644 index 2de8bbbcb..000000000 --- a/fpga/include/villas/fpga/vlnv.h +++ /dev/null @@ -1,61 +0,0 @@ -/** Vendor, Library, Name, Version (VLNV) tag. - * - * @file - * @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 . - *********************************************************************************/ - -/** @addtogroup fpga VILLASfpga - * @{ - */ - -#ifndef _FPGA_VLNV_H_ -#define _FPGA_VLNV_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Forward declarations */ -struct list; - -struct fpga_vlnv { - char *vendor; - char *library; - char *name; - char *version; -}; - -/** Return the first IP block in list \p l which matches the VLNV */ -struct fpga_ip * fpga_vlnv_lookup(struct list *l, struct fpga_vlnv *v); - -/** Check if IP block \p c matched VLNV. */ -int fpga_vlnv_cmp(struct fpga_vlnv *a, struct fpga_vlnv *b); - -/** Tokenizes VLNV \p vlnv and stores it into \p c */ -int fpga_vlnv_parse(struct fpga_vlnv *c, const char *vlnv); - -/** Release memory allocated by fpga_vlnv_parse(). */ -int fpga_vlnv_destroy(struct fpga_vlnv *v); - -#ifdef __cplusplus -} -#endif - -#endif /** _FPGA_VLNV_H_ @} */ diff --git a/fpga/include/villas/plugin.h b/fpga/include/villas/plugin.h deleted file mode 100644 index 8c915b573..000000000 --- a/fpga/include/villas/plugin.h +++ /dev/null @@ -1,82 +0,0 @@ -/** Loadable / plugin support. - * - * @file - * @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 . - *********************************************************************************/ - -#pragma once - -#include "utils.h" -#include "fpga/ip.h" - -/** @todo This is ugly as hell and broken on OS X / Clang anyway. */ -#define REGISTER_PLUGIN(p) \ -__attribute__((constructor(110))) static void UNIQUE(__ctor)() {\ - if (plugins.state == STATE_DESTROYED) \ - list_init(&plugins); \ - list_push(&plugins, p); \ -} \ -__attribute__((destructor(110))) static void UNIQUE(__dtor)() { \ - if (plugins.state != STATE_DESTROYED) \ - list_remove(&plugins, p); \ -} - -extern struct list plugins; - -enum plugin_type { - PLUGIN_TYPE_FPGA_IP, -}; - -struct plugin { - const char *name; - const char *description; - void *handle; - char *path; - - enum plugin_type type; - - enum state state; - - int (*load)(struct plugin *p); - int (*unload)(struct plugin *p); - - struct fpga_ip_type ip; -}; - -/** Return a pointer to the plugin structure */ -#define plugin(vt) ((struct plugin *) ((char *) (vt) - offsetof(struct plugin, api))) - -#define plugin_name(vt) plugin(vt)->name -#define plugin_description(vt) plugin(vt)->description - -int plugin_init(struct plugin *p); - -int plugin_destroy(struct plugin *p); - -int plugin_parse(struct plugin *p, json_t *cfg); - -int plugin_load(struct plugin *p); - -int plugin_unload(struct plugin *p); - -void plugin_dump(enum plugin_type type); - -/** Find registered and loaded plugin with given name and type. */ -struct plugin * plugin_lookup(enum plugin_type type, const char *name); diff --git a/fpga/lib/card.c b/fpga/lib/card.c deleted file mode 100644 index 651ab76ac..000000000 --- a/fpga/lib/card.c +++ /dev/null @@ -1,315 +0,0 @@ -/** FPGA card. - * - * @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 "config.h" -#include "log.h" -#include "log_config.h" -#include "list.h" -#include "utils.h" - -#include "kernel/pci.h" -#include "kernel/vfio.h" - -#include "fpga/ip.h" -#include "fpga/card.h" - -int fpga_card_init(struct fpga_card *c, struct pci *pci, struct vfio_container *vc) -{ - assert(c->state == STATE_DESTROYED); - - c->vfio_container = vc; - c->pci = pci; - - list_init(&c->ips); - - /* Default values */ - c->filter.id.vendor = FPGA_PCI_VID_XILINX; - c->filter.id.device = FPGA_PCI_PID_VFPGA; - - c->affinity = 0; - c->do_reset = 0; - - c->state = STATE_INITIALIZED; - - return 0; -} - -int fpga_card_parse(struct fpga_card *c, json_t *cfg, const char *name) -{ - int ret; - - json_t *json_ips; - json_t *json_slot = NULL; - json_t *json_id = NULL; - json_error_t err; - - c->name = strdup(name); - - ret = json_unpack_ex(cfg, &err, 0, "{ s?: i, s?: b, s?: o, s?: o, s: o }", - "affinity", &c->affinity, - "do_reset", &c->do_reset, - "slot", &json_slot, - "id", &json_id, - "ips", &json_ips - ); - if (ret) - jerror(&err, "Failed to parse FPGA vard configuration"); - - if (json_slot) { - const char *err, *slot; - - slot = json_string_value(json_slot); - if (slot) { - ret = pci_device_parse_slot(&c->filter, slot, &err); - if (ret) - error("Failed to parse PCI slot: %s", err); - } - else - error("PCI slot must be a string"); - } - - if (json_id) { - const char *err, *id; - - id = json_string_value(json_id); - if (id) { - ret = pci_device_parse_id(&c->filter, (char*) id, &err); - if (ret) - error("Failed to parse PCI id: %s", err); - } - else - error("PCI ID must be a string"); - } - - if (!json_is_object(json_ips)) - error("FPGA card IPs section must be an object"); - - const char *name_ip; - json_t *json_ip; - json_object_foreach(json_ips, name_ip, json_ip) { - const char *vlnv; - - struct fpga_ip_type *vt; - struct fpga_ip *ip = (struct fpga_ip *) alloc(sizeof(struct fpga_ip)); - - ip->card = c; - - ret = json_unpack_ex(json_ip, &err, 0, "{ s: s }", "vlnv", &vlnv); - if (ret) - error("Failed to parse FPGA IP '%s' of card '%s'", name_ip, name); - - vt = fpga_ip_type_lookup(vlnv); - if (!vt) - error("FPGA IP core VLNV identifier '%s' is invalid", vlnv); - - ret = fpga_ip_init(ip, vt); - if (ret) - error("Failed to initalize FPGA IP core"); - - ret = fpga_ip_parse(ip, json_ip, name_ip); - if (ret) - error("Failed to parse FPGA IP core"); - - list_push(&c->ips, ip); - } - - c->state = STATE_PARSED; - - return 0; -} - -int fpga_card_parse_list(struct list *cards, json_t *cfg) -{ - int ret; - - if (!json_is_object(cfg)) - error("FPGA card configuration section must be a JSON object"); - - const char *name; - json_t *json_fpga; - json_object_foreach(cfg, name, json_fpga) { - struct fpga_card *c = (struct fpga_card *) alloc(sizeof(struct fpga_card)); - - ret = fpga_card_parse(c, json_fpga, name); - if (ret) - error("Failed to parse FPGA card configuration"); - - list_push(cards, c); - } - - return 0; -} - -int fpga_card_start(struct fpga_card *c) -{ - int ret; - - struct pci_device *pdev; - - assert(c->state == STATE_INITIALIZED); - - /* Search for FPGA card */ - pdev = pci_lookup_device(c->pci, &c->filter); - if (!pdev) - error("Failed to find PCI device"); - - /* Attach PCIe card to VFIO container */ - ret = vfio_pci_attach(&c->vfio_device, c->vfio_container, pdev); - if (ret) - error("Failed to attach VFIO device"); - - /* Map PCIe BAR */ - c->map = vfio_map_region(&c->vfio_device, VFIO_PCI_BAR0_REGION_INDEX); - if (c->map == MAP_FAILED) - serror("Failed to mmap() BAR0"); - - /* Enable memory access and PCI bus mastering for DMA */ - ret = vfio_pci_enable(&c->vfio_device); - if (ret) - serror("Failed to enable PCI device"); - - /* Reset system? */ - if (c->do_reset) { - /* Reset / detect PCI device */ - ret = vfio_pci_reset(&c->vfio_device); - if (ret) - serror("Failed to reset PCI device"); - - ret = fpga_card_reset(c); - if (ret) - error("Failed to reset FGPA card"); - } - - /* Initialize IP cores */ - for (size_t j = 0; j < list_length(&c->ips); j++) { - struct fpga_ip *i = (struct fpga_ip *) list_at(&c->ips, j); - - ret = fpga_ip_start(i); - if (ret) - error("Failed to initalize FPGA IP core: %s (%u)", i->name, ret); - } - - c->state = STATE_STARTED; - - return 0; -} - -int fpga_card_stop(struct fpga_card *c) -{ - int ret; - - assert(c->state == STATE_STOPPED); - - for (size_t j = 0; j < list_length(&c->ips); j++) { - struct fpga_ip *i = (struct fpga_ip *) list_at(&c->ips, j); - - ret = fpga_ip_stop(i); - if (ret) - error("Failed to stop FPGA IP core: %s (%u)", i->name, ret); - } - - c->state = STATE_STOPPED; - - return 0; -} - -void fpga_card_dump(struct fpga_card *c) -{ - info("VILLASfpga card:"); - { INDENT - info("Slot: %04x:%02x:%02x.%d", c->vfio_device.pci_device->slot.domain, c->vfio_device.pci_device->slot.bus, c->vfio_device.pci_device->slot.device, c->vfio_device.pci_device->slot.function); - info("Vendor ID: %04x", c->vfio_device.pci_device->id.vendor); - info("Device ID: %04x", c->vfio_device.pci_device->id.device); - info("Class ID: %04x", c->vfio_device.pci_device->id.class_code); - - info("BAR0 mapped at %p", c->map); - - info("IP blocks:"); - for (size_t j = 0; j < list_length(&c->ips); j++) { INDENT - struct fpga_ip *i = (struct fpga_ip *) list_at(&c->ips, j); - - fpga_ip_dump(i); - } - } - - vfio_dump(c->vfio_device.group->container); -} - -int fpga_card_check(struct fpga_card *c) -{ - assert(c->state == STATE_PARSED); - - /* Check FPGA configuration */ - c->reset = fpga_vlnv_lookup(&c->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_gpio", NULL }); - if (!c->reset) - error("FPGA is missing a reset controller"); - - c->intc = fpga_vlnv_lookup(&c->ips, &(struct fpga_vlnv) { "acs.eonerc.rwth-aachen.de", "user", "axi_pcie_intc", NULL }); - if (!c->intc) - error("FPGA is missing a interrupt controller"); - - c->sw = fpga_vlnv_lookup(&c->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axis_interconnect", NULL }); - if (!c->sw) - warn("FPGA is missing an AXI4-Stream switch"); - - return 0; -} - -int fpga_card_destroy(struct fpga_card *c) -{ - list_destroy(&c->ips, (dtor_cb_t) fpga_ip_destroy, true); - - return 0; -} - -int fpga_card_reset(struct fpga_card *c) -{ - int ret; - char state[4096]; - - /* Save current state of PCI configuration space */ - ret = pread(c->vfio_device.fd, state, sizeof(state), (off_t) VFIO_PCI_CONFIG_REGION_INDEX << 40); - if (ret != sizeof(state)) - return -1; - - uint32_t *rst_reg = (uint32_t *) (c->map + c->reset->baseaddr); - - debug(3, "FPGA: reset"); - rst_reg[0] = 1; - - usleep(100000); - - /* Restore previous state of PCI configuration space */ - ret = pwrite(c->vfio_device.fd, state, sizeof(state), (off_t) VFIO_PCI_CONFIG_REGION_INDEX << 40); - if (ret != sizeof(state)) - return -1; - - /* After reset the value should be zero again */ - if (rst_reg[0]) - return -2; - - c->state = STATE_INITIALIZED; - - return 0; -} diff --git a/fpga/lib/ip.c b/fpga/lib/ip.c deleted file mode 100644 index 816bf2e7f..000000000 --- a/fpga/lib/ip.c +++ /dev/null @@ -1,167 +0,0 @@ -/** 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" - -int fpga_ip_init(struct fpga_ip *c, struct fpga_ip_type *vt) -{ - int ret; - - assert(c->state == STATE_DESTROYED); - - c->_vt = vt; - c->_vd = alloc(vt->size); - - ret = c->_vt->init ? c->_vt->init(c) : 0; - if (ret) - return ret; - - c->state = STATE_INITIALIZED; - - debug(8, "IP Core %s initalized (%u)", c->name, ret); - - return ret; -} - -int fpga_ip_parse(struct fpga_ip *c, json_t *cfg, const char *name) -{ - int ret, baseaddr = -1; - - assert(c->state != STATE_STARTED && c->state != STATE_DESTROYED); - - c->name = strdup(name); - c->baseaddr = -1; - c->irq = -1; - c->port = -1; - - json_error_t err; - - ret = json_unpack_ex(cfg, &err, 0, "{ s?: i, s?: i, s?: i }", - "baseaddr", &baseaddr, - "irq", &c->irq, - "port", &c->port - ); - if (ret) - jerror(&err, "Failed to parse configuration for FPGA IP '%s'", name); - - c->baseaddr = baseaddr; - - /* Type sepecific settings */ - ret = c->_vt && c->_vt->parse ? c->_vt->parse(c, cfg) : 0; - if (ret) - error("Failed to parse settings for IP core '%s'", name); - - c->state = STATE_PARSED; - - return 0; -} - -int fpga_ip_start(struct fpga_ip *c) -{ - int ret; - - assert(c->state == STATE_CHECKED); - - ret = c->_vt->start ? c->_vt->start(c) : 0; - if (ret) - return ret; - - c->state = STATE_STARTED; - - return 0; -} - -int fpga_ip_stop(struct fpga_ip *c) -{ - int ret; - - assert(c->state == STATE_STARTED); - - ret = c->_vt->stop ? c->_vt->stop(c) : 0; - if (ret) - return ret; - - c->state = STATE_STOPPED; - - return 0; -} - -int fpga_ip_destroy(struct fpga_ip *c) -{ - int ret; - - assert(c->state != STATE_DESTROYED); - - fpga_vlnv_destroy(&c->vlnv); - - ret = c->_vt->destroy ? c->_vt->destroy(c) : 0; - if (ret) - return ret; - - c->state = STATE_DESTROYED; - - free(c->_vd); - - return 0; -} - -int fpga_ip_reset(struct fpga_ip *c) -{ - debug(3, "Reset IP core: %s", c->name); - - return c->_vt->reset ? c->_vt->reset(c) : 0; -} - -void fpga_ip_dump(struct fpga_ip *c) -{ - assert(c->state != STATE_DESTROYED); - - info("IP %s: vlnv=%s:%s:%s:%s baseaddr=%#jx, irq=%d, port=%d", - c->name, c->vlnv.vendor, c->vlnv.library, c->vlnv.name, c->vlnv.version, - c->baseaddr, c->irq, c->port); - - if (c->_vt->dump) - c->_vt->dump(c); -} - -struct fpga_ip_type * fpga_ip_type_lookup(const char *vstr) -{ - int ret; - - struct fpga_vlnv vlnv; - - ret = fpga_vlnv_parse(&vlnv, vstr); - if (ret) - return NULL; - - /* Try to find matching IP type */ - for (size_t i = 0; i < list_length(&plugins); i++) { - struct plugin *p = (struct plugin *) list_at(&plugins, i); - - if (p->type == PLUGIN_TYPE_FPGA_IP && !fpga_vlnv_cmp(&vlnv, &p->ip.vlnv)) - return &p->ip; - } - - return NULL; -} diff --git a/fpga/lib/ips/dma.c b/fpga/lib/ips/dma.c deleted file mode 100644 index c02175709..000000000 --- a/fpga/lib/ips/dma.c +++ /dev/null @@ -1,657 +0,0 @@ -/** DMA related helper functions - * - * These functions present a simpler interface to Xilinx' DMA driver (XAxiDma_*) - * - * @author Steffen Vogel - * @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 . - *********************************************************************************/ - -#include -#include -#include -#include - -#include "log.h" -#include "plugin.h" -#include "utils.h" - -#include "fpga/ip.h" -#include "fpga/card.h" -#include "fpga/ips/dma.h" - -int dma_mem_split(struct dma_mem *o, struct dma_mem *a, struct dma_mem *b) -{ - int split = o->len / 2; - - a->base_virt = o->base_virt; - a->base_phys = o->base_phys; - - b->base_virt = a->base_virt + split; - b->base_phys = a->base_phys + split; - - a->len = split; - b->len = o->len - split; - - return 0; -} - -int dma_alloc(struct fpga_ip *c, struct dma_mem *mem, size_t len, int flags) -{ - int ret; - - struct fpga_card *f = c->card; - - /* Align to next bigger page size chunk */ - if (len & 0xFFF) { - len += 0x1000; - len &= ~0xFFF; - } - - mem->len = len; - mem->base_phys = (void *) -1; /* find free */ - mem->base_virt = mmap(0, mem->len, PROT_READ | PROT_WRITE, flags | MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, 0, 0); - if (mem->base_virt == MAP_FAILED) - return -1; - - ret = vfio_map_dma(f->vfio_device.group->container, (uint64_t) mem->base_virt, (uint64_t) mem->base_phys, mem->len); - if (ret) - return -2; - - return 0; -} - -int dma_free(struct fpga_ip *c, struct dma_mem *mem) -{ - int ret; - - ret = vfio_unmap_dma(c->card->vfio_device.group->container, (uint64_t) mem->base_virt, (uint64_t) mem->base_phys, mem->len); - if (ret) - return ret; - - ret = munmap(mem->base_virt, mem->len); - if (ret) - return ret; - - return 0; -} - -int dma_ping_pong(struct fpga_ip *c, char *src, char *dst, size_t len) -{ - int ret; - - ret = dma_read(c, dst, len); - if (ret) - return ret; - - ret = dma_write(c, src, len); - if (ret) - return ret; - - ret = dma_write_complete(c, NULL, NULL); - if (ret) - return ret; - - ret = dma_read_complete(c, NULL, NULL); - if (ret) - return ret; - - return 0; -} - -int dma_write(struct fpga_ip *c, char *buf, size_t len) -{ - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - - debug(25, "DMA write: dmac=%s buf=%p len=%#zx", c->name, buf, len); - - return xdma->HasSg - ? dma_sg_write(c, buf, len) - : dma_simple_write(c, buf, len); -} - -int dma_read(struct fpga_ip *c, char *buf, size_t len) -{ - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - - debug(25, "DMA read: dmac=%s buf=%p len=%#zx", c->name, buf, len); - - return xdma->HasSg - ? dma_sg_read(c, buf, len) - : dma_simple_read(c, buf, len); -} - -int dma_read_complete(struct fpga_ip *c, char **buf, size_t *len) -{ - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - - debug(25, "DMA read complete: dmac=%s", c->name); - - return xdma->HasSg - ? dma_sg_read_complete(c, buf, len) - : dma_simple_read_complete(c, buf, len); -} - -int dma_write_complete(struct fpga_ip *c, char **buf, size_t *len) -{ - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - - debug(25, "DMA write complete: dmac=%s", c->name); - - return xdma->HasSg - ? dma_sg_write_complete(c, buf, len) - : dma_simple_write_complete(c, buf, len); -} - -int dma_sg_write(struct fpga_ip *c, char *buf, size_t len) -{ - int ret, bdcnt; - - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); - XAxiDma_Bd *bds, *bd; - - uint32_t remaining, bdlen, bdbuf, cr; - - /* Checks */ - if (!xdma->HasSg) - return -1; - - if (len < 1) - return -2; - - if (!xdma->HasMm2S) - return -3; - - if (!ring->HasDRE) { - uint32_t mask = xdma->MicroDmaMode ? XAXIDMA_MICROMODE_MIN_BUF_ALIGN : ring->DataWidth - 1; - if ((uintptr_t) buf & mask) - return -4; - } - - bdcnt = CEIL(len, FPGA_DMA_BOUNDARY); - ret = XAxiDma_BdRingAlloc(ring, bdcnt, &bds); - if (ret != XST_SUCCESS) - return -5; - - remaining = len; - bdbuf = (uintptr_t) buf; - bd = bds; - for (int i = 0; i < bdcnt; i++) { - bdlen = MIN(remaining, FPGA_DMA_BOUNDARY); - - ret = XAxiDma_BdSetBufAddr(bd, bdbuf); - if (ret != XST_SUCCESS) - goto out; - - ret = XAxiDma_BdSetLength(bd, bdlen, ring->MaxTransferLen); - if (ret != XST_SUCCESS) - goto out; - - /* Set SOF / EOF / ID */ - cr = 0; - if (i == 0) - cr |= XAXIDMA_BD_CTRL_TXSOF_MASK; - if (i == bdcnt - 1) - cr |= XAXIDMA_BD_CTRL_TXEOF_MASK; - - XAxiDma_BdSetCtrl(bd, cr); - XAxiDma_BdSetId(bd, (uintptr_t) buf); - - remaining -= bdlen; - bdbuf += bdlen; - bd = (XAxiDma_Bd *) XAxiDma_BdRingNext(ring, bd); - } - - /* Give the BD to DMA to kick off the transmission. */ - ret = XAxiDma_BdRingToHw(ring, bdcnt, bds); - if (ret != XST_SUCCESS) - return -8; - - return 0; - -out: - ret = XAxiDma_BdRingUnAlloc(ring, bdcnt, bds); - if (ret != XST_SUCCESS) - return -6; - - return -5; -} - -int dma_sg_read(struct fpga_ip *c, char *buf, size_t len) -{ - int ret, bdcnt; - - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); - XAxiDma_Bd *bds, *bd; - - uint32_t remaining, bdlen, bdbuf; - - /* Checks */ - if (!xdma->HasSg) - return -1; - - if (len < 1) - return -2; - - if (!xdma->HasS2Mm) - return -3; - - if (!ring->HasDRE) { - uint32_t mask = xdma->MicroDmaMode ? XAXIDMA_MICROMODE_MIN_BUF_ALIGN : ring->DataWidth - 1; - if ((uintptr_t) buf & mask) - return -4; - } - - bdcnt = CEIL(len, FPGA_DMA_BOUNDARY); - ret = XAxiDma_BdRingAlloc(ring, bdcnt, &bds); - if (ret != XST_SUCCESS) - return -5; - - bdbuf = (uintptr_t) buf; - remaining = len; - bd = bds; - for (int i = 0; i < bdcnt; i++) { - bdlen = MIN(remaining, FPGA_DMA_BOUNDARY); - ret = XAxiDma_BdSetLength(bd, bdlen, ring->MaxTransferLen); - if (ret != XST_SUCCESS) - goto out; - - ret = XAxiDma_BdSetBufAddr(bd, bdbuf); - if (ret != XST_SUCCESS) - goto out; - - /* Receive BDs do not need to set anything for the control - * The hardware will set the SOF/EOF bits per stream ret */ - XAxiDma_BdSetCtrl(bd, 0); - XAxiDma_BdSetId(bd, (uintptr_t) buf); - - remaining -= bdlen; - bdbuf += bdlen; - bd = (XAxiDma_Bd *) XAxiDma_BdRingNext(ring, bd); - } - - ret = XAxiDma_BdRingToHw(ring, bdcnt, bds); - if (ret != XST_SUCCESS) - return -8; - - return 0; - -out: - ret = XAxiDma_BdRingUnAlloc(ring, bdcnt, bds); - if (ret != XST_SUCCESS) - return -6; - - return -5; -} - -int dma_sg_write_complete(struct fpga_ip *c, char **buf, size_t *len) -{ - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); - XAxiDma_Bd *bds; - - int processed, ret; - - /* Wait until the one BD TX transaction is done */ - while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DMA_TO_DEVICE) & XAXIDMA_IRQ_IOC_MASK)) - intc_wait(c->card->intc, c->irq); - XAxiDma_IntrAckIrq(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DMA_TO_DEVICE); - - processed = XAxiDma_BdRingFromHw(ring, XAXIDMA_ALL_BDS, &bds); - - if (len != NULL) - *len = XAxiDma_BdGetActualLength(bds, XAXIDMA_MAX_TRANSFER_LEN); - - if (buf != NULL) - *buf = (char *) (uintptr_t) XAxiDma_BdGetId(bds); - - /* Free all processed TX BDs for future transmission */ - ret = XAxiDma_BdRingFree(ring, processed, bds); - if (ret != XST_SUCCESS) - return -1; - - return 0; -} - -int dma_sg_read_complete(struct fpga_ip *c, char **buf, size_t *len) -{ - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); - XAxiDma_Bd *bds, *bd; - - int ret, bdcnt; - uint32_t recvlen, sr; - uintptr_t recvbuf = 0; - - if (!xdma->HasSg) - return -1; - - while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DEVICE_TO_DMA) & XAXIDMA_IRQ_IOC_MASK)) - intc_wait(c->card->intc, c->irq + 1); - XAxiDma_IntrAckIrq(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DEVICE_TO_DMA); - - bdcnt = XAxiDma_BdRingFromHw(ring, XAXIDMA_ALL_BDS, &bds); - - recvlen = 0; - - bd = bds; - for (int i = 0; i < bdcnt; i++) { - recvlen += XAxiDma_BdGetActualLength(bd, ring->MaxTransferLen); - - sr = XAxiDma_BdGetSts(bd); - if (sr & XAXIDMA_BD_STS_RXSOF_MASK) - if (i != 0) - warn("sof not first"); - - if (sr & XAXIDMA_BD_STS_RXEOF_MASK) - if (i != bdcnt - 1) - warn("eof not last"); - - recvbuf = XAxiDma_BdGetId(bd); - - bd = (XAxiDma_Bd *) XAxiDma_BdRingNext(ring, bd); - } - - if (len != NULL) - *len = recvlen; - if (buf != NULL) - *buf = (char *) recvbuf; - - /* Free all processed RX BDs for future transmission */ - ret = XAxiDma_BdRingFree(ring, bdcnt, bds); - if (ret != XST_SUCCESS) - return -3; - - return 0; -} - -int dma_simple_read(struct fpga_ip *c, char *buf, size_t len) -{ - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); - - /* Checks */ - if (xdma->HasSg) - return -1; - - if ((len < 1) || (len > FPGA_DMA_BOUNDARY)) - return -2; - - if (!xdma->HasS2Mm) - return -3; - - if (!ring->HasDRE) { - uint32_t mask = xdma->MicroDmaMode ? XAXIDMA_MICROMODE_MIN_BUF_ALIGN : ring->DataWidth - 1; - if ((uintptr_t) buf & mask) - return -4; - } - - if(!(XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_SR_OFFSET) & XAXIDMA_HALTED_MASK)) { - if (XAxiDma_Busy(xdma, XAXIDMA_DEVICE_TO_DMA)) - return -5; - } - - XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_DESTADDR_OFFSET, LOWER_32_BITS((uintptr_t) buf)); - if (xdma->AddrWidth > 32) - XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_DESTADDR_MSB_OFFSET, UPPER_32_BITS((uintptr_t) buf)); - - XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_CR_OFFSET, XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_CR_OFFSET) | XAXIDMA_CR_RUNSTOP_MASK); - XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_BUFFLEN_OFFSET, len); - - return XST_SUCCESS; -} - -int dma_simple_write(struct fpga_ip *c, char *buf, size_t len) -{ - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); - - /* Checks */ - if (xdma->HasSg) - return -1; - - if ((len < 1) || (len > FPGA_DMA_BOUNDARY)) - return -2; - - if (!xdma->HasMm2S) - return -3; - - if (!ring->HasDRE) { - uint32_t mask = xdma->MicroDmaMode ? XAXIDMA_MICROMODE_MIN_BUF_ALIGN : ring->DataWidth - 1; - if ((uintptr_t) buf & mask) - return -4; - } - - /* If the engine is doing transfer, cannot submit */ - if(!(XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_SR_OFFSET) & XAXIDMA_HALTED_MASK)) { - if (XAxiDma_Busy(xdma, XAXIDMA_DMA_TO_DEVICE)) - return -5; - } - - XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_SRCADDR_OFFSET, LOWER_32_BITS((uintptr_t) buf)); - if (xdma->AddrWidth > 32) - XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_SRCADDR_MSB_OFFSET, UPPER_32_BITS((uintptr_t) buf)); - - XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_CR_OFFSET, XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_CR_OFFSET) | XAXIDMA_CR_RUNSTOP_MASK); - XAxiDma_WriteReg(ring->ChanBase, XAXIDMA_BUFFLEN_OFFSET, len); - - return XST_SUCCESS; -} - -int dma_simple_read_complete(struct fpga_ip *c, char **buf, size_t *len) -{ - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); - - while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DEVICE_TO_DMA) & XAXIDMA_IRQ_IOC_MASK)) - intc_wait(c->card->intc, c->irq + 1); - XAxiDma_IntrAckIrq(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DEVICE_TO_DMA); - - if (len) - *len = XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_BUFFLEN_OFFSET); - - if (buf) { - *buf = (char *) (uintptr_t) XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_DESTADDR_OFFSET); - if (xdma->AddrWidth > 32) - *buf += XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_DESTADDR_MSB_OFFSET); - } - - return 0; -} - -int dma_simple_write_complete(struct fpga_ip *c, char **buf, size_t *len) -{ - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); - - while (!(XAxiDma_IntrGetIrq(xdma, XAXIDMA_DMA_TO_DEVICE) & XAXIDMA_IRQ_IOC_MASK)) - intc_wait(c->card->intc, c->irq); - XAxiDma_IntrAckIrq(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DMA_TO_DEVICE); - - if (len) - *len = XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_BUFFLEN_OFFSET); - - if (buf) { - *buf = (char *) (uintptr_t) XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_SRCADDR_OFFSET); - if (xdma->AddrWidth > 32) - *buf += XAxiDma_ReadReg(ring->ChanBase, XAXIDMA_SRCADDR_MSB_OFFSET); - } - - return 0; -} - -static int dma_setup_ring(XAxiDma_BdRing *ring, struct dma_mem *bdbuf) -{ - int delay = 0; - int coalesce = 1; - int ret, cnt; - - XAxiDma_Bd clearbd; - - /* Disable all RX interrupts before RxBD space setup */ - XAxiDma_BdRingIntDisable(ring, XAXIDMA_IRQ_ALL_MASK); - - /* Set delay and coalescing */ - XAxiDma_BdRingSetCoalesce(ring, coalesce, delay); - - /* Setup Rx BD space */ - cnt = XAxiDma_BdRingCntCalc(XAXIDMA_BD_MINIMUM_ALIGNMENT, bdbuf->len); - - ret = XAxiDma_BdRingCreate(ring, (uintptr_t) bdbuf->base_phys, (uintptr_t) bdbuf->base_virt, XAXIDMA_BD_MINIMUM_ALIGNMENT, cnt); - if (ret != XST_SUCCESS) - return -1; - - XAxiDma_BdClear(&clearbd); - ret = XAxiDma_BdRingClone(ring, &clearbd); - if (ret != XST_SUCCESS) - return -2; - - /* Start the channel */ - ret = XAxiDma_BdRingStart(ring); - if (ret != XST_SUCCESS) - return -3; - - return XST_SUCCESS; -} - -static int dma_init_rings(XAxiDma *xdma, struct dma_mem *bd) -{ - int ret; - - struct dma_mem bd_rx, bd_tx; - - ret = dma_mem_split(bd, &bd_rx, &bd_tx); - if (ret) - return -1; - - ret = dma_setup_ring(XAxiDma_GetRxRing(xdma), &bd_rx); - if (ret != XST_SUCCESS) - return -2; - - ret = dma_setup_ring(XAxiDma_GetTxRing(xdma), &bd_tx); - if (ret != XST_SUCCESS) - return -3; - - return 0; -} - -int dma_start(struct fpga_ip *c) -{ - int ret, sg; - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma *xdma = &dma->inst; - - /* Guess DMA type */ - sg = (XAxiDma_In32((uintptr_t) c->card->map + c->baseaddr + XAXIDMA_TX_OFFSET+ XAXIDMA_SR_OFFSET) & - XAxiDma_In32((uintptr_t) c->card->map + c->baseaddr + XAXIDMA_RX_OFFSET+ XAXIDMA_SR_OFFSET) & XAXIDMA_SR_SGINCL_MASK) ? 1 : 0; - - XAxiDma_Config xdma_cfg = { - .BaseAddr = (uintptr_t) c->card->map + c->baseaddr, - .HasStsCntrlStrm = 0, - .HasMm2S = 1, - .HasMm2SDRE = 1, - .Mm2SDataWidth = 128, - .HasS2Mm = 1, - .HasS2MmDRE = 1, /* Data Realignment Engine */ - .HasSg = sg, - .S2MmDataWidth = 128, - .Mm2sNumChannels = 1, - .S2MmNumChannels = 1, - .Mm2SBurstSize = 64, - .S2MmBurstSize = 64, - .MicroDmaMode = 0, - .AddrWidth = 32 - }; - - ret = XAxiDma_CfgInitialize(xdma, &xdma_cfg); - if (ret != XST_SUCCESS) - return -1; - - /* Perform selftest */ - ret = XAxiDma_Selftest(xdma); - if (ret != XST_SUCCESS) - return -2; - - /* Map buffer descriptors */ - if (xdma->HasSg) { - ret = dma_alloc(c, &dma->bd, FPGA_DMA_BD_SIZE, 0); - if (ret) - return -3; - - ret = dma_init_rings(xdma, &dma->bd); - if (ret) - return -4; - } - - /* Enable completion interrupts for both channels */ - XAxiDma_IntrEnable(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DMA_TO_DEVICE); - XAxiDma_IntrEnable(xdma, XAXIDMA_IRQ_IOC_MASK, XAXIDMA_DEVICE_TO_DMA); - - return 0; -} - -int dma_reset(struct fpga_ip *c) -{ - struct dma *dma = (struct dma *) c->_vd; - - XAxiDma_Reset(&dma->inst); - - return 0; -} - -static struct plugin p = { - .name = "Xilinx's AXI4 Direct Memory Access Controller", - .description = "Transfer data streams between VILLASnode and VILLASfpga", - .type = PLUGIN_TYPE_FPGA_IP, - .ip = { - .vlnv = { "xilinx.com", "ip", "axi_dma", NULL }, - .type = FPGA_IP_TYPE_DM_DMA, - .init = dma_start, - .reset = dma_reset, - .size = sizeof(struct dma) - } -}; - -REGISTER_PLUGIN(&p) diff --git a/fpga/lib/ips/fifo.c b/fpga/lib/ips/fifo.c deleted file mode 100644 index 1f4c058f3..000000000 --- a/fpga/lib/ips/fifo.c +++ /dev/null @@ -1,153 +0,0 @@ -/** FIFO related helper functions - * - * These functions present a simpler interface to Xilinx' FIFO driver (XLlFifo_*) - * - * @author Steffen Vogel - * @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 . - *********************************************************************************/ - -#include - -#include "utils.h" -#include "plugin.h" - -#include "fpga/ip.h" -#include "fpga/card.h" -#include "fpga/ips/fifo.h" -#include "fpga/ips/intc.h" - -int fifo_start(struct fpga_ip *c) -{ - int ret; - - struct fpga_card *f = c->card; - struct fifo *fifo = (struct fifo *) c->_vd; - - XLlFifo *xfifo = &fifo->inst; - XLlFifo_Config fifo_cfg = { - .BaseAddress = (uintptr_t) f->map + c->baseaddr, - .Axi4BaseAddress = (uintptr_t) c->card->map + fifo->baseaddr_axi4, - .Datainterface = (fifo->baseaddr_axi4 != -1) ? 1 : 0 /* use AXI4 for Data, AXI4-Lite for control */ - }; - - ret = XLlFifo_CfgInitialize(xfifo, &fifo_cfg, (uintptr_t) c->card->map + c->baseaddr); - if (ret != XST_SUCCESS) - return -1; - - XLlFifo_IntEnable(xfifo, XLLF_INT_RC_MASK); /* Receive complete IRQ */ - - return 0; -} - -int fifo_stop(struct fpga_ip *c) -{ - struct fifo *fifo = (struct fifo *) c->_vd; - - XLlFifo *xfifo = &fifo->inst; - - XLlFifo_IntDisable(xfifo, XLLF_INT_RC_MASK); /* Receive complete IRQ */ - - return 0; -} - -ssize_t fifo_write(struct fpga_ip *c, char *buf, size_t len) -{ - struct fifo *fifo = (struct fifo *) c->_vd; - - XLlFifo *xllfifo = &fifo->inst; - - uint32_t tdfv; - - tdfv = XLlFifo_TxVacancy(xllfifo); - if (tdfv < len) - return -1; - - XLlFifo_Write(xllfifo, buf, len); - XLlFifo_TxSetLen(xllfifo, len); - - return len; -} - -ssize_t fifo_read(struct fpga_ip *c, char *buf, size_t len) -{ - struct fifo *fifo = (struct fifo *) c->_vd; - - XLlFifo *xllfifo = &fifo->inst; - - size_t nextlen = 0; - uint32_t rxlen; - - while (!XLlFifo_IsRxDone(xllfifo)) - intc_wait(c->card->intc, c->irq); - XLlFifo_IntClear(xllfifo, XLLF_INT_RC_MASK); - - /* Get length of next frame */ - rxlen = XLlFifo_RxGetLen(xllfifo); - nextlen = MIN(rxlen, len); - - /* Read from FIFO */ - XLlFifo_Read(xllfifo, buf, nextlen); - - return nextlen; -} - -int fifo_parse(struct fpga_ip *c, json_t *cfg) -{ - struct fifo *fifo = (struct fifo *) c->_vd; - - int baseaddr_axi4 = -1, ret; - - json_error_t err; - - fifo->baseaddr_axi4 = -1; - - ret = json_unpack_ex(cfg, &err, 0, "{ s?: i }", "baseaddr_axi4", &baseaddr_axi4); - if (ret) - jerror(&err, "Failed to parse configuration of FPGA IP '%s'", c->name); - - fifo->baseaddr_axi4 = baseaddr_axi4; - - return 0; -} - -int fifo_reset(struct fpga_ip *c) -{ - struct fifo *fifo = (struct fifo *) c->_vd; - - XLlFifo_Reset(&fifo->inst); - - return 0; -} - -static struct plugin p = { - .name = "Xilinx's AXI4 FIFO data mover", - .description = "", - .type = PLUGIN_TYPE_FPGA_IP, - .ip = { - .vlnv = { "xilinx.com", "ip", "axi_fifo_mm_s", NULL }, - .type = FPGA_IP_TYPE_DM_FIFO, - .start = fifo_start, - .stop = fifo_stop, - .parse = fifo_parse, - .reset = fifo_reset, - .size = sizeof(struct fifo) - } -}; - -REGISTER_PLUGIN(&p) diff --git a/fpga/lib/ips/intc.c b/fpga/lib/ips/intc.c deleted file mode 100644 index 7fcf109d6..000000000 --- a/fpga/lib/ips/intc.c +++ /dev/null @@ -1,180 +0,0 @@ -/** AXI-PCIe Interrupt controller - * - * @author Steffen Vogel - * @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 . - *********************************************************************************/ - -#include - -#include "config.h" -#include "log.h" -#include "plugin.h" - -#include "kernel/vfio.h" -#include "kernel/kernel.h" - -#include "fpga/ip.h" -#include "fpga/card.h" -#include "fpga/ips/intc.h" - -int intc_start(struct fpga_ip *c) -{ - int ret; - - struct fpga_card *f = c->card; - struct intc *intc = (struct intc *) c->_vd; - - uintptr_t base = (uintptr_t) f->map + c->baseaddr; - - 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; - - /* For each IRQ */ - for (int i = 0; i < intc->num_irqs; i++) { - /* Pin to core */ - ret = kernel_irq_setaffinity(intc->nos[i], f->affinity, NULL); - if (ret) - serror("Failed to change affinity of VFIO-MSI interrupt"); - - /* Setup vector */ - XIntc_Out32(base + XIN_IVAR_OFFSET + i * 4, i); - } - - XIntc_Out32(base + XIN_IMR_OFFSET, 0); /* Use manual acknowlegement for all IRQs */ - XIntc_Out32(base + XIN_IAR_OFFSET, 0xFFFFFFFF); /* Acknowlege all pending IRQs manually */ - XIntc_Out32(base + XIN_IMR_OFFSET, 0xFFFFFFFF); /* Use fast acknowlegement for all IRQs */ - XIntc_Out32(base + XIN_IER_OFFSET, 0x00000000); /* Disable all IRQs by default */ - XIntc_Out32(base + XIN_MER_OFFSET, XIN_INT_HARDWARE_ENABLE_MASK | XIN_INT_MASTER_ENABLE_MASK); - - debug(4, "FPGA: enabled interrupts"); - - return 0; -} - -int intc_destroy(struct fpga_ip *c) -{ - 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; - - /* Current state of INTC */ - ier = XIntc_In32(base + XIN_IER_OFFSET); - imr = XIntc_In32(base + XIN_IMR_OFFSET); - - /* Clear pending IRQs */ - XIntc_Out32(base + XIN_IAR_OFFSET, mask); - - for (int i = 0; i < intc->num_irqs; i++) { - if (mask & (1 << i)) - intc->flags[i] = flags; - } - - if (flags & INTC_POLLING) { - XIntc_Out32(base + XIN_IMR_OFFSET, imr & ~mask); - XIntc_Out32(base + XIN_IER_OFFSET, ier & ~mask); - } - else { - XIntc_Out32(base + XIN_IER_OFFSET, ier | mask); - XIntc_Out32(base + XIN_IMR_OFFSET, imr | mask); - } - - debug(3, "New ier = %#x", XIntc_In32(base + XIN_IER_OFFSET)); - 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); - - return 0; -} - -int intc_disable(struct fpga_ip *c, uint32_t mask) -{ - struct fpga_card *f = c->card; - - uintptr_t base = (uintptr_t) f->map + c->baseaddr; - uint32_t ier = XIntc_In32(base + XIN_IER_OFFSET); - - XIntc_Out32(base + XIN_IER_OFFSET, ier & ~mask); - - return 0; -} - -uint64_t intc_wait(struct fpga_ip *c, int irq) -{ - struct fpga_card *f = c->card; - struct intc *intc = (struct intc *) c->_vd; - - uintptr_t base = (uintptr_t) f->map + c->baseaddr; - - if (intc->flags[irq] & INTC_POLLING) { - uint32_t isr, mask = 1 << irq; - - do { - isr = XIntc_In32(base + XIN_ISR_OFFSET); - pthread_testcancel(); - } while ((isr & mask) != mask); - - XIntc_Out32(base + XIN_IAR_OFFSET, mask); - - return 1; - } - else { - uint64_t cnt; - ssize_t ret = read(intc->efds[irq], &cnt, sizeof(cnt)); - if (ret != sizeof(cnt)) - return 0; - - return cnt; - } -} - -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) diff --git a/fpga/lib/ips/switch.c b/fpga/lib/ips/switch.c deleted file mode 100644 index 73c647be1..000000000 --- a/fpga/lib/ips/switch.c +++ /dev/null @@ -1,221 +0,0 @@ -/** AXI Stream interconnect related helper functions - * - * These functions present a simpler interface to Xilinx' AXI Stream switch driver (XAxis_Switch_*) - * - * @author Steffen Vogel - * @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 . - *********************************************************************************/ - -#include "list.h" -#include "log.h" -#include "log_config.h" -#include "plugin.h" - -#include "fpga/ip.h" -#include "fpga/card.h" -#include "fpga/ips/switch.h" - -int switch_start(struct fpga_ip *c) -{ - int ret; - - struct fpga_card *f = c->card; - struct sw *sw = (struct sw *) c->_vd; - - XAxis_Switch *xsw = &sw->inst; - - if (c != f->sw) - error("There can be only one AXI4-Stream interconnect per FPGA"); - - - /* Setup AXI-stream switch */ - XAxis_Switch_Config sw_cfg = { - .BaseAddress = (uintptr_t) f->map + c->baseaddr, - .MaxNumMI = sw->num_ports, - .MaxNumSI = sw->num_ports - }; - - ret = XAxisScr_CfgInitialize(xsw, &sw_cfg, (uintptr_t) c->card->map + c->baseaddr); - if (ret != XST_SUCCESS) - return -1; - - /* Disable all masters */ - XAxisScr_RegUpdateDisable(xsw); - XAxisScr_MiPortDisableAll(xsw); - XAxisScr_RegUpdateEnable(xsw); - - switch_init_paths(c); - - return 0; -} - -int switch_init_paths(struct fpga_ip *c) -{ - int ret; - struct sw *sw = (struct sw *) c->_vd; - - XAxis_Switch *xsw = &sw->inst; - - XAxisScr_RegUpdateDisable(xsw); - XAxisScr_MiPortDisableAll(xsw); - - for (size_t i = 0; i < list_length(&sw->paths); i++) { - struct sw_path *p = (struct sw_path *) list_at(&sw->paths, i); - struct fpga_ip *mi, *si; - - mi = list_lookup(&c->card->ips, p->out); - si = list_lookup(&c->card->ips, p->in); - - if (!mi || !si || mi->port == -1 || si->port == -1) - error("Invalid path configuration for FPGA"); - - ret = switch_connect(c, mi, si); - if (ret) - error("Failed to configure switch"); - } - - XAxisScr_RegUpdateEnable(xsw); - - return 0; -} - -int switch_destroy(struct fpga_ip *c) -{ - struct sw *sw = (struct sw *) c->_vd; - - list_destroy(&sw->paths, NULL, true); - - return 0; -} - -int switch_parse(struct fpga_ip *c, json_t *cfg) -{ - struct sw *sw = (struct sw *) c->_vd; - - int ret; - size_t index; - json_error_t err; - json_t *json_path, *json_paths = NULL; - - list_init(&sw->paths); - - ret = json_unpack_ex(cfg, &err, 0, "{ s: i, s?: o }", - "num_ports", &sw->num_ports, - "paths", &json_paths - ); - if (ret) - jerror(&err, "Failed to parse configuration of FPGA IP '%s'", c->name); - - if (!json_paths) - return 0; /* no switch config available */ - - if (!json_is_array(json_paths)) - error("Setting 'paths' of FPGA IP '%s' should be an array of JSON objects", c->name); - - json_array_foreach(json_paths, index, json_path) { - struct sw_path *p = (struct sw_path *) alloc(sizeof(struct sw_path)); - int reverse = 0; - - ret = json_unpack_ex(json_path, &err, 0, "{ s?: b, s: s, s: s }", - "reverse", &reverse, - "in", &p->in, - "out", &p->out - ); - if (ret) - jerror(&err, "Failed to parse path %zu of FPGA IP '%s'", index, c->name); - - list_push(&sw->paths, p); - - if (reverse) { - struct sw_path *r = memdup(p, sizeof(struct sw_path)); - - r->in = p->out; - r->out = p->in; - - list_push(&sw->paths, r); - } - } - - return 0; -} - -int switch_connect(struct fpga_ip *c, struct fpga_ip *mi, struct fpga_ip *si) -{ - struct sw *sw = (struct sw *) c->_vd; - XAxis_Switch *xsw = &sw->inst; - - uint32_t mux, port; - - /* Check if theres already something connected */ - for (int i = 0; i < sw->num_ports; i++) { - mux = XAxisScr_ReadReg(xsw->Config.BaseAddress, XAXIS_SCR_MI_MUX_START_OFFSET + i * 4); - if (!(mux & XAXIS_SCR_MI_X_DISABLE_MASK)) { - port = mux & ~XAXIS_SCR_MI_X_DISABLE_MASK; - - if (port == si->port) { - warn("Switch: Slave port %s (%u) has been connected already to port %u. Disconnecting...", si->name, si->port, i); - XAxisScr_RegUpdateDisable(xsw); - XAxisScr_MiPortDisable(xsw, i); - XAxisScr_RegUpdateEnable(xsw); - } - } - } - - /* Reconfigure switch */ - XAxisScr_RegUpdateDisable(xsw); - XAxisScr_MiPortEnable(xsw, mi->port, si->port); - XAxisScr_RegUpdateEnable(xsw); - - /* Reset IPs */ - /*ip_reset(mi); - ip_reset(si);*/ - - debug(8, "FPGA: Switch connected %s (%u) to %s (%u)", mi->name, mi->port, si->name, si->port); - - return 0; -} - -int switch_disconnect(struct fpga_ip *c, struct fpga_ip *mi, struct fpga_ip *si) -{ - struct sw *sw = (struct sw *) c->_vd; - XAxis_Switch *xsw = &sw->inst; - - if (!XAxisScr_IsMiPortEnabled(xsw, mi->port, si->port)) - return -1; - - XAxisScr_MiPortDisable(xsw, mi->port); - - return 0; -} - -static struct plugin p = { - .name = "Xilinx's AXI4-Stream switch", - .description = "", - .type = PLUGIN_TYPE_FPGA_IP, - .ip = { - .vlnv = { "xilinx.com", "ip", "axis_interconnect", NULL }, - .type = FPGA_IP_TYPE_MISC, - .start = switch_start, - .destroy = switch_destroy, - .parse = switch_parse, - .size = sizeof(struct sw) - } -}; - -REGISTER_PLUGIN(&p) diff --git a/fpga/lib/ips/timer.c b/fpga/lib/ips/timer.c deleted file mode 100644 index 57eb1a67a..000000000 --- a/fpga/lib/ips/timer.c +++ /dev/null @@ -1,61 +0,0 @@ -/** Timer related helper functions - * - * These functions present a simpler interface to Xilinx' Timer Counter driver (XTmrCtr_*) - * - * @author Steffen Vogel - * @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 . - *********************************************************************************/ - -#include "config.h" -#include "plugin.h" - -#include "fpga/ip.h" -#include "fpga/card.h" -#include "fpga/ips/timer.h" - -int timer_start(struct fpga_ip *c) -{ - struct fpga_card *f = c->card; - struct timer *tmr = (struct timer *) c->_vd; - - XTmrCtr *xtmr = &tmr->inst; - XTmrCtr_Config xtmr_cfg = { - .BaseAddress = (uintptr_t) f->map + c->baseaddr, - .SysClockFreqHz = FPGA_AXI_HZ - }; - - XTmrCtr_CfgInitialize(xtmr, &xtmr_cfg, (uintptr_t) f->map + c->baseaddr); - XTmrCtr_InitHw(xtmr); - - return 0; -} - -static struct plugin p = { - .name = "Xilinx's programmable timer / counter", - .description = "", - .type = PLUGIN_TYPE_FPGA_IP, - .ip = { - .vlnv = { "xilinx.com", "ip", "axi_timer", NULL }, - .type = FPGA_IP_TYPE_MISC, - .start = timer_start, - .size = sizeof(struct timer) - } -}; - -REGISTER_PLUGIN(&p) diff --git a/fpga/lib/plugin.c b/fpga/lib/plugin.c deleted file mode 100644 index 908d8eea4..000000000 --- a/fpga/lib/plugin.c +++ /dev/null @@ -1,111 +0,0 @@ -/** 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 "plugin.h" - -/** Global list of all known plugins */ -struct list plugins = { .state = STATE_DESTROYED }; - -LIST_INIT_STATIC(&plugins) - -int plugin_init(struct plugin *p) -{ - assert(p->state == STATE_DESTROYED); - - p->state = STATE_INITIALIZED; - - return 0; -} - -int plugin_parse(struct plugin *p, json_t *cfg) -{ - const char *path; - - path = json_string_value(cfg); - if (!path) - return -1; - - p->path = strdup(path); - - return 0; -} - -int plugin_load(struct plugin *p) -{ - p->handle = dlopen(p->path, RTLD_NOW); - if (!p->path) - return -1; - - p->state = STATE_LOADED; - - return 0; -} - -int plugin_unload(struct plugin *p) -{ - int ret; - - assert(p->state == STATE_LOADED); - - ret = dlclose(p->handle); - if (ret) - return -1; - - p->state = STATE_UNLOADED; - - return 0; -} - -int plugin_destroy(struct plugin *p) -{ - assert(p->state != STATE_DESTROYED && p->state != STATE_LOADED); - - if (p->path) - free(p->path); - - return 0; -} - -struct plugin * plugin_lookup(enum plugin_type type, const char *name) -{ - for (size_t i = 0; i < list_length(&plugins); i++) { - struct plugin *p = (struct plugin *) list_at(&plugins, i); - - if (p->type == type && strcmp(p->name, name) == 0) - return p; - } - - return NULL; -} - -void plugin_dump(enum plugin_type type) -{ - for (size_t i = 0; i < list_length(&plugins); i++) { - struct plugin *p = (struct plugin *) list_at(&plugins, i); - - if (p->type == type) - printf(" - %-13s: %s\n", p->name, p->description); - } -} diff --git a/fpga/lib/vlnv.c b/fpga/lib/vlnv.c deleted file mode 100644 index e6c693302..000000000 --- a/fpga/lib/vlnv.c +++ /dev/null @@ -1,64 +0,0 @@ -/** 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 "fpga/vlnv.h" -#include "fpga/ip.h" - -struct fpga_ip * fpga_vlnv_lookup(struct list *l, struct fpga_vlnv *v) -{ - return (struct fpga_ip *) list_search(l, (cmp_cb_t) fpga_vlnv_cmp, v); -} - -int fpga_vlnv_cmp(struct fpga_vlnv *a, struct fpga_vlnv *b) -{ - return ((!a->vendor || !b->vendor || !strcmp(a->vendor, b->vendor )) && - (!a->library || !b->library || !strcmp(a->library, b->library)) && - (!a->name || !b->name || !strcmp(a->name, b->name )) && - (!a->version || !b->version || !strcmp(a->version, b->version))) ? 0 : 1; -} - -int fpga_vlnv_parse(struct fpga_vlnv *c, const char *vlnv) -{ - char *tmp = strdup(vlnv); - - c->vendor = strdup(strtok(tmp, ":")); - c->library = strdup(strtok(NULL, ":")); - c->name = strdup(strtok(NULL, ":")); - c->version = strdup(strtok(NULL, ":")); - - free(tmp); - - return 0; -} - -int fpga_vlnv_destroy(struct fpga_vlnv *v) -{ - free(v->vendor); - free(v->library); - free(v->name); - free(v->version); - - return 0; -}