diff --git a/include/villas/fpga/card.h b/include/villas/fpga/card.h new file mode 100644 index 000000000..8fa9815d4 --- /dev/null +++ b/include/villas/fpga/card.h @@ -0,0 +1,63 @@ +/** FPGA card + * + * This class represents a FPGA device. + * + * @file + * @author Steffen Vogel + * @copyright 2017, Steffen Vogel + * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + */ +/** + * @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once + +enum fpga_card_state { + FPGA_CARD_STATE_UNKOWN, + FPGA_CARD_STATE_RESETTED, + FPGA_CARD_STATE_INITIALIZED +}; + +struct fpga_card { + char *name; /**< The name of the FPGA card */ + + enum fpga_card_state state; /**< The state of this FPGA card. */ + + struct pci_dev filter; /**< Filter for PCI device. */ + struct vfio_dev vd; /**< 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; + + config_setting_t *cfg; +}; + +int fpga_card_parse(struct fpga_card *c, config_setting_t *cfg); + +/** Initialize FPGA card and its IP components. */ +int fpga_card_init(struct fpga_card *c); + +int fpga_card_destroy(struct fpga_card *c); + +/** Check if the FPGA card configuration is plausible. */ +int fpga_card_check(struct fpga_card *c); + +/** Reset the FPGA to a known state */ +int fpga_card_reset(struct fpga_card *c); + +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/dma.h b/include/villas/fpga/dma.h deleted file mode 100644 index 172d80dba..000000000 --- a/include/villas/fpga/dma.h +++ /dev/null @@ -1,68 +0,0 @@ -/** DMA related helper functions - * - * These functions present a simpler interface to Xilinx' DMA driver (XAxiDma_*) - * - * @file - * @author Steffen Vogel - * @copyright 2015-2016, Steffen Vogel - * This file is part of S2SS. All Rights Reserved. Proprietary and confidential. - * Unauthorized copying of this file, via any medium is strictly prohibited. - **********************************************************************************/ - -#ifndef _FPGA_DMA_H_ -#define _FPGA_DMA_H_ - -#include -#include -#include - -#include - -#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 ip *c, struct dma_mem *mem, size_t len, int flags); -int dma_free(struct ip *c, struct dma_mem *mem); - -int dma_write(struct ip *c, char *buf, size_t len); -int dma_read(struct ip *c, char *buf, size_t len); -int dma_read_complete(struct ip *c, char **buf, size_t *len); -int dma_write_complete(struct ip *c, char **buf, size_t *len); - -int dma_sg_write(struct ip *c, char *buf, size_t len); -int dma_sg_read(struct ip *c, char *buf, size_t len); - -int dma_sg_write_complete(struct ip *c, char **buf, size_t *len); -int dma_sg_read_complete(struct ip *c, char **buf, size_t *len); - -int dma_simple_read(struct ip *c, char *buf, size_t len); -int dma_simple_write(struct ip *c, char *buf, size_t len); - -int dma_simple_read_complete(struct ip *c, char **buf, size_t *len); -int dma_simple_write_complete(struct ip *c, char **buf, size_t *len); - -int dma_ping_pong(struct ip *c, char *src, char *dst, size_t len); - -int dma_init(struct ip *c); - -#endif /* _FPGA_DMA_H_ */ \ No newline at end of file diff --git a/include/villas/fpga/ip.h b/include/villas/fpga/ip.h index 72a7cda7d..fb0e94a88 100644 --- a/include/villas/fpga/ip.h +++ b/include/villas/fpga/ip.h @@ -1,62 +1,73 @@ -#ifndef _FPGA_IP_H_ -#define _FPGA_IP_H_ +/** Interlectual Property component. + * + * This class represents a module within the FPGA. + * + * @file + * @author Steffen Vogel + * @copyright 2015-2016, Steffen Vogel + * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + */ +/** + * @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once #include -#include -#include -#include -#include -#include - #include "utils.h" -#include "fpga/dma.h" -#include "fpga/switch.h" -#include "fpga/fifo.h" -#include "fpga/rtds_axis.h" -#include "fpga/timer.h" -#include "fpga/model.h" -#include "fpga/dft.h" -#include "fpga/intc.h" + #include "nodes/fpga.h" -extern struct list ip_types; /**< Table of existing FPGA IP core drivers */ +#include "fpga/vlnv.h" -enum ip_state { +#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" + +enum fpga_ip_state { IP_STATE_UNKNOWN, IP_STATE_INITIALIZED }; -struct ip_vlnv { - char *vendor; - char *library; - char *name; - char *version; +struct fpga_ip_type { + struct fpga_vlnv vlnv; + + enum { + FPGA_IP_TYPE_DATAMOVER, /**< A datamover IP exchanges streaming data between the FPGA and the CPU. */ + FPGA_IP_TYPE_MODEL, /**< A model IP simulates a system on the FPGA. */ + FPGA_IP_TYPE_MATH, /**< A math IP performs some kind of mathematical operation on the streaming data */ + FPGA_IP_TYPE_MISC, /**< Other IP components like timer, counters, interrupt conctrollers or routing. */ + FPGA_IP_TYPE_INTERFACE /**< A interface IP connects the FPGA to another system or controller. */ + } type; + + int (*parse)(struct fpga_ip *c); + int (*init)(struct fpga_ip *c); + int (*reset)(struct fpga_ip *c); + void (*dump)(struct fpga_ip *c); + void (*destroy)(struct fpga_ip *c); }; -struct ip_type { - struct ip_vlnv vlnv; +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. */ - int (*parse)(struct ip *c); - int (*init)(struct ip *c); - int (*reset)(struct ip *c); - void (*dump)(struct ip *c); - void (*destroy)(struct ip *c); -}; + enum fpga_ip_state state; /**< The current state of the FPGA IP component. */ -struct ip { - char *name; + struct fpga_ip_type *_vt; /**< Vtable containing FPGA IP type function pointers. */ - struct ip_vlnv vlnv; + uintptr_t baseaddr; /**< The baseadress of this FPGA IP component */ + uintptr_t baseaddr_axi4; /**< Used by AXI4 FIFO DM */ - uintptr_t baseaddr; - uintptr_t baseaddr_axi4; - - int port, irq; - - enum ip_state state; - - struct ip_type *_vt; + 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. */ union { struct model model; @@ -66,33 +77,26 @@ struct ip { struct sw sw; struct dft dft; struct intc intc; - }; + }; /**< Specific private date per FPGA IP type. Depends on fpga_ip::_vt */ - struct fpga *card; + struct fpga_card *card; /**< The FPGA to which this IP instance belongs to. */ config_setting_t *cfg; }; -/** Return the first IP block in list \p l which matches the VLNV */ -struct ip * ip_vlnv_lookup(struct list *l, const char *vendor, const char *library, const char *name, const char *version); +/** Initialize IP instance. */ +int fpga_ip_init(struct fpga_ip *c); -/** Check if IP block \p c matched VLNV. */ -int ip_vlnv_cmp(struct ip_vlnv *a, struct ip_vlnv *b); +/** Release dynamic memory allocated by this IP instance. */ +int fpga_ip_destroy(struct fpga_ip *c); -/** Tokenizes VLNV \p vlnv and stores it into \p c */ -int ip_vlnv_parse(struct ip_vlnv *c, const char *vlnv); +/** Dump details about this IP instance to stdout. */ +void fpga_ip_dump(struct fpga_ip *c); -/** Release memory allocated by ip_vlnv_parse(). */ -void ip_vlnv_destroy(struct ip_vlnv *v); +/** Reset IP component to its initial state. */ +int fpga_ip_reset(struct fpga_ip *c); -int ip_init(struct ip *c); +/** Parse IP configuration from configuration file */ +int fpga_ip_parse(struct fpga_ip *c, config_setting_t *cfg); -void ip_destroy(struct ip *c); - -void ip_dump(struct ip *c); - -int ip_reset(struct ip *c); - -int ip_parse(struct ip *c, config_setting_t *cfg); - -#endif /* _FPGA_IP_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/dft.h b/include/villas/fpga/ips/dft.h similarity index 68% rename from include/villas/fpga/dft.h rename to include/villas/fpga/ips/dft.h index 52edfb37b..95edb9abf 100644 --- a/include/villas/fpga/dft.h +++ b/include/villas/fpga/ips/dft.h @@ -5,10 +5,13 @@ * @copyright 2015-2016, Steffen Vogel * This file is part of S2SS. All Rights Reserved. Proprietary and confidential. * Unauthorized copying of this file, via any medium is strictly prohibited. - **********************************************************************************/ - -#ifndef _FPGA_DFT_H_ -#define _FPGA_DFT_H_ + */ +/** + * @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once #include @@ -24,11 +27,10 @@ struct dft { int decimation; }; -int dft_parse(struct ip *c); +int dft_parse(struct fpga_ip *c); -int dft_init(struct ip *c); +int dft_init(struct fpga_ip *c); -void dft_destroy(struct ip *c); +int dft_destroy(struct fpga_ip *c); - -#endif /* _FPGA_DFT_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/ips/dma.h b/include/villas/fpga/ips/dma.h new file mode 100644 index 000000000..ab6fffb10 --- /dev/null +++ b/include/villas/fpga/ips/dma.h @@ -0,0 +1,74 @@ +/** DMA related helper functions. + * + * These functions present a simpler interface to Xilinx' DMA driver (XAxiDma_*). + * + * @file + * @author Steffen Vogel + * @copyright 2015-2016, Steffen Vogel + * This file is part of S2SS. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + */ +/** + * @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_init(struct fpga_ip *c); + +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/fifo.h b/include/villas/fpga/ips/fifo.h similarity index 65% rename from include/villas/fpga/fifo.h rename to include/villas/fpga/ips/fifo.h index 1872fa488..4602ed36f 100644 --- a/include/villas/fpga/fifo.h +++ b/include/villas/fpga/ips/fifo.h @@ -7,10 +7,13 @@ * @copyright 2015-2016, Steffen Vogel * This file is part of S2SS. All Rights Reserved. Proprietary and confidential. * Unauthorized copying of this file, via any medium is strictly prohibited. - **********************************************************************************/ + */ +/** + * @addtogroup fpga VILLASfpga + * @{ + */ -#ifndef _FPGA_FIFO_H_ -#define _FPGA_FIFO_H_ +#pragma once #include @@ -26,10 +29,10 @@ struct fifo { /* Forward declaration */ struct ip; -int fifo_init(struct ip *c); +int fifo_init(struct fpga_ip *c); -ssize_t fifo_write(struct ip *c, char *buf, size_t len); +ssize_t fifo_write(struct fpga_ip *c, char *buf, size_t len); -ssize_t fifo_read(struct ip *c, char *buf, size_t len); +ssize_t fifo_read(struct fpga_ip *c, char *buf, size_t len); -#endif /* _FPGA_FIFO_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/intc.h b/include/villas/fpga/ips/intc.h similarity index 63% rename from include/villas/fpga/intc.h rename to include/villas/fpga/ips/intc.h index 626fe07d6..2449259b9 100644 --- a/include/villas/fpga/intc.h +++ b/include/villas/fpga/ips/intc.h @@ -4,10 +4,13 @@ * @copyright 2015-2016, Steffen Vogel * This file is part of S2SS. All Rights Reserved. Proprietary and confidential. * Unauthorized copying of this file, via any medium is strictly prohibited. - **********************************************************************************/ + */ +/** + * @addtogroup fpga VILLASfpga + * @{ + */ -#ifndef _FPGA_INTC_H_ -#define _FPGA_INTC_H_ +#pragma once #include @@ -25,14 +28,14 @@ struct intc { int flags[32]; /**< Mask of intc_flags */ }; -int intc_init(struct ip *c); +int intc_init(struct fpga_ip *c); -void intc_destroy(struct ip *c); +int intc_destroy(struct fpga_ip *c); -int intc_enable(struct ip *c, uint32_t mask, int poll); +int intc_enable(struct fpga_ip *c, uint32_t mask, int poll); -int intc_disable(struct ip *c, uint32_t mask); +int intc_disable(struct fpga_ip *c, uint32_t mask); -uint64_t intc_wait(struct ip *c, int irq); +uint64_t intc_wait(struct fpga_ip *c, int irq); -#endif /* _FPGA_INTC_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/model.h b/include/villas/fpga/ips/model.h similarity index 82% rename from include/villas/fpga/model.h rename to include/villas/fpga/ips/model.h index 5270d626a..a5387e6c7 100644 --- a/include/villas/fpga/model.h +++ b/include/villas/fpga/ips/model.h @@ -5,10 +5,13 @@ * @copyright 2016, Steffen Vogel * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. * Unauthorized copying of this file, via any medium is strictly prohibited. - *********************************************************************************/ - -#ifndef _FPGA_MODEL_H_ -#define _FPGA_MODEL_H_ + */ +/** + * @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once #include #include @@ -85,26 +88,26 @@ struct model_param { union model_param_value default_value; - struct ip *ip; /**< A pointer to the model structure to which this parameters belongs to. */ + struct fpga_ip *ip; /**< A pointer to the model structure to which this parameters belongs to. */ }; /** Initialize a model */ -int model_init(struct ip *c); +int model_init(struct fpga_ip *c); /** Parse model */ -int model_parse(struct ip *c); +int model_parse(struct fpga_ip *c); /** Destroy a model */ -void model_destroy(struct ip *c); +int model_destroy(struct fpga_ip *c); /** Print detailed information about the model to the screen. */ -void model_dump(struct ip *c); +void model_dump(struct fpga_ip *c); /** Add a new parameter to the model */ -void model_param_add(struct ip *c, const char *name, enum model_param_direction dir, enum model_param_type type); +void model_param_add(struct fpga_ip *c, const char *name, enum model_param_direction dir, enum model_param_type type); /** Remove an existing parameter by its name */ -int model_param_remove(struct ip *c, const char *name); +int model_param_remove(struct fpga_ip *c, const char *name); /** Read a model parameter. * @@ -123,4 +126,4 @@ int model_param_write(struct model_param *p, double v); int model_param_update(struct model_param *p, struct model_param *u); -#endif /* _FPGA_MODEL_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/rtds_axis.h b/include/villas/fpga/ips/rtds_axis.h similarity index 88% rename from include/villas/fpga/rtds_axis.h rename to include/villas/fpga/ips/rtds_axis.h index ecd6072fc..c4b8a907f 100644 --- a/include/villas/fpga/rtds_axis.h +++ b/include/villas/fpga/ips/rtds_axis.h @@ -5,12 +5,15 @@ * @copyright 2015-2016, Steffen Vogel * This file is part of S2SS. All Rights Reserved. Proprietary and confidential. * Unauthorized copying of this file, via any medium is strictly prohibited. - **********************************************************************************/ + */ +/** + * @addtogroup fpga VILLASfpga + * @{ + */ -#ifndef _FPGA_RTDS_AXIS_H_ -#define _FPGA_RTDS_AXIS_H_ +#pragma once -/* Forward declaration */ +/* Forward declarations */ struct ip; #define RTDS_HZ 100000000 // 100 MHz @@ -38,8 +41,8 @@ struct ip; /* Control register bits */ #define RTDS_AXIS_CR_DISABLE_LINK 0 /**< Disable SFP TX when set */ -void rtds_axis_dump(struct ip *c); +void rtds_axis_dump(struct fpga_ip *c); -double rtds_axis_dt(struct ip *c); +double rtds_axis_dt(struct fpga_ip *c); -#endif /* _FPGA_RTDS_AXIS_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/switch.h b/include/villas/fpga/ips/switch.h similarity index 63% rename from include/villas/fpga/switch.h rename to include/villas/fpga/ips/switch.h index fe109ad83..39de68b70 100644 --- a/include/villas/fpga/switch.h +++ b/include/villas/fpga/ips/switch.h @@ -7,10 +7,13 @@ * @copyright 2015-2016, Steffen Vogel * This file is part of S2SS. All Rights Reserved. Proprietary and confidential. * Unauthorized copying of this file, via any medium is strictly prohibited. - **********************************************************************************/ + */ +/** + * @addtogroup fpga VILLASfpga + * @{ + */ -#ifndef _FPGA_SWITCH_H_ -#define _FPGA_SWITCH_H_ +#pragma once #include @@ -33,17 +36,17 @@ struct sw { struct ip; -int switch_init(struct ip *c); +int switch_init(struct fpga_ip *c); /** Initialize paths which have been parsed by switch_parse() */ -int switch_init_paths(struct ip *c); +int switch_init_paths(struct fpga_ip *c); -void switch_destroy(struct ip *c); +int switch_destroy(struct fpga_ip *c); -int switch_parse(struct ip *c); +int switch_parse(struct fpga_ip *c); -int switch_connect(struct ip *c, struct ip *mi, struct ip *si); +int switch_connect(struct fpga_ip *c, struct fpga_ip *mi, struct fpga_ip *si); -int switch_disconnect(struct ip *c, struct ip *mi, struct ip *si); +int switch_disconnect(struct fpga_ip *c, struct fpga_ip *mi, struct fpga_ip *si); -#endif /* _FPGA_SWITCH_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/timer.h b/include/villas/fpga/ips/timer.h similarity index 73% rename from include/villas/fpga/timer.h rename to include/villas/fpga/ips/timer.h index 27cc37b98..2a83ce1d2 100644 --- a/include/villas/fpga/timer.h +++ b/include/villas/fpga/ips/timer.h @@ -7,13 +7,18 @@ * @copyright 2015-2016, Steffen Vogel * This file is part of S2SS. All Rights Reserved. Proprietary and confidential. * Unauthorized copying of this file, via any medium is strictly prohibited. - **********************************************************************************/ + */ +/** + * @addtogroup fpga VILLASfpga + * @{ + */ -#ifndef _FPGA_TIMER_H_ -#define _FPGA_TIMER_H_ +#pragma once + +#include struct timer { XTmrCtr inst; }; -#endif /* _FPGA_TIMER_H_ */ \ No newline at end of file +/** @} */ \ No newline at end of file diff --git a/include/villas/fpga/vlnv.h b/include/villas/fpga/vlnv.h new file mode 100644 index 000000000..2abf2721e --- /dev/null +++ b/include/villas/fpga/vlnv.h @@ -0,0 +1,39 @@ +/** Vendor, Library, Name, Version (VLNV) tag. + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + */ +/** + * @addtogroup fpga VILLASfpga + * @{ + */ + +#ifndef _FPGA_VLNV_H_ +#define _FPGA_VLNV_H_ + +/* 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); + +#endif /** _FPGA_VLNV_H_ @} */ \ No newline at end of file diff --git a/lib/fpga/Makefile.inc b/lib/fpga/Makefile.inc index 3881fd813..01a3188c8 100644 --- a/lib/fpga/Makefile.inc +++ b/lib/fpga/Makefile.inc @@ -1,6 +1,8 @@ # Enable VILLASfpga support when libxil is available ifndef WITHOUT_FPGA ifeq ($(shell pkg-config libxil; echo $$?),0) - LIB_SRCS += $(wildcard lib/fpga/*.c) + LIB_SRCS += $(wildcard lib/fpga/*.c) endif -endif \ No newline at end of file +endif + +-include lib/fpga/ip/Makefile.inc \ No newline at end of file diff --git a/lib/fpga/card.c b/lib/fpga/card.c new file mode 100644 index 000000000..02c5d5de6 --- /dev/null +++ b/lib/fpga/card.c @@ -0,0 +1,184 @@ +#include + +#include "config.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) +{ + int ret; + + struct pci_dev *pdev; + + fpga_card_check(c); + + if (c->state == FPGA_CARD_STATE_INITIALIZED) + return 0; + + /* Search for FPGA card */ + pdev = pci_lookup_device(pci, &c->filter); + if (!pdev) + error("Failed to find PCI device"); + + /* Attach PCIe card to VFIO container */ + ret = vfio_pci_attach(&c->vd, vc, pdev); + if (ret) + error("Failed to attach VFIO device"); + + /* Map PCIe BAR */ + c->map = vfio_map_region(&c->vd, 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->vd); + if (ret) + serror("Failed to enable PCI device"); + + /* Reset system? */ + if (c->do_reset) { + /* Reset / detect PCI device */ + ret = vfio_pci_reset(&c->vd); + if (ret) + serror("Failed to reset PCI device"); + + ret = fpga_card_reset(c); + if (ret) + error("Failed to reset FGPA card"); + } + + /* Initialize IP cores */ + list_foreach(struct fpga_ip *i, &c->ips) { + ret = fpga_ip_init(i); + if (ret) + error("Failed to initalize IP core: %s (%u)", i->name, ret); + } + + return 0; +} + +int fpga_card_parse(struct fpga_card *c, config_setting_t *cfg) +{ + int ret; + const char *slot, *id, *err; + config_setting_t *cfg_ips, *cfg_slot, *cfg_id; + + /* Default values */ + c->filter.id.vendor = FPGA_PCI_VID_XILINX; + c->filter.id.device = FPGA_PCI_PID_VFPGA; + + c->name = config_setting_name(cfg); + c->state = FPGA_CARD_STATE_UNKOWN; + + if (!config_setting_lookup_int(cfg, "affinity", &c->affinity)) + c->affinity = 0; + + if (!config_setting_lookup_bool(cfg, "do_reset", &c->do_reset)) + c->do_reset = 0; + + cfg_slot = config_setting_get_member(cfg, "slot"); + if (cfg_slot) { + slot = config_setting_get_string(cfg_slot); + if (slot) { + ret = pci_dev_parse_slot(&c->filter, slot, &err); + if (ret) + cerror(cfg_slot, "Failed to parse PCI slot: %s", err); + } + else + cerror(cfg_slot, "PCI slot must be a string"); + } + + cfg_id = config_setting_get_member(cfg, "id"); + if (cfg_id) { + id = config_setting_get_string(cfg_id); + if (id) { + ret = pci_dev_parse_id(&c->filter, (char*) id, &err); + if (ret) + cerror(cfg_id, "Failed to parse PCI id: %s", err); + } + else + cerror(cfg_slot, "PCI ID must be a string"); + } + + cfg_ips = config_setting_get_member(cfg, "ips"); + if (!cfg_ips) + cerror(cfg, "FPGA configuration is missing ips section"); + + for (int i = 0; i < config_setting_length(cfg_ips); i++) { + config_setting_t *cfg_ip = config_setting_get_elem(cfg_ips, i); + + struct fpga_ip ip = { + .card = c + }; + + ret = fpga_ip_parse(&ip, cfg_ip); + if (ret) + cerror(cfg_ip, "Failed to parse VILLASfpga IP core"); + + list_push(&c->ips, memdup(&ip, sizeof(ip))); + } + + c->cfg = cfg; + + return 0; +} + +int fpga_card_check(struct fpga_card *c) +{ + /* 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->vd.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->vd.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 = FPGA_CARD_STATE_RESETTED; + + return 0; +} \ No newline at end of file diff --git a/lib/fpga/ip.c b/lib/fpga/ip.c index 4bb87f07c..9fcf16ae0 100644 --- a/lib/fpga/ip.c +++ b/lib/fpga/ip.c @@ -1,48 +1,9 @@ -#include -#include - #include #include "log.h" +#include "plugin.h" -#include "fpga/ip.h" -#include "fpga/intc.h" -#include "fpga/fifo.h" -#include "nodes/fpga.h" - -#include "config.h" - -int ip_vlnv_cmp(struct ip_vlnv *a, struct ip_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 ip_vlnv_parse(struct ip_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; -} - -void ip_vlnv_destroy(struct ip_vlnv *v) -{ - free(c->vendor); - free(c->library); - free(c->name); - free(c->version); -} - -int ip_init(struct ip *c) +int fpga_ip_init(struct fpga_ip *c) { int ret; @@ -58,22 +19,24 @@ int ip_init(struct ip *c) return ret; } -int ip_reset(struct ip *c) +int fpga_ip_reset(struct fpga_ip *c) { debug(3, "Reset IP core: %s", c->name); return c->_vt && c->_vt->reset ? c->_vt->reset(c) : 0; } -void ip_destroy(struct ip *c) +int fpga_ip_destroy(struct fpga_ip *c) { if (c->_vt && c->_vt->destroy) c->_vt->destroy(c); - ip_vlnv_destroy(c->vlnv); + fpga_vlnv_destroy(&c->vlnv); + + return 0; } -void ip_dump(struct ip *c) +void fpga_ip_dump(struct fpga_ip *c) { 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, @@ -83,7 +46,7 @@ void ip_dump(struct ip *c) c->_vt->dump(c); } -int ip_parse(struct ip *c, config_setting_t *cfg) +int fpga_ip_parse(struct fpga_ip *c, config_setting_t *cfg) { int ret; const char *vlnv; @@ -98,15 +61,15 @@ int ip_parse(struct ip *c, config_setting_t *cfg) if (!config_setting_lookup_string(cfg, "vlnv", &vlnv)) cerror(cfg, "IP %s is missing the VLNV identifier", c->name); - ret = ip_vlnv_parse(&c->vlnv, vlnv); + ret = fpga_vlnv_parse(&c->vlnv, vlnv); if (ret) cerror(cfg, "Failed to parse VLNV identifier"); /* Try to find matching IP type */ list_foreach(struct plugin *l, &plugins) { if (l->type == PLUGIN_TYPE_FPGA_IP && - !ip_vlnv_match(&c->ip.vlnv, &l->ip.vlnv)) { - c->_vt = t; + !fpga_vlnv_cmp(&c->vlnv, &l->ip.vlnv)) { + c->_vt = &l->ip; break; } } diff --git a/lib/fpga/ips/Makefile.inc b/lib/fpga/ips/Makefile.inc new file mode 100644 index 000000000..54f1d72eb --- /dev/null +++ b/lib/fpga/ips/Makefile.inc @@ -0,0 +1,6 @@ +# Enable VILLASfpga support when libxil is available +ifndef WITHOUT_FPGA +ifeq ($(shell pkg-config libxil; echo $$?),0) + LIB_SRCS += $(wildcard lib/fpga/ips/*.c) +endif +endif \ No newline at end of file diff --git a/lib/fpga/dft.c b/lib/fpga/ips/dft.c similarity index 87% rename from lib/fpga/dft.c rename to lib/fpga/ips/dft.c index db5b4be16..652621f6b 100644 --- a/lib/fpga/dft.c +++ b/lib/fpga/ips/dft.c @@ -11,9 +11,10 @@ #include "plugin.h" #include "fpga/ip.h" -#include "fpga/dft.h" +#include "fpga/card.h" +#include "fpga/ips/dft.h" -int dft_parse(struct ip *c) +int dft_parse(struct fpga_ip *c) { struct dft *dft = &c->dft; @@ -44,13 +45,16 @@ int dft_parse(struct ip *c) return 0; } -int dft_init(struct ip *c) +int dft_init(struct fpga_ip *c) { int ret; + + struct fpga_card *f = c->card; struct dft *dft = &c->dft; + XHls_dft *xdft = &dft->inst; XHls_dft_Config xdft_cfg = { - .Ctrl_BaseAddress = (uintptr_t) c->card->map + c->baseaddr + .Ctrl_BaseAddress = (uintptr_t) f->map + c->baseaddr }; ret = XHls_dft_CfgInitialize(xdft, &xdft_cfg); @@ -74,7 +78,7 @@ int dft_init(struct ip *c) return 0; } -void dft_destroy(struct ip *c) +int dft_destroy(struct fpga_ip *c) { struct dft *dft = &c->dft; XHls_dft *xdft = &dft->inst; @@ -85,6 +89,8 @@ void dft_destroy(struct ip *c) free(dft->fharmonics); dft->fharmonics = NULL; } + + return 0; } static struct plugin p = { @@ -92,10 +98,11 @@ static struct plugin p = { .description = "Perfom Discrete Fourier Transforms with variable number of harmonics on the FPGA", .type = PLUGIN_TYPE_FPGA_IP, .ip = { - .vlnv = { "acs.eonerc.rwth-aachen.de", "hls", "hls_dft", NULL }, - .init = dft_init, + .vlnv = { "acs.eonerc.rwth-aachen.de", "hls", "hls_dft", NULL }, + .type = FPGA_IP_TYPE_MATH, + .init = dft_init, .destroy = dft_destroy, - .parse = dft_parse + .parse = dft_parse } }; diff --git a/lib/fpga/dma.c b/lib/fpga/ips/dma.c similarity index 89% rename from lib/fpga/dma.c rename to lib/fpga/ips/dma.c index ebfdbadc7..3ca509dab 100644 --- a/lib/fpga/dma.c +++ b/lib/fpga/ips/dma.c @@ -17,8 +17,9 @@ #include "plugin.h" #include "utils.h" -#include "fpga/dma.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) { @@ -36,9 +37,11 @@ int dma_mem_split(struct dma_mem *o, struct dma_mem *a, struct dma_mem *b) return 0; } -int dma_alloc(struct ip *c, struct dma_mem *mem, size_t len, int flags) +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) { @@ -52,18 +55,18 @@ int dma_alloc(struct ip *c, struct dma_mem *mem, size_t len, int flags) if (mem->base_virt == MAP_FAILED) return -1; - ret = vfio_map_dma(c->card->vd.group->container, mem); + ret = vfio_map_dma(f->vd.group->container, (uint64_t) mem->base_virt, (uint64_t) mem->base_phys, mem->len); if (ret) return -2; return 0; } -int dma_free(struct ip *c, struct dma_mem *mem) +int dma_free(struct fpga_ip *c, struct dma_mem *mem) { int ret; - ret = vfio_unmap_dma(c->card->vd.group->container, mem); + ret = vfio_unmap_dma(c->card->vd.group->container, (uint64_t) mem->base_virt, (uint64_t) mem->base_phys, mem->len); if (ret) return ret; @@ -74,7 +77,7 @@ int dma_free(struct ip *c, struct dma_mem *mem) return 0; } -int dma_ping_pong(struct ip *c, char *src, char *dst, size_t len) +int dma_ping_pong(struct fpga_ip *c, char *src, char *dst, size_t len) { int ret; @@ -97,7 +100,7 @@ int dma_ping_pong(struct ip *c, char *src, char *dst, size_t len) return 0; } -int dma_write(struct ip *c, char *buf, size_t len) +int dma_write(struct fpga_ip *c, char *buf, size_t len) { XAxiDma *xdma = &c->dma.inst; @@ -108,7 +111,7 @@ int dma_write(struct ip *c, char *buf, size_t len) : dma_simple_write(c, buf, len); } -int dma_read(struct ip *c, char *buf, size_t len) +int dma_read(struct fpga_ip *c, char *buf, size_t len) { XAxiDma *xdma = &c->dma.inst; @@ -119,7 +122,7 @@ int dma_read(struct ip *c, char *buf, size_t len) : dma_simple_read(c, buf, len); } -int dma_read_complete(struct ip *c, char **buf, size_t *len) +int dma_read_complete(struct fpga_ip *c, char **buf, size_t *len) { XAxiDma *xdma = &c->dma.inst; @@ -130,7 +133,7 @@ int dma_read_complete(struct ip *c, char **buf, size_t *len) : dma_simple_read_complete(c, buf, len); } -int dma_write_complete(struct ip *c, char **buf, size_t *len) +int dma_write_complete(struct fpga_ip *c, char **buf, size_t *len) { XAxiDma *xdma = &c->dma.inst; @@ -141,7 +144,7 @@ int dma_write_complete(struct ip *c, char **buf, size_t *len) : dma_simple_write_complete(c, buf, len); } -int dma_sg_write(struct ip *c, char *buf, size_t len) +int dma_sg_write(struct fpga_ip *c, char *buf, size_t len) { int ret, bdcnt; @@ -216,7 +219,7 @@ out: return -5; } -int dma_sg_read(struct ip *c, char *buf, size_t len) +int dma_sg_read(struct fpga_ip *c, char *buf, size_t len) { int ret, bdcnt; @@ -284,7 +287,7 @@ out: return -5; } -int dma_sg_write_complete(struct ip *c, char **buf, size_t *len) +int dma_sg_write_complete(struct fpga_ip *c, char **buf, size_t *len) { XAxiDma *xdma = &c->dma.inst; XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); @@ -313,7 +316,7 @@ int dma_sg_write_complete(struct ip *c, char **buf, size_t *len) return 0; } -int dma_sg_read_complete(struct ip *c, char **buf, size_t *len) +int dma_sg_read_complete(struct fpga_ip *c, char **buf, size_t *len) { XAxiDma *xdma = &c->dma.inst; XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); @@ -365,7 +368,7 @@ int dma_sg_read_complete(struct ip *c, char **buf, size_t *len) return 0; } -int dma_simple_read(struct ip *c, char *buf, size_t len) +int dma_simple_read(struct fpga_ip *c, char *buf, size_t len) { XAxiDma *xdma = &c->dma.inst; XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); @@ -401,7 +404,7 @@ int dma_simple_read(struct ip *c, char *buf, size_t len) return XST_SUCCESS; } -int dma_simple_write(struct ip *c, char *buf, size_t len) +int dma_simple_write(struct fpga_ip *c, char *buf, size_t len) { XAxiDma *xdma = &c->dma.inst; XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); @@ -438,7 +441,7 @@ int dma_simple_write(struct ip *c, char *buf, size_t len) return XST_SUCCESS; } -int dma_simple_read_complete(struct ip *c, char **buf, size_t *len) +int dma_simple_read_complete(struct fpga_ip *c, char **buf, size_t *len) { XAxiDma *xdma = &c->dma.inst; XAxiDma_BdRing *ring = XAxiDma_GetRxRing(xdma); @@ -459,7 +462,7 @@ int dma_simple_read_complete(struct ip *c, char **buf, size_t *len) return 0; } -int dma_simple_write_complete(struct ip *c, char **buf, size_t *len) +int dma_simple_write_complete(struct fpga_ip *c, char **buf, size_t *len) { XAxiDma *xdma = &c->dma.inst; XAxiDma_BdRing *ring = XAxiDma_GetTxRing(xdma); @@ -535,7 +538,7 @@ static int dma_init_rings(XAxiDma *xdma, struct dma_mem *bd) return 0; } -int dma_init(struct ip *c) +int dma_init(struct fpga_ip *c) { int ret, sg; struct dma *dma = &c->dma; @@ -590,7 +593,7 @@ int dma_init(struct ip *c) return 0; } -int dma_reset(struct ip *c) +int dma_reset(struct fpga_ip *c) { XAxiDma_Reset(&c->dma.inst); @@ -602,9 +605,10 @@ static struct plugin p = { .description = "Transfer data streams between VILLASnode and VILLASfpga", .type = PLUGIN_TYPE_FPGA_IP, .ip = { - .vlnv = { "xilinx.com", "ip", "axi_dma", NULL }, - .init = dma_init, - .reset = dma_reset + .vlnv = { "xilinx.com", "ip", "axi_dma", NULL }, + .type = FPGA_IP_TYPE_DATAMOVER, + .init = dma_init, + .reset = dma_reset } }; diff --git a/lib/fpga/fifo.c b/lib/fpga/ips/fifo.c similarity index 78% rename from lib/fpga/fifo.c rename to lib/fpga/ips/fifo.c index fab633588..d912b60e6 100644 --- a/lib/fpga/fifo.c +++ b/lib/fpga/ips/fifo.c @@ -14,18 +14,20 @@ #include "plugin.h" #include "fpga/ip.h" -#include "fpga/fifo.h" -#include "fpga/intc.h" +#include "fpga/card.h" +#include "fpga/ips/fifo.h" +#include "fpga/ips/intc.h" -int fifo_init(struct ip *c) +int fifo_init(struct fpga_ip *c) { - struct fifo *fifo = &c->fifo; - XLlFifo *xfifo = &fifo->inst; - int ret; + struct fpga_card *f = c->card; + struct fifo *fifo = &c->fifo; + + XLlFifo *xfifo = &fifo->inst; XLlFifo_Config fifo_cfg = { - .BaseAddress = (uintptr_t) c->card->map + c->baseaddr, + .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 */ }; @@ -39,7 +41,7 @@ int fifo_init(struct ip *c) return 0; } -ssize_t fifo_write(struct ip *c, char *buf, size_t len) +ssize_t fifo_write(struct fpga_ip *c, char *buf, size_t len) { XLlFifo *fifo = &c->fifo.inst; uint32_t tdfv; @@ -54,7 +56,7 @@ ssize_t fifo_write(struct ip *c, char *buf, size_t len) return len; } -ssize_t fifo_read(struct ip *c, char *buf, size_t len) +ssize_t fifo_read(struct fpga_ip *c, char *buf, size_t len) { XLlFifo *fifo = &c->fifo.inst; @@ -75,7 +77,7 @@ ssize_t fifo_read(struct ip *c, char *buf, size_t len) return nextlen; } -int fifo_parse(struct ip *c) +int fifo_parse(struct fpga_ip *c) { struct fifo *fifo = &c->fifo; @@ -89,7 +91,7 @@ int fifo_parse(struct ip *c) return 0; } -int fifo_reset(struct ip *c) +int fifo_reset(struct fpga_ip *c) { XLlFifo_Reset(&c->fifo.inst); @@ -101,10 +103,11 @@ static struct plugin p = { .description = "", .type = PLUGIN_TYPE_FPGA_IP, .ip = { - .vlnv = { "xilinx.com", "ip", "axi_fifo_mm_s", NULL }, - .init = fifo_init, - .parse = fifo_parse, - .reset = fifo_reset + .vlnv = { "xilinx.com", "ip", "axi_fifo_mm_s", NULL }, + .type = FPGA_IP_TYPE_DATAMOVER, + .init = fifo_init, + .parse = fifo_parse, + .reset = fifo_reset } }; diff --git a/lib/fpga/intc.c b/lib/fpga/ips/intc.c similarity index 86% rename from lib/fpga/intc.c rename to lib/fpga/ips/intc.c index 0e0e32b7d..6c9abf012 100644 --- a/lib/fpga/intc.c +++ b/lib/fpga/ips/intc.c @@ -18,13 +18,14 @@ #include "kernel/kernel.h" #include "fpga/ip.h" -#include "fpga/intc.h" +#include "fpga/card.h" +#include "fpga/ips/intc.h" -int intc_init(struct ip *c) +int intc_init(struct fpga_ip *c) { int ret; - struct fpga *f = c->card; + struct fpga_card *f = c->card; struct intc *intc = &c->intc; uintptr_t base = (uintptr_t) f->map + c->baseaddr; @@ -62,18 +63,20 @@ int intc_init(struct ip *c) return 0; } -void intc_destroy(struct ip *c) +int intc_destroy(struct fpga_ip *c) { - struct fpga *f = c->card; + struct fpga_card *f = c->card; struct intc *intc = &c->intc; vfio_pci_msi_deinit(&f->vd, intc->efds); + + return 0; } -int intc_enable(struct ip *c, uint32_t mask, int flags) +int intc_enable(struct fpga_ip *c, uint32_t mask, int flags) { + struct fpga_card *f = c->card; struct intc *intc = &c->intc; - struct fpga *f = c->card; uint32_t ier, imr; uintptr_t base = (uintptr_t) f->map + c->baseaddr; @@ -108,9 +111,9 @@ int intc_enable(struct ip *c, uint32_t mask, int flags) return 0; } -int intc_disable(struct ip *c, uint32_t mask) +int intc_disable(struct fpga_ip *c, uint32_t mask) { - struct fpga *f = c->card; + struct fpga_card *f = c->card; uintptr_t base = (uintptr_t) f->map + c->baseaddr; uint32_t ier = XIntc_In32(base + XIN_IER_OFFSET); @@ -120,10 +123,10 @@ int intc_disable(struct ip *c, uint32_t mask) return 0; } -uint64_t intc_wait(struct ip *c, int irq) +uint64_t intc_wait(struct fpga_ip *c, int irq) { + struct fpga_card *f = c->card; struct intc *intc = &c->intc; - struct fpga *f = c->card; uintptr_t base = (uintptr_t) f->map + c->baseaddr; @@ -154,8 +157,9 @@ static struct plugin p = { .description = "", .type = PLUGIN_TYPE_FPGA_IP, .ip = { - .vlnv = { "acs.eonerc.rwth-aachen.de", "user", "axi_pcie_intc", NULL }, - .init = intc_init, + .vlnv = { "acs.eonerc.rwth-aachen.de", "user", "axi_pcie_intc", NULL }, + .type = FPGA_IP_TYPE_MISC, + .init = intc_init, .destroy = intc_destroy } }; diff --git a/lib/fpga/model.c b/lib/fpga/ips/model.c similarity index 89% rename from lib/fpga/model.c rename to lib/fpga/ips/model.c index 6c7f8366f..9806cdeb9 100644 --- a/lib/fpga/model.c +++ b/lib/fpga/ips/model.c @@ -16,17 +16,22 @@ #include "plugin.h" #include "fpga/ip.h" -#include "fpga/model.h" +#include "fpga/card.h" +#include "fpga/ips/model.h" -static void model_param_destroy(struct model_param *p) +static int model_param_destroy(struct model_param *p) { free(p->name); + + return 0; } -static void model_info_destroy(struct model_info *i) +static int model_info_destroy(struct model_info *i) { free(i->field); free(i->value); + + return 0; } static uint32_t model_xsg_map_checksum(uint32_t *map, size_t len) @@ -130,7 +135,7 @@ static int model_xsg_map_read(uint32_t *map, size_t len, void *baseaddr) return i; } -int model_parse(struct ip *c) +int model_parse(struct fpga_ip *c) { struct model *m = &c->model; struct model_param p; @@ -188,7 +193,7 @@ static int model_init_from_xsg_map(struct model *m, void *baseaddr) return 0; } -int model_init(struct ip *c) +int model_init(struct fpga_ip *c) { int ret; struct model *m = &c->model; @@ -196,7 +201,7 @@ int model_init(struct ip *c) list_init(&m->parameters); list_init(&m->infos); - if (ip_vlnv_match(c, NULL, "sysgen", NULL, NULL)) + if (!fpga_vlnv_cmp(&c->vlnv, &(struct fpga_vlnv) { NULL, "sysgen", NULL, NULL })) ret = model_init_from_xsg_map(m, c->card->map + c->baseaddr); else ret = 0; @@ -217,7 +222,7 @@ int model_init(struct ip *c) return 0; } -void model_destroy(struct ip *c) +int model_destroy(struct fpga_ip *c) { struct model *m = &c->model; @@ -226,9 +231,11 @@ void model_destroy(struct ip *c) if (m->xsg.map != NULL) free(m->xsg.map); + + return 0; } -void model_dump(struct ip *c) +void model_dump(struct fpga_ip *c) { struct model *m = &c->model; @@ -264,7 +271,7 @@ void model_dump(struct ip *c) int model_param_read(struct model_param *p, double *v) { - struct ip *c = p->ip; + struct fpga_ip *c = p->ip; union model_param_value *ptr = (union model_param_value *) (c->card->map + c->baseaddr + p->offset); @@ -290,7 +297,7 @@ int model_param_read(struct model_param *p, double *v) int model_param_write(struct model_param *p, double v) { - struct ip *c = p->ip; + struct fpga_ip *c = p->ip; union model_param_value *ptr = (union model_param_value *) (c->card->map + c->baseaddr + p->offset); @@ -315,7 +322,7 @@ int model_param_write(struct model_param *p, double v) return 0; } -void model_param_add(struct ip *c, const char *name, enum model_param_direction dir, enum model_param_type type) +void model_param_add(struct fpga_ip *c, const char *name, enum model_param_direction dir, enum model_param_type type) { struct model *m = &c->model; struct model_param *p = alloc(sizeof(struct model_param)); @@ -327,7 +334,7 @@ void model_param_add(struct ip *c, const char *name, enum model_param_direction list_push(&m->parameters, p); } -int model_param_remove(struct ip *c, const char *name) +int model_param_remove(struct fpga_ip *c, const char *name) { struct model *m = &c->model; struct model_param *p; @@ -359,11 +366,12 @@ static struct plugin p_hls = { .description = "", .type = PLUGIN_TYPE_FPGA_IP, .ip = { - .vlnv = { NULL, "hls", NULL, NULL }, - .init = model_init, + .vlnv = { NULL, "hls", NULL, NULL }, + .type = FPGA_IP_TYPE_MODEL, + .init = model_init, .destroy = model_destroy, - .dump = model_dump, - .parse = model_parse + .dump = model_dump, + .parse = model_parse } }; @@ -374,11 +382,12 @@ static struct plugin p_sysgen = { .description = "", .type = PLUGIN_TYPE_FPGA_IP, .ip = { - .vlnv = { NULL, "sysgen", NULL, NULL }, - .init = model_init, + .vlnv = { NULL, "sysgen", NULL, NULL }, + .type = FPGA_IP_TYPE_MODEL, + .init = model_init, .destroy = model_destroy, - .dump = model_dump, - .parse = model_parse + .dump = model_dump, + .parse= model_parse } }; diff --git a/lib/fpga/rtds_axis.c b/lib/fpga/ips/rtds_axis.c similarity index 88% rename from lib/fpga/rtds_axis.c rename to lib/fpga/ips/rtds_axis.c index ebb2e1ef6..3bc9372ae 100644 --- a/lib/fpga/rtds_axis.c +++ b/lib/fpga/ips/rtds_axis.c @@ -13,9 +13,10 @@ #include "plugin.h" #include "fpga/ip.h" -#include "fpga/rtds_axis.h" +#include "fpga/card.h" +#include "fpga/ips/rtds_axis.h" -void rtds_axis_dump(struct ip *c) +void rtds_axis_dump(struct fpga_ip *c) { /* Check RTDS_Axis registers */ uint32_t *regs = (uint32_t *) (c->card->map + c->baseaddr); @@ -42,7 +43,7 @@ void rtds_axis_dump(struct ip *c) } } -double rtds_axis_dt(struct ip *c) +double rtds_axis_dt(struct fpga_ip *c) { uint32_t *regs = (uint32_t *) (c->card->map + c->baseaddr); uint16_t dt = regs[RTDS_AXIS_TS_PERIOD_OFFSET/4]; @@ -55,8 +56,9 @@ static struct plugin p = { .description = "", .type = PLUGIN_TYPE_FPGA_IP, .ip = { - .vlnv = { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL }, - .dump = rtds_axis_dump + .vlnv = { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL }, + .type = FPGA_IP_TYPE_INTERFACE, + .dump = rtds_axis_dump } }; diff --git a/lib/fpga/switch.c b/lib/fpga/ips/switch.c similarity index 85% rename from lib/fpga/switch.c rename to lib/fpga/ips/switch.c index 6ba664ccb..a5b1d79ce 100644 --- a/lib/fpga/switch.c +++ b/lib/fpga/ips/switch.c @@ -12,14 +12,16 @@ #include "log.h" #include "plugin.h" -#include "fpga/switch.h" #include "fpga/ip.h" +#include "fpga/card.h" +#include "fpga/ips/switch.h" -int switch_init(struct ip *c) +int switch_init(struct fpga_ip *c) { int ret; + + struct fpga_card *f = c->card; struct sw *sw = &c->sw; - struct fpga *f = c->card; XAxis_Switch *xsw = &sw->inst; @@ -29,7 +31,7 @@ int switch_init(struct ip *c) /* Setup AXI-stream switch */ XAxis_Switch_Config sw_cfg = { - .BaseAddress = (uintptr_t) c->card->map + c->baseaddr, + .BaseAddress = (uintptr_t) f->map + c->baseaddr, .MaxNumMI = sw->num_ports, .MaxNumSI = sw->num_ports }; @@ -42,11 +44,13 @@ int switch_init(struct ip *c) XAxisScr_RegUpdateDisable(xsw); XAxisScr_MiPortDisableAll(xsw); XAxisScr_RegUpdateEnable(xsw); + + switch_init_paths(c); return 0; } -int switch_init_paths(struct ip *c) +int switch_init_paths(struct fpga_ip *c) { int ret; struct sw *sw = &c->sw; @@ -57,7 +61,7 @@ int switch_init_paths(struct ip *c) XAxisScr_MiPortDisableAll(xsw); list_foreach(struct sw_path *p, &sw->paths) { - struct ip *mi, *si; + struct fpga_ip *mi, *si; mi = list_lookup(&c->card->ips, p->out); si = list_lookup(&c->card->ips, p->in); @@ -75,15 +79,18 @@ int switch_init_paths(struct ip *c) return 0; } -void switch_destroy(struct ip *c) +int switch_destroy(struct fpga_ip *c) { struct sw *sw = &c->sw; list_destroy(&sw->paths, NULL, true); + + return 0; } -int switch_parse(struct ip *c) +int switch_parse(struct fpga_ip *c) { + struct fpga_card *f = c->card; struct sw *sw = &c->sw; list_init(&sw->paths); @@ -93,7 +100,7 @@ int switch_parse(struct ip *c) if (!config_setting_lookup_int(c->cfg, "num_ports", &sw->num_ports)) cerror(c->cfg, "Switch IP '%s' requires 'num_ports' option", c->name); - cfg_sw = config_setting_get_member(c->card->cfg, "paths"); + cfg_sw = config_setting_get_member(f->cfg, "paths"); if (!cfg_sw) return 0; /* no switch config available */ @@ -133,7 +140,7 @@ int switch_parse(struct ip *c) return 0; } -int switch_connect(struct ip *c, struct ip *mi, struct ip *si) +int switch_connect(struct fpga_ip *c, struct fpga_ip *mi, struct fpga_ip *si) { struct sw *sw = &c->sw; XAxis_Switch *xsw = &sw->inst; @@ -169,7 +176,7 @@ int switch_connect(struct ip *c, struct ip *mi, struct ip *si) return 0; } -int switch_disconnect(struct ip *c, struct ip *mi, struct ip *si) +int switch_disconnect(struct fpga_ip *c, struct fpga_ip *mi, struct fpga_ip *si) { struct sw *sw = &c->sw; XAxis_Switch *xsw = &sw->inst; @@ -187,10 +194,11 @@ static struct plugin p = { .description = "", .type = PLUGIN_TYPE_FPGA_IP, .ip = { - .vlnv = { "xilinx.com", "ip", "axis_interconnect", NULL }, - .init = switch_init, + .vlnv = { "xilinx.com", "ip", "axis_interconnect", NULL }, + .type = FPGA_IP_TYPE_MISC, + .init = switch_init, .destroy = switch_destroy, - .parse = switch_parse + .parse = switch_parse } }; diff --git a/lib/fpga/timer.c b/lib/fpga/ips/timer.c similarity index 82% rename from lib/fpga/timer.c rename to lib/fpga/ips/timer.c index 051eeb6b7..15de04544 100644 --- a/lib/fpga/timer.c +++ b/lib/fpga/ips/timer.c @@ -13,12 +13,13 @@ #include "plugin.h" #include "fpga/ip.h" -#include "fpga/timer.h" +#include "fpga/card.h" +#include "fpga/ips/timer.h" -int timer_init(struct ip *c) +int timer_init(struct fpga_ip *c) { + struct fpga_card *f = c->card; struct timer *tmr = &c->timer; - struct fpga *f = c->card; XTmrCtr *xtmr = &tmr->inst; XTmrCtr_Config xtmr_cfg = { @@ -37,8 +38,9 @@ static struct plugin p = { .description = "", .type = PLUGIN_TYPE_FPGA_IP, .ip = { - .vlnv = { "xilinx.com", "ip", "axi_timer", NULL }, - .init = timer_init + .vlnv = { "xilinx.com", "ip", "axi_timer", NULL }, + .type = FPGA_IP_TYPE_MISC, + .init = timer_init } }; diff --git a/lib/fpga/vlnv.c b/lib/fpga/vlnv.c new file mode 100644 index 000000000..e656fea43 --- /dev/null +++ b/lib/fpga/vlnv.c @@ -0,0 +1,45 @@ +/** Vendor, Library, Name, Version (VLNV) tag + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + */ + +#include +#include + +#include "fpga/vlnv.h" + +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; +} diff --git a/lib/nodes/fpga.c b/lib/nodes/fpga.c index 0c71f3070..7e5487e3e 100644 --- a/lib/nodes/fpga.c +++ b/lib/nodes/fpga.c @@ -19,73 +19,38 @@ #include "timing.h" #include "plugin.h" -struct fpga fpga; -struct pci pci; -struct vfio_container vc; +#include "fpga/card.h" -int fpga_reset(struct fpga *f) -{ - int ret; - char state[4096]; - - /* Save current state of PCI configuration space */ - ret = pread(f->vd.fd, state, sizeof(state), (off_t) VFIO_PCI_CONFIG_REGION_INDEX << 40); - if (ret != sizeof(state)) - return -1; - - uint32_t *rst_reg = (uint32_t *) (f->map + f->reset->baseaddr); - - debug(3, "FPGA: reset"); - rst_reg[0] = 1; - - usleep(100000); - - /* Restore previous state of PCI configuration space */ - ret = pwrite(f->vd.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; - - return 0; -} +static struct list cards; +static struct pci pci; +static struct vfio_container vc; void fpga_dump(struct fpga *f) { + struct fpga_card *c = f->ip->card; + info("VILLASfpga card:"); { INDENT - info("Slot: %04x:%02x:%02x.%d", fpga.vd.pdev->slot.domain, fpga.vd.pdev->slot.bus, fpga.vd.pdev->slot.device, fpga.vd.pdev->slot.function); - info("Vendor ID: %04x", fpga.vd.pdev->id.vendor); - info("Device ID: %04x", fpga.vd.pdev->id.device); - info("Class ID: %04x", fpga.vd.pdev->id.class); + info("Slot: %04x:%02x:%02x.%d", c->vd.pdev->slot.domain, c->vd.pdev->slot.bus, c->vd.pdev->slot.device, c->vd.pdev->slot.function); + info("Vendor ID: %04x", c->vd.pdev->id.vendor); + info("Device ID: %04x", c->vd.pdev->id.device); + info("Class ID: %04x", c->vd.pdev->id.class); - info("BAR0 mapped at %p", fpga.map); + info("BAR0 mapped at %p", c->map); info("IP blocks:"); - list_foreach(struct ip *i, &f->ips) { INDENT - ip_dump(i); + list_foreach(struct fpga_ip *i, &c->ips) { INDENT + fpga_ip_dump(i); } } - vfio_dump(fpga.vd.group->container); + vfio_dump(c->vd.group->container); } -struct fpga * fpga_get() -{ - return &fpga; -} - -int fpga_parse_card(struct fpga *f, int argc, char * argv[], config_setting_t *cfg) +int fpga_parse_cards(config_setting_t *cfg) { int ret; - const char *slot, *id, *err; - config_setting_t *cfg_ips, *cfg_slot, *cfg_id, *cfg_fpgas; - - /* Default values */ - f->filter.id.vendor = FPGA_PCI_VID_XILINX; - f->filter.id.device = FPGA_PCI_PID_VFPGA; + config_setting_t *cfg_fpgas; cfg_fpgas = config_setting_get_member(cfg, "fpgas"); if (!cfg_fpgas) @@ -94,56 +59,16 @@ int fpga_parse_card(struct fpga *f, int argc, char * argv[], config_setting_t *c if (!config_setting_is_group(cfg_fpgas)) cerror(cfg_fpgas, "FPGA configuration section must be a group"); - if (config_setting_length(cfg_fpgas) != 1) - cerror(cfg_fpgas, "Currently, only a single FPGA is currently supported."); - - f->cfg = config_setting_get_elem(cfg_fpgas, 0); - - if (!config_setting_lookup_int(cfg, "affinity", &f->affinity)) - f->affinity = 0; - - config_setting_lookup_bool(f->cfg, "do_reset", &f->do_reset); - - cfg_slot = config_setting_get_member(f->cfg, "slot"); - if (cfg_slot) { - slot = config_setting_get_string(cfg_slot); - if (slot) { - ret = pci_dev_parse_slot(&f->filter, slot, &err); - if (ret) - cerror(cfg_slot, "Failed to parse PCI slot: %s", err); - } - else - cerror(cfg_slot, "PCI slot must be a string"); - } - - cfg_id = config_setting_get_member(f->cfg, "id"); - if (cfg_id) { - id = config_setting_get_string(cfg_id); - if (id) { - ret = pci_dev_parse_id(&f->filter, (char*) id, &err); - if (ret) - cerror(cfg_id, "Failed to parse PCI id: %s", err); - } - else - cerror(cfg_slot, "PCI ID must be a string"); - } - - cfg_ips = config_setting_get_member(f->cfg, "ips"); - if (!cfg_ips) - cerror(f->cfg, "FPGA configuration is missing ips section"); - - for (int i = 0; i < config_setting_length(cfg_ips); i++) { - config_setting_t *cfg_ip = config_setting_get_elem(cfg_ips, i); - - struct ip ip = { - .card = f - }; - - ret = ip_parse(&ip, cfg_ip); + for (int i = 0; i < config_setting_length(cfg_fpgas); i++) { + config_setting_t *cfg_fpga = config_setting_get_elem(cfg_fpgas, i); + + struct fpga_card *c = alloc(sizeof(struct fpga_card)); + + ret = fpga_card_parse(c, cfg_fpga); if (ret) - cerror(cfg_ip, "Failed to parse VILLASfpga IP core"); - - list_push(&f->ips, memdup(&ip, sizeof(ip))); + cerror(cfg_fpga, "Failed to parse FPGA card configuration"); + + list_push(&cards, c); } return 0; @@ -152,77 +77,19 @@ int fpga_parse_card(struct fpga *f, int argc, char * argv[], config_setting_t *c int fpga_init(int argc, char * argv[], config_setting_t *cfg) { int ret; - struct fpga *f; - struct pci_dev *pdev; - - /* For now we only support a single VILALSfpga card */ - f = fpga_get(); - list_init(&f->ips); - - pci_init(&pci); - pci_dev_init(&f->filter); - - /* Parse FPGA configuration */ - ret = fpga_parse_card(f, argc, argv, cfg); + + ret = pci_init(&pci); if (ret) - cerror(cfg, "Failed to parse VILLASfpga config"); - - /* Check FPGA configuration */ - f->reset = ip_vlnv_lookup(&f->ips, "xilinx.com", "ip", "axi_gpio", NULL); - if (!f->reset) - error("FPGA is missing a reset controller"); - - f->intc = ip_vlnv_lookup(&f->ips, "acs.eonerc.rwth-aachen.de", "user", "axi_pcie_intc", NULL); - if (!f->intc) - error("FPGA is missing a interrupt controller"); - - f->sw = ip_vlnv_lookup(&f->ips, "xilinx.com", "ip", "axis_interconnect", NULL); - if (!f->sw) - warn("FPGA is missing an AXI4-Stream switch"); - - /* Search for FPGA card */ - pdev = pci_lookup_device(&pci, &f->filter); - if (!pdev) - error("Failed to find PCI device"); - - /* Get VFIO handles and details */ + cerror(cfg, "Failed to initialize PCI sub-system"); + ret = vfio_init(&vc); if (ret) - serror("Failed to initialize VFIO"); + cerror(cfg, "Failed to initiliaze VFIO sub-system"); - /* Attach PCIe card to VFIO container */ - ret = vfio_pci_attach(&f->vd, &vc, pdev); + /* Parse FPGA configuration */ + ret = fpga_parse_cards(cfg); if (ret) - error("Failed to attach VFIO device"); - - /* Map PCIe BAR */ - f->map = vfio_map_region(&f->vd, VFIO_PCI_BAR0_REGION_INDEX); - if (f->map == MAP_FAILED) - serror("Failed to mmap() BAR0"); - - /* Enable memory access and PCI bus mastering for DMA */ - ret = vfio_pci_enable(&f->vd); - if (ret) - serror("Failed to enable PCI device"); - - /* Reset system? */ - if (f->do_reset) { - /* Reset / detect PCI device */ - ret = vfio_pci_reset(&f->vd); - if (ret) - serror("Failed to reset PCI device"); - - ret = fpga_reset(f); - if (ret) - error("Failed to reset FGPA card"); - } - - /* Initialize IP cores */ - list_foreach(struct ip *c, &f->ips) { - ret = ip_init(c); - if (ret) - error("Failed to initalize IP core: %s (%u)", c->name, ret); - } + cerror(cfg, "Failed to parse VILLASfpga config"); return 0; } @@ -231,53 +98,78 @@ int fpga_deinit() { int ret; - list_destroy(&fpga.ips, (dtor_cb_t) ip_destroy, true); + list_destroy(&cards, (dtor_cb_t) fpga_card_destroy, true); pci_destroy(&pci); ret = vfio_destroy(&vc); if (ret) - error("Failed to deinitialize VFIO module"); + error("Failed to deinitialize VFIO sub-system"); + + ret = pci_destroy(&pci); + if (ret) + error("Failed to deinitialize PCI sub-system"); return 0; } int fpga_parse(struct node *n, config_setting_t *cfg) { - struct fpga_dm *d = n->_vd; + struct fpga *f = n->_vd; + struct fpga_card *card; + struct fpga_ip *ip; - /* There is currently only support for a single FPGA card */ - d->card = fpga_get(); + char *cpy, *card_name, *ip_name; + const char *dm; - if (!config_setting_lookup_string(cfg, "datamover", &d->ip_name)) + if (!config_setting_lookup_string(cfg, "datamover", &dm)) cerror(cfg, "Node '%s' is missing the 'datamover' setting", node_name(n)); - if (!config_setting_lookup_bool(cfg, "use_irqs", &d->use_irqs)) - d->use_irqs = false; + if (!config_setting_lookup_bool(cfg, "use_irqs", &f->use_irqs)) + f->use_irqs = false; + + cpy = strdup(dm); /* strtok can not operate on type const char * */ + + card_name = strtok(cpy, ":"); + ip_name = strtok(NULL, ":"); + + card = list_lookup(&cards, card_name); + if (!card) + cerror(cfg, "There is no FPGA card named '%s", card_name); + + ip = list_lookup(&card->ips, ip_name); + if (!ip) + cerror(cfg, "There is no datamover named '%s' on the FPGA card '%s'", ip_name, card_name); + if (!ip->_vt->type != FPGA_IP_TYPE_DATAMOVER) + cerror(cfg, "The IP '%s' on FPGA card '%s' is not a datamover", ip_name, card_name); + + free(cpy); + + f->ip = ip; return 0; } char * fpga_print(struct node *n) { - struct fpga_dm *d = n->_vd; - struct fpga *f = d->card; + struct fpga *f = n->_vd; + struct fpga_card *c = f->ip->card; - if (d->ip) + if (f->ip) return strf("dm=%s (%s:%s:%s:%s) baseaddr=%#jx port=%u slot=%02"PRIx8":%02"PRIx8".%"PRIx8" id=%04"PRIx16":%04"PRIx16, - d->ip->name, d->ip->vlnv.vendor, d->ip->vlnv.library, d->ip->vlnv.name, d->ip->vlnv.version, - d->ip->baseaddr, d->ip->port, - f->filter.slot.bus, f->filter.slot.device, f->filter.slot.function, - f->filter.id.vendor, f->filter.id.device); + f->ip->name, f->ip->vlnv.vendor, f->ip->vlnv.library, f->ip->vlnv.name, f->ip->vlnv.version, + f->ip->baseaddr, f->ip->port, + c->filter.slot.bus, c->filter.slot.device, c->filter.slot.function, + c->filter.id.vendor, c->filter.id.device); else - return strf("dm=%s", d->ip_name); + return strf("dm=%s", f->ip->name); } -int fpga_get_type(struct ip *c) +int fpga_get_type(struct fpga_ip *c) { - if (ip_vlnv_match(c, "xilinx.com", "ip", "axi_dma", NULL)) + if (!fpga_vlnv_cmp(&c->vlnv, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_dma", NULL })) return FPGA_DM_DMA; - else if (ip_vlnv_match(c, "xilinx.com", "ip", "axi_fifo_mm_s", NULL)) + else if (!fpga_vlnv_cmp(&c->vlnv, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_fifo_mm_s", NULL })) return FPGA_DM_FIFO; else return -1; @@ -287,36 +179,28 @@ int fpga_open(struct node *n) { int ret; - struct fpga_dm *d = n->_vd; - struct fpga *f = d->card; + struct fpga *f = n->_vd; + struct fpga_card *c = f->ip->card; - d->ip = list_lookup(&d->card->ips, d->ip_name); - if (!d->ip) - cerror(n->cfg, "Datamover '%s' is unknown. Please specify it in the fpga.ips section", d->ip_name); - - d->type = fpga_get_type(d->ip); - if (d->type < 0) - cerror(n->cfg, "IP '%s' is not a supported datamover", d->ip->name); - - switch_init_paths(f->sw); + fpga_card_init(c, &pci, &vc); int flags = 0; - if (!d->use_irqs) + if (!f->use_irqs) flags |= INTC_POLLING; - switch (d->type) { + switch (f->type) { case FPGA_DM_DMA: /* Map DMA accessible memory */ - ret = dma_alloc(d->ip, &d->dma, 0x1000, 0); + ret = dma_alloc(f->ip, &f->dma, 0x1000, 0); if (ret) return ret; - intc_enable(f->intc, (1 << (d->ip->irq )), flags); /* MM2S */ - intc_enable(f->intc, (1 << (d->ip->irq + 1)), flags); /* S2MM */ + intc_enable(c->intc, (1 << (f->ip->irq )), flags); /* MM2S */ + intc_enable(c->intc, (1 << (f->ip->irq + 1)), flags); /* S2MM */ break; case FPGA_DM_FIFO: - intc_enable(f->intc, (1 << d->ip->irq), flags); /* MM2S & S2MM */ + intc_enable(c->intc, (1 << f->ip->irq), flags); /* MM2S & S2MM */ break; } @@ -328,21 +212,21 @@ int fpga_close(struct node *n) { int ret; - struct fpga_dm *d = n->_vd; - struct fpga *f = d->card; + struct fpga *f = n->_vd; + struct fpga_card *c = f->ip->card; - switch (d->type) { + switch (f->type) { case FPGA_DM_DMA: - intc_disable(f->intc, d->ip->irq); /* MM2S */ - intc_disable(f->intc, d->ip->irq + 1); /* S2MM */ + intc_disable(c->intc, f->ip->irq); /* MM2S */ + intc_disable(c->intc, f->ip->irq + 1); /* S2MM */ - ret = dma_free(d->ip, &d->dma); + ret = dma_free(f->ip, &f->dma); if (ret) return ret; case FPGA_DM_FIFO: - if (d->use_irqs) - intc_disable(f->intc, d->ip->irq); /* MM2S & S2MM */ + if (f->use_irqs) + intc_disable(c->intc, f->ip->irq); /* MM2S & S2MM */ } return 0; @@ -352,7 +236,7 @@ int fpga_read(struct node *n, struct sample *smps[], unsigned cnt) { int ret; - struct fpga_dm *d = n->_vd; + struct fpga *f = n->_vd; struct sample *smp = smps[0]; size_t recvlen; @@ -364,22 +248,22 @@ int fpga_read(struct node *n, struct sample *smps[], unsigned cnt) smp->ts.origin = time_now(); /* Read data from RTDS */ - switch (d->type) { + switch (f->type) { case FPGA_DM_DMA: - ret = dma_read(d->ip, d->dma.base_phys + 0x800, len); + ret = dma_read(f->ip, f->dma.base_phys + 0x800, len); if (ret) return ret; - ret = dma_read_complete(d->ip, NULL, &recvlen); + ret = dma_read_complete(f->ip, NULL, &recvlen); if (ret) return ret; - memcpy(smp->data, d->dma.base_virt + 0x800, recvlen); + memcpy(smp->data, f->dma.base_virt + 0x800, recvlen); smp->length = recvlen / 4; return 1; case FPGA_DM_FIFO: - recvlen = fifo_read(d->ip, (char *) smp->data, len); + recvlen = fifo_read(f->ip, (char *) smp->data, len); smp->length = recvlen / 4; return 1; @@ -391,29 +275,22 @@ int fpga_read(struct node *n, struct sample *smps[], unsigned cnt) int fpga_write(struct node *n, struct sample *smps[], unsigned cnt) { int ret; - struct fpga_dm *d = n->_vd; + struct fpga *f = n->_vd; struct sample *smp = smps[0]; size_t sentlen; size_t len = smp->length * sizeof(smp->data[0]); - //intc_wait(f->intc, 5, 1); - - //if (n->received % 40000 == 0) { - // struct timespec now = time_now(); - // info("proc time = %f", time_delta(&smp->ts.origin, &now)); - //} - /* Send data to RTDS */ - switch (d->type) { + switch (f->type) { case FPGA_DM_DMA: - memcpy(d->dma.base_virt, smp->data, len); + memcpy(f->dma.base_virt, smp->data, len); - ret = dma_write(d->ip, d->dma.base_phys, len); + ret = dma_write(f->ip, f->dma.base_phys, len); if (ret) return ret; - ret = dma_write_complete(d->ip, NULL, &sentlen); + ret = dma_write_complete(f->ip, NULL, &sentlen); if (ret) return ret; @@ -421,7 +298,7 @@ int fpga_write(struct node *n, struct sample *smps[], unsigned cnt) return 1; case FPGA_DM_FIFO: - sentlen = fifo_write(d->ip, (char *) smp->data, len); + sentlen = fifo_write(f->ip, (char *) smp->data, len); return sentlen / sizeof(smp->data[0]); break; } @@ -434,7 +311,7 @@ static struct plugin p = { .description = "VILLASfpga PCIe card (libxil)", .type = PLUGIN_TYPE_NODE, .node = { - .size = sizeof(struct fpga_dm), + .size = sizeof(struct fpga), .vectorize = 1, .parse = fpga_parse, .print = fpga_print, diff --git a/src/fpga-bench-overruns.c b/src/fpga-bench-overruns.c index 73346b5e9..fd2f8a418 100644 --- a/src/fpga-bench-overruns.c +++ b/src/fpga-bench-overruns.c @@ -65,7 +65,7 @@ static int lapack_workload(int N, double *A) int fpga_benchmark_overruns(struct fpga *f) { - struct ip *rtds, *dm; + struct fpga_ip *rtds, *dm; dm = list_lookup(&f->ips, "dma_1"); rtds = list_lookup(&f->ips, "rtds_axis_0"); diff --git a/src/fpga-bench.c b/src/fpga-bench.c index 1de87f1f3..7dcb2a45f 100644 --- a/src/fpga-bench.c +++ b/src/fpga-bench.c @@ -7,9 +7,7 @@ **********************************************************************************/ #include -#include #include -#include #include #include @@ -87,7 +85,7 @@ int fpga_benchmark_jitter(struct fpga *f) { int ret; - struct ip *tmr; + struct fpga_ip *tmr; tmr = list_lookup(&f->ips, "timer_0"); if (!tmr || !f->intc) @@ -184,7 +182,7 @@ int fpga_benchmark_datamover(struct fpga *f) { int ret; - struct ip *dm; + struct fpga_ip *dm; struct dma_mem mem, src, dst; #if BENCH_DM == 1 diff --git a/src/fpga-tests.c b/src/fpga-tests.c index 0a44b569d..cade78278 100644 --- a/src/fpga-tests.c +++ b/src/fpga-tests.c @@ -7,11 +7,7 @@ *********************************************************************************/ #include -#include #include -#include -#include -#include #include @@ -96,12 +92,12 @@ int fpga_test_xsg(struct fpga *f) int ret; double factor, err = 0; - struct ip *xsg, *dma; + struct fpga_ip *xsg, *dma; struct model_param *p; struct dma_mem mem; - xsg = ip_vlnv_lookup(&f->ips, NULL, "sysgen", "xsg_multiply", NULL); - dma = ip_vlnv_lookup(&f->ips, "xilinx.com", "ip", "axi_dma", NULL); + xsg = fpga_vlnv_lookup(&f->ips, &(struct fpga_vlnv) { NULL, "sysgen", "xsg_multiply", NULL }); + dma = fpga_vlnv_lookup(&f->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_dma", NULL }); /* Check if required IP is available on FPGA */ if (!dma || !xsg || !dma) @@ -160,10 +156,10 @@ int fpga_test_xsg(struct fpga *f) int fpga_test_hls_dft(struct fpga *f) { int ret; - struct ip *hls, *rtds; + struct fpga_ip *hls, *rtds; - rtds = ip_vlnv_lookup(&f->ips, "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL); - hls = ip_vlnv_lookup(&f->ips, NULL, "hls", "hls_dft", NULL); + rtds = fpga_vlnv_lookup(&f->ips, &(struct fpga_vlnv) { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL }); + hls = fpga_vlnv_lookup(&f->ips, &(struct fpga_vlnv) { NULL, "hls", "hls_dft", NULL }); /* Check if required IP is available on FPGA */ if (!hls || !rtds) @@ -216,9 +212,9 @@ int fpga_test_fifo(struct fpga *f) int ret; ssize_t len; char src[255], dst[255]; - struct ip *fifo; + struct fpga_ip *fifo; - fifo = ip_vlnv_lookup(&f->ips, "xilinx.com", "ip", "axi_fifo_mm_s", NULL); + fifo = fpga_vlnv_lookup(&f->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_fifo_mm_s", NULL }); if (!fifo) return -1; @@ -261,8 +257,8 @@ int fpga_test_dma(struct fpga *f) int ret = -1; struct dma_mem mem, src, dst; - list_foreach(struct ip *dma, &f->ips) { INDENT - if (!ip_vlnv_match(dma, "xilinx.com", "ip", "axi_dma", NULL)) + list_foreach(struct fpga_ip *dma, &f->ips) { INDENT + if (!fpga_vlnv_match(dma, "xilinx.com", "ip", "axi_dma", NULL)) continue; /* skip non DMA IP cores */ /* Simple DMA can only transfer up to 4 kb due to @@ -321,9 +317,9 @@ int fpga_test_dma(struct fpga *f) int fpga_test_timer(struct fpga *f) { int ret; - struct ip *tmr; + struct fpga_ip *tmr; - tmr = ip_vlnv_lookup(&f->ips, "xilinx.com", "ip", "axi_timer", NULL); + tmr = fpga_vlnv_lookup(&f->ips, &(struct fpga_vlnv) { "xilinx.com", "ip", "axi_timer", NULL }); if (!tmr) return -1; @@ -355,12 +351,12 @@ int fpga_test_timer(struct fpga *f) int fpga_test_rtds_rtt(struct fpga *f) { int ret; - struct ip *dma, *rtds; + struct fpga_ip *dma, *rtds; struct dma_mem buf; size_t recvlen; /* Get IP cores */ - rtds = ip_vlnv_lookup(&f->ips, "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL); + rtds = fpga_vlnv_lookup(&f->ips, &(struct fpga_vlnv) { "acs.eonerc.rwth-aachen.de", "user", "rtds_axis", NULL }); dma = list_lookup(&f->ips, "dma_1"); /* Check if required IP is available on FPGA */