Commit 8f780347 authored by Steffen Vogel's avatar Steffen Vogel 🎅🏼

imported source code from VILLASfpga repo and made it compile

parent c8db2e0b
Pipeline #30054 canceled with stages
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Matches multiple files with brace expansion notation
# Set default charset
[{etc,include,lib,plugins,src,tests,tools}/**.{c,h}]
charset = utf-8
indent_style = tab
indent_size = 8
trim_trailing_whitespace=true
variables:
GIT_STRATEGY: fetch
GIT_SUBMODULE_STRATEGY: recursive
PREFIX: /usr/
DOCKER_TAG_DEV: ${CI_COMMIT_REF_NAME}
DOCKER_IMAGE_DEV: villas/fpga-dev
stages:
- prepare
- build
- test
- deploy
- docker
# For some reason, GitLab CI prunes the contents of the submodules so we need to restore them.
before_script:
- git submodule foreach git checkout .
# Stage: prepare
##############################################################################
# Build docker image which is used to build & test VILLASnode
docker-dev:
stage: prepare
script:
- docker build -t ${DOCKER_IMAGE_DEV}:${DOCKER_TAG_DEV} .
tags:
- shell
- linux
# Stage: build
##############################################################################
build:source:
stage: build
script:
- mkdir build && cd build && cmake .. && make
artifacts:
expire_in: 1 week
name: ${CI_PROJECT_NAME}-${CI_BUILD_REF}
paths:
- build/
image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG_DEV}
tags:
- docker
#build:packages:
# stage: build
# script:
# - mkdir build && cd build && cmake .. && make package
# artifacts:
# expire_in: 1 week
# name: ${CI_PROJECT_NAME}-${CI_BUILD_REF}
# paths:
# - build/
# image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG_DEV}
# tags:
# - docker
# Stage: test
##############################################################################
#test:unit:
# stage: test
# dependencies:
# - build:source
# script:
# - make test
# image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG_DEV}
# tags:
# - docker
# - fpga
# Stage: deploy
##############################################################################
#deploy:packages:
# stage: deploy
# script:
# - ssh ${DEPLOY_USER}@${DEPLOY_HOST} mkdir -p ${DEPLOY_PATH}/{dist,../packages}
# - rsync ${RSYNC_OPTS} build/*.rpm ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/../packages/
# - rsync ${RSYNC_OPTS} build//*.tar.gz ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/dist/
# - ssh ${DEPLOY_USER}@${DEPLOY_HOST} createrepo ${DEPLOY_PATH}/../packages
# dependencies:
# - build:packages
# tags:
# - villas-deploy
# only:
# - tags
#
#deploy:git-mirror:
# stage: deploy
# script:
# - git push --force --mirror --prune https://${GITHUB_USER}:${GITHUB_TOKEN}@github.com:VILLASframework/VILLASnode.git
cmake_minimum_required(VERSION 3.5)
project(VILLASfpga C)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
add_subdirectory(lib)
add_subdirectory(tests)
# This file is licensed under the WTFPL version 2 -- you can see the full
# license over at http://www.wtfpl.net/txt/copying/
#
# - Try to find Criterion
#
# Once done this will define
# CRITERION_FOUND - System has Criterion
# CRITERION_INCLUDE_DIRS - The Criterion include directories
# CRITERION_LIBRARIES - The libraries needed to use Criterion
find_package(PkgConfig)
find_path(CRITERION_INCLUDE_DIR criterion/criterion.h
PATH_SUFFIXES criterion)
find_library(CRITERION_LIBRARY NAMES criterion libcriterion)
set(CRITERION_LIBRARIES ${CRITERION_LIBRARY})
set(CRITERION_INCLUDE_DIRS ${CRITERION_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
# handle the QUIET and REQUIRED arguments and set CRITERION_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(Criterion DEFAULT_MSG
CRITERION_LIBRARY CRITERION_INCLUDE_DIR)
mark_as_advanced(CRITERION_INCLUDE_DIR CRITERION_LIBRARY)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="148.89053mm"
height="148.89053mm"
viewBox="0 0 148.89053 148.89053"
version="1.1"
id="svg8"
inkscape:version="0.91+devel r14647 custom"
sodipodi:docname="villas_fpga.svg"
inkscape:export-filename="/Users/stv0g/workspace/rwth/villas/node/doc/pictures/villas_fpga.png"
inkscape:export-xdpi="70"
inkscape:export-ydpi="70">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.1539865"
inkscape:cx="273.11099"
inkscape:cy="286.34845"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:snap-global="true"
inkscape:window-width="1440"
inkscape:window-height="851"
inkscape:window-x="0"
inkscape:window-y="23"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:object-paths="true"
inkscape:object-nodes="false" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-2.3870832,-17.382582)">
<path
inkscape:connector-curvature="0"
style="opacity:1;fill:#f65d5d;fill-opacity:1;stroke:none;stroke-width:34.06763077;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 12.855646,54.255283 -0.0023,0.0015 -1.23e-4,0.0028 z"
id="path4267" />
<circle
style="opacity:1;fill:none;fill-opacity:1;stroke:none;stroke-width:0.09076402;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path4286"
cx="77.834518"
cy="91.776962"
r="29.89892" />
<path
inkscape:connector-curvature="0"
style="opacity:1;fill:#f65d5d;fill-opacity:1;stroke:none;stroke-width:34.06763077;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 76.974417,16.797321 -0.0023,0.0015 0.0046,-1.62e-4 z"
id="path4275" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
style="opacity:1;fill:#f98e8e;fill-opacity:1;stroke:none;stroke-width:34.06763077;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 81.536624,19.580815 -0.218452,23.613422 35.481498,20.486912 20.6168,-11.836694 z"
id="path4273" />
<path
id="path42454"
d="M 71.221452,19.580815 71.439902,43.194237 35.95843,63.681149 15.341626,51.844455 Z"
style="opacity:1;fill:#f65d5d;fill-opacity:1;stroke:none;stroke-width:34.06763077;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
id="path42458"
d="m 81.536624,164.22286 -0.218452,-23.61343 35.481498,-20.48693 20.6168,11.8367 z"
style="opacity:1;fill:#8f1515;fill-opacity:1;stroke:none;stroke-width:34.06763077;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
style="opacity:1;fill:#aa2424;fill-opacity:1;stroke:none;stroke-width:34.06763077;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 71.221452,164.22286 71.439902,140.60943 35.95843,120.1225 15.341626,131.9592 Z"
id="path42460" />
<path
id="path42462"
d="M 11.878931,124.09941 32.437982,112.48188 32.439482,71.510572 11.88019,59.574251 Z"
style="opacity:1;fill:#de2727;fill-opacity:1;stroke:none;stroke-width:34.06763077;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>
/** Example configuration file for VILLASfpga.
*
* The syntax of this file is similar to JSON.
* A detailed description of the format can be found here:
* http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
# Some global settings are used by multiple configuration files
# and therefore defined in separate files
@include "global.conf"
@include "plugins.conf"
fpgas = {
vc707 = {
/* Card identification */
id = "10ee:7022";
slot = "01:00.0";
intc = 0x5000;
reset = 0x2000;
do_reset = true;
ips = {
switch_0 = {
vlnv = "xilinx.com:ip:axis_interconnect:2.1"
baseaddr = 0x0000;
numports = 3;
paths = (
{ in = "dma_0", out = "rtds_0" },
{ in = "rtds_0", out = "dma_0" }
)
},
rtds_0 = {
vlnv = "acs.eonerc.rwth-aachen.de:user:rtds_axis:1.0"
baseaddr = 0x3000;
port = 0;
},
dma_0 = {
vlnv = "xilinx.com:ip:axi_dma:7.1";
baseaddr = 0x1000;
port = 2;
irq = 0
}
}
}
}
nodes = {
rtds = {
datamover = "dma_0";
use_irqs = false;
}
}
/** Example configuration file for VILLASfpga / VILLASfpga.
*
* The syntax of this file is similar to JSON.
* A detailed description of the format can be found here:
* http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
# Some global settings are used by multiple configuration files
# and therefore defined in separate files
@include "global.conf"
@include "plugins.conf"
############ Dictionary of FPGAs ############
fpgas = {
vc707 = {
id = "10ee:7022"; # Card identification
slot = "01:00.0"; # Usually only id or slot is required
do_reset = true; # Perform a full reset of the FPGA board
# Requires a IP core named 'axi_reset_0'
############ List of IP cores on FPGA ############
#
# Every IP core can have the following settings:
# baseaddr Baseaddress as accessible from BAR0 memory region
# irq Interrupt index of MSI interrupt controller
# port Port index of AXI4-Stream interconnect
ips = {
### Utility IPs
axi_pcie_intc_0 = {
vlnv = "acs.eonerc.rwth-aachen.de:user:axi_pcie_intc:1.0";
baseaddr = 0xb000;
},
switch_0 = {
vlnv = "xilinx.com:ip:axis_interconnect:2.1"
baseaddr = 0x5000;
num_ports = 10;
paths = (
// { in = "fifo_mm_s_0", out = "fifo_mm_s_0" }, # Loopback fifo_mm_s_0
// { in = "dma_0", out = "dma_0" }, # Loopback dma_0
// { in = "dma_1", out = "dma_1" } # Loopback dma_1
// { in = "rtds_axis_0", out = "fifo_mm_s_0", reverse = true } # Linux <-> RTDS
// { in = "rtds_axis_0", out = "dma_0", reverse = true } # Linux (dma_0) <-> RTDS
{ in = "rtds_axis_0", out = "dma_1", reverse = true } # Linux (dma_1) <-> RTDS
// { in = "rtds_axis_0", out = "fifo_mm_s_0", reverse = true } # Linux (fifo_mm_s_0) <-> RTDS
// { in = "dma_0", out = "hls_dft_0", reverse = true } # DFT <-> Linux
// { in = "rtds_axis_0", out = "hls_dft_0", reverse = true }, # DFT <-> RTDS
)
},
axi_reset_0 = {
vlnv = "xilinx.com:ip:axi_gpio:2.0";
baseaddr = 0x7000;
},
timer_0 = {
vlnv = "xilinx.com:ip:axi_timer:2.0";
baseaddr = 0x4000;
irq = 0;
},
### Data mover IPs
dma_0 = {
vlnv = "xilinx.com:ip:axi_dma:7.1";
baseaddr = 0x3000;
port = 1;
irq = 3; /* 3 - 4 */
},
dma_1 = {
vlnv = "xilinx.com:ip:axi_dma:7.1";
baseaddr = 0x2000;
port = 6;
irq = 3; /* 3 - 4 */
},
fifo_mm_s_0 = {
vlnv = "xilinx.com:ip:axi_fifo_mm_s:4.1";
baseaddr = 0x6000;
baseaddr_axi4 = 0xC000;
port = 2;
irq = 2;
},
### Interface IPs
rtds_axis_0 = {
vlnv = "acs.eonerc.rwth-aachen.de:user:rtds_axis:1.0";
baseaddr = 0x8000;
port = 0;
irq = 5; /* 5 -7 */
},
### Model IPs
hls_dft_0 = {
vlnv = "acs.eonerc.rwth-aachen.de:hls:hls_dft:1.0";
baseaddr = 0x9000;
port = 5;
irq = 1;
period = 400; /* in samples: 20ms / 50uS = 400*/
harmonics = [ 0, 1, 3, 5, 7 ]
decimation = 0; /* 0 = disabled */
//harmonics = [ 0, 1, 2, 5, 22 ]
},
axis_data_fifo_0 = {
vlnv = "xilinx.com:ip:axis_data_fifo:1.1";
port = 3;
},
axis_data_fifo_1 = {
vlnv = "xilinx.com:ip:axis_data_fifo:1.1";
port = 6;
},
}
}
}
############ Dictionary of nodes ############
nodes = {
dma_0 = {
type = "fpga"; # Datamovers to VILLASfpga
datamover = "dma_0"; # Name of IP core in fpga.ips
use_irqs = false; # Use polling or MSI interrupts?
},
dma_1 = {
type = "fpga";
datamover = "dma_1";
use_irqs = false;
},
fifo_0 = {
type = "fpga";
datamover = "fifo_mm_s_0";
use_irqs = false;
},
simple_circuit = {
type = "cbuilder";
model = "simple_circuit",
timestep = 25e-6; # in seconds
parameters = [
1.0, # R2 = 1 Ohm
0.001 # C2 = 1000 uF
];
}
}
############ List of paths ############
paths = (
{ in = "dma_1", out = "simple_circuit", reverse = true }
)
/** Some common defines, enums and datastructures.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#pragma once
/* Common states for most objects in VILLASfpga (paths, nodes, hooks, plugins) */
enum state {
STATE_DESTROYED = 0,
STATE_INITIALIZED = 1,
STATE_PARSED = 2,
STATE_CHECKED = 3,
STATE_STARTED = 4,
STATE_LOADED = 4, /* alias for STATE_STARTED used by plugins */
STATE_STOPPED = 5,
STATE_UNLOADED = 5 /* alias for STATE_STARTED used by plugins */
};
/** Static server configuration
*
* This file contains some compiled-in settings.
* This settings are not part of the configuration file.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#pragma once
#ifndef V
#define V 2
#endif
/* Paths */
#define PLUGIN_PATH PREFIX "/share/villas/node/plugins"
#define WEB_PATH PREFIX "/share/villas/node/web"
#define SYSFS_PATH "/sys"
#define PROCFS_PATH "/proc"
/** Default number of values in a sample */
#define DEFAULT_SAMPLELEN 64
#define DEFAULT_QUEUELEN 1024
/** Number of hugepages which are requested from the the kernel.
* @see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt */
#define DEFAULT_NR_HUGEPAGES 100
/** Width of log output in characters */
#define LOG_WIDTH 80
#define LOG_HEIGHT 25
/** Socket priority */
#define SOCKET_PRIO 7
/* Protocol numbers */
#define IPPROTO_VILLAS 137
#define ETH_P_VILLAS 0xBABE
#define USER_AGENT "VILLASfpga (" BUILDID ")"
/* Required kernel version */
#define KERNEL_VERSION_MAJ 3
#define KERNEL_VERSION_MIN 6
/** PCIe BAR number of VILLASfpga registers */
#define FPGA_PCI_BAR 0
#define FPGA_PCI_VID_XILINX 0x10ee
#define FPGA_PCI_PID_VFPGA 0x7022
/** AXI Bus frequency for all components
* except RTDS AXI Stream bridge which runs at RTDS_HZ (100 Mhz) */
#define FPGA_AXI_HZ 125000000 // 125 MHz
/** FPGA card
*
* This class represents a FPGA device.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/** @addtogroup fpga VILLASfpga
* @{
*/
#pragma once
#include <jansson.h>
#include "common.h"
#include "kernel/pci.h"
#include "kernel/vfio.h"
/* Forward declarations */
struct fpga_ip;
struct vfio_container;
struct fpga_card {
char *name; /**< The name of the FPGA card */
enum state state; /**< The state of this FPGA card. */
struct pci *pci;
struct pci_device filter; /**< Filter for PCI device. */
struct vfio_container *vfio_container;
struct vfio_device vfio_device; /**< VFIO device handle. */
int do_reset; /**< Reset VILLASfpga during startup? */
int affinity; /**< Affinity for MSI interrupts */
struct list ips; /**< List of IP components on FPGA. */
char *map; /**< PCI BAR0 mapping for register access */
size_t maplen;
size_t dmalen;
/* Some IP cores are special and referenced here */
struct fpga_ip *intc;
struct fpga_ip *reset;
struct fpga_ip *sw;
};
/** Initialize FPGA card and its IP components. */
int fpga_card_init(struct fpga_card *c, struct pci *pci, struct vfio_container *vc);
/** Parse configuration of FPGA card including IP cores from config. */
int fpga_card_parse(struct fpga_card *c, json_t *cfg, const char *name);
int fpga_card_parse_list(struct list *l, json_t *cfg);
/** Check if the FPGA card configuration is plausible. */
int fpga_card_check(struct fpga_card *c);
/** Start FPGA card. */
int fpga_card_start(struct fpga_card *c);
/** Stop FPGA card. */
int fpga_card_stop(struct fpga_card *c);
/** Destroy FPGA card. */
int fpga_card_destroy(struct fpga_card *c);
/** Dump details of FPGA card to stdout. */
void fpga_card_dump(struct fpga_card *c);
/** Reset the FPGA to a known state */
int fpga_card_reset(struct fpga_card *c);
/** @} */
/** Interlectual Property component.
*
* This class represents a module within the FPGA.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTI