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:
parent
30e0ecf544
commit
7de25683d7
29 changed files with 839 additions and 595 deletions
63
include/villas/fpga/card.h
Normal file
63
include/villas/fpga/card.h
Normal 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);
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
|
@ -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_ */
|
||||
/** @} */
|
|
@ -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_ */
|
||||
/** @} */
|
74
include/villas/fpga/ips/dma.h
Normal file
74
include/villas/fpga/ips/dma.h
Normal 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);
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
/** @} */
|
|
@ -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_ */
|
||||
/** @} */
|
|
@ -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_ */
|
||||
/** @} */
|
|
@ -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_ */
|
||||
/** @} */
|
|
@ -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_ */
|
||||
/** @} */
|
|
@ -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_ */
|
||||
/** @} */
|
39
include/villas/fpga/vlnv.h
Normal file
39
include/villas/fpga/vlnv.h
Normal 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_ @} */
|
|
@ -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
184
lib/fpga/card.c
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
6
lib/fpga/ips/Makefile.inc
Normal file
6
lib/fpga/ips/Makefile.inc
Normal 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
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
@ -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
|
||||
}
|
||||
};
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
@ -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
45
lib/fpga/vlnv.c
Normal 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;
|
||||
}
|
337
lib/nodes/fpga.c
337
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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue