1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

fpga: refactored VILLASfpga node type

This commit is contained in:
Steffen Vogel 2017-02-18 10:43:58 -05:00
parent 30e0ecf544
commit 7de25683d7
29 changed files with 839 additions and 595 deletions

View file

@ -0,0 +1,63 @@
/** FPGA card
*
* This class represents a FPGA device.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @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);
/** @} */

View file

@ -1,68 +0,0 @@
/** DMA related helper functions
*
* These functions present a simpler interface to Xilinx' DMA driver (XAxiDma_*)
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @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 <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <xilinx/xaxidma.h>
#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_ */

View file

@ -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 <stvogel@eonerc.rwth-aachen.de>
* @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 <stdint.h>
#include <xilinx/xtmrctr.h>
#include <xilinx/xintc.h>
#include <xilinx/xllfifo.h>
#include <xilinx/xaxis_switch.h>
#include <xilinx/xaxidma.h>
#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_ */
/** @} */

View file

@ -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 <xilinx/xhls_dft.h>
@ -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_ */
/** @} */

View file

@ -0,0 +1,74 @@
/** DMA related helper functions.
*
* These functions present a simpler interface to Xilinx' DMA driver (XAxiDma_*).
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @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 <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <xilinx/xaxidma.h>
/* 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);
/** @} */

View file

@ -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 <sys/types.h>
@ -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_ */
/** @} */

View file

@ -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 <xilinx/xintc.h>
@ -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_ */
/** @} */

View file

@ -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 <stdlib.h>
#include <stdint.h>
@ -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_ */
/** @} */

View file

@ -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_ */
/** @} */

View file

@ -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 <xilinx/xaxis_switch.h>
@ -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_ */
/** @} */

View file

@ -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 <xilinx/xtmrctr.h>
struct timer {
XTmrCtr inst;
};
#endif /* _FPGA_TIMER_H_ */
/** @} */

View file

@ -0,0 +1,39 @@
/** Vendor, Library, Name, Version (VLNV) tag.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @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_ @} */

View file

@ -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
endif
-include lib/fpga/ip/Makefile.inc

184
lib/fpga/card.c Normal file
View file

@ -0,0 +1,184 @@
#include <unistd.h>
#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;
}

View file

@ -1,48 +1,9 @@
#include <string.h>
#include <unistd.h>
#include <libconfig.h>
#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;
}
}

View file

@ -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

View file

@ -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
}
};

View file

@ -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
}
};

View file

@ -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
}
};

View file

@ -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
}
};

View file

@ -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
}
};

View file

@ -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
}
};

View file

@ -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
}
};

View file

@ -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
}
};

45
lib/fpga/vlnv.c Normal file
View file

@ -0,0 +1,45 @@
/** Vendor, Library, Name, Version (VLNV) tag
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @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 <stdlib.h>
#include <string.h>
#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;
}

View file

@ -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,

View file

@ -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");

View file

@ -7,9 +7,7 @@
**********************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <villas/utils.h>
@ -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

View file

@ -7,11 +7,7 @@
*********************************************************************************/
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <xilinx/xtmrctr.h>
@ -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 */