...
 
Commits (32)
......@@ -33,7 +33,7 @@ docker-dev:
build:source:
stage: build
script:
- mkdir build && cd build && cmake .. && make -j8
- mkdir build && cd build && cmake3 .. && make -j8
artifacts:
expire_in: 1 week
name: ${CI_PROJECT_NAME}-${CI_BUILD_REF}
......@@ -46,7 +46,7 @@ build:source:
#build:packages:
# stage: build
# script:
# - mkdir build && cd build && cmake .. && make package
# - mkdir build && cd build && cmake3 .. && make package
# artifacts:
# expire_in: 1 week
# name: ${CI_PROJECT_NAME}-${CI_BUILD_REF}
......@@ -59,24 +59,14 @@ build:source:
# Stage: test
##############################################################################
test:unit-software:
test:unit:
stage: test
dependencies:
- build:source
script:
- build/tests/unit-tests --filter 'graph/*'
image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG_DEV}
tags:
- docker
test:unit-hardware:
stage: test
# dependencies:
# - build:source
tags:
- villas-fpga
- cuda
allow_failure: true
script: |
rm -r build && mkdir build && cd build && cmake .. && make unit-tests -j8
rm -r build && mkdir build && cd build && cmake3 .. && make unit-tests -j8
if [ "$(who | wc -l)" -eq "0" ]; then
tests/unit-tests --jobs 1 --filter 'fpga/*'
else
......
......@@ -5,8 +5,14 @@
path = thirdparty/libxil
url = https://git.rwth-aachen.de/acs/public/villas/libxil.git
[submodule "lib/gpu/gdrcopy"]
path = lib/gpu/gdrcopy
path = gpu/thirdparty/gdrcopy
url = https://github.com/daniel-k/gdrcopy.git
[submodule "thirdparty/udmabuf"]
path = thirdparty/udmabuf
url = https://github.com/ikwzm/udmabuf
[submodule "hardware"]
path = hardware
url = ../VILLASfpga-hardware.git
[submodule "common"]
path = common
url = ../VILLAScommon.git
cmake_minimum_required(VERSION 3.5)
## CMakeLists.txt
#
# @author Daniel Krebs <github@daniel-krebs.net>
# @copyright 2018, RWTH Institute for Automation of Complex Power Systems (ACS)
# @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/>.
##############################################################################
cmake_minimum_required(VERSION 3.5)
project(VILLASfpga C CXX)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
set (CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
include_directories(thirdparty/spdlog/include)
# GPU library is optional, check for CUDA presence
include(CheckLanguage)
check_language(CUDA)
if(CMAKE_CUDA_COMPILER)
add_subdirectory(gpu)
else()
message("No CUDA support, not building GPU library")
endif()
include_directories(thirdparty/CLI11)
include_directories(thirdparty/rang)
add_subdirectory(common)
add_subdirectory(lib)
add_subdirectory(src)
add_subdirectory(tests)
# Project settings
......@@ -29,10 +62,10 @@ configure_file("libvillas-fpga.pc.in" "libvillas-fpga.pc" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libvillas-fpga.pc" DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig")
# CPack
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_DESCRIPTION})
SET(CPACK_PACKAGE_VENDOR ${PROJECT_VENDOR})
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING.md")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_DESCRIPTION})
set(CPACK_PACKAGE_VENDOR ${PROJECT_VENDOR})
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING.md")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_PACKAGE_NAME "villas-fpga")
......@@ -56,4 +89,4 @@ set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries")
set(CPACK_PACKAGE_FILE_NAME "${CPACK_SOURCE_PACKAGE_FILE_NAME}-${CPACK_RPM_PACKAGE_RELEASE}.${CPACK_RPM_PACKAGE_ARCHITECTURE}")
set(CPACK_GENERATOR "RPM")
include(CPack)
\ No newline at end of file
include(CPack)
......@@ -9,7 +9,7 @@
# make docker
#
# @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
# @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
# @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
# @license GNU General Public License (version 3)
#
# VILLASfpga
......@@ -28,7 +28,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
###################################################################################
FROM fedora:27
FROM nvidia/cuda:9.2-devel-centos7
LABEL \
org.label-schema.schema-version="1.0" \
......@@ -42,31 +42,34 @@ LABEL \
org.label-schema.vcs-url="https://git.rwth-aachen.de/VILLASframework/VILLASfpga" \
org.label-schema.usage="https://villas.fein-aachen.org/doc/fpga.html"
# Some of the dependencies are only available in our own repo
ADD https://villas.fein-aachen.org/packages/villas.repo /etc/yum.repos.d/
# Enable Extra Packages for Enterprise Linux (EPEL) and Software collection repo
RUN yum -y install epel-release centos-release-scl
# Toolchain
RUN dnf -y install \
gcc gcc-c++ \
pkgconfig make cmake \
RUN yum -y install \
devtoolset-7-toolchain \
pkgconfig make cmake3 \
autoconf automake autogen libtool \
texinfo git curl tar
# Several tools only needed for developement and testing
RUN dnf -y install \
RUN yum -y install \
rpmdevtools rpm-build
# Some of the dependencies are only available in our own repo
ADD https://villas.fein-aachen.org/packages/villas.repo /etc/yum.repos.d/
# Dependencies
RUN dnf -y install \
RUN yum -y install \
jansson-devel \
libxil-devel \
lapack-devel
# Build & Install Criterion
COPY thirdparty/criterion /tmp/criterion
RUN mkdir -p /tmp/criterion/build && cd /tmp/criterion/build && cmake .. && make install && rm -rf /tmp/*
RUN mkdir -p /tmp/criterion/build && cd /tmp/criterion/build && cmake3 .. && make install && rm -rf /tmp/*
ENV LD_LIBRARY_PATH /usr/local/lib:/usr/local/lib64
WORKDIR /villas
ENTRYPOINT bash
WORKDIR /fpga
ENTRYPOINT scl enable devtoolset-7 bash
......@@ -11,12 +11,17 @@ User documentation is available here: <https://villas.fein-aachen.org/doc/fpga.h
## Copyright
2017, Institute for Automation of Complex Power Systems, EONERC
2018, Institute for Automation of Complex Power Systems, EONERC
## License
This project is released under the terms of the [GPL version 3](COPYING.md).
We kindly ask all academic publications employing components of VILLASframework to cite one of the following papers:
- A. Monti et al., "[A Global Real-Time Superlab: Enabling High Penetration of Power Electronics in the Electric Grid](https://ieeexplore.ieee.org/document/8458285/)," in IEEE Power Electronics Magazine, vol. 5, no. 3, pp. 35-44, Sept. 2018.
- S. Vogel, M. Mirz, L. Razik and A. Monti, "[An open solution for next-generation real-time power system simulation](http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=8245739&isnumber=8244404)," 2017 IEEE Conference on Energy Internet and Energy System Integration (EI2), Beijing, 2017, pp. 1-6.
```
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
......@@ -39,7 +44,8 @@ For other licensing options please consult [Prof. Antonello Monti](mailto:amonti
[![EONERC ACS Logo](doc/pictures/eonerc_logo.png)](http://www.acs.eonerc.rwth-aachen.de)
- Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
- Daniel Krebs <dkrebs@eonerc.rwth-aachen.de>
[Institute for Automation of Complex Power Systems (ACS)](http://www.acs.eonerc.rwth-aachen.de)
[EON Energy Research Center (EONERC)](http://www.eonerc.rwth-aachen.de)
[RWTH University Aachen, Germany](http://www.rwth-aachen.de)
[Institute for Automation of Complex Power Systems (ACS)](http://www.acs.eonerc.rwth-aachen.de)
[EON Energy Research Center (EONERC)](http://www.eonerc.rwth-aachen.de)
[RWTH University Aachen, Germany](http://www.rwth-aachen.de)
Subproject commit 9747c6ead6dedff943dbf22ce74e40e9b2622514
......@@ -5,7 +5,7 @@
* 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
* @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
......
......@@ -5,7 +5,7 @@
* 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
* @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
......
## CMakeLists.txt
#
# @author Daniel Krebs <github@daniel-krebs.net>
# @copyright 2018, RWTH Institute for Automation of Complex Power Systems (ACS)
# @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/>.
##############################################################################
cmake_minimum_required(VERSION 3.8)
project(villas-gpu
VERSION 1.0
DESCRIPTION "VILLASgpu"
LANGUAGES C CXX CUDA)
add_subdirectory(thirdparty/gdrcopy)
add_library(villas-gpu
SHARED
src/gpu.cpp
src/kernels.cu
)
target_compile_options(villas-gpu PRIVATE -g)
set_source_files_properties(src/gpu.cpp PROPERTIES
LANGUAGE CUDA
)
target_include_directories(villas-gpu
PRIVATE
/opt/cuda/include
)
target_link_libraries(villas-gpu
PUBLIC
villas-common
gdrapi
cuda
)
target_include_directories(villas-gpu
PUBLIC
${CMAKE_CURRENT_LIST_DIR}/include
PRIVATE
${CMAKE_CURRENT_LIST_DIR}
)
/** GPU managment.
*
* @file
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017-2018, 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
#include <sstream>
#include <plugin.hpp>
#include <memory_manager.hpp>
#include <memory.hpp>
#include <villas/plugin.hpp>
#include <villas/memory_manager.hpp>
#include <villas/memory.hpp>
#include <villas/log.hpp>
namespace villas {
namespace gpu {
......@@ -62,6 +84,8 @@ private:
class GpuAllocator : public BaseAllocator<GpuAllocator> {
public:
static constexpr size_t GpuPageSize = 64UL << 10;
GpuAllocator(Gpu& gpu);
std::string getName() const;
......@@ -71,6 +95,8 @@ public:
private:
Gpu& gpu;
// TODO: replace by multimap (key is available memory)
std::list<std::unique_ptr<LinearAllocator>> chunks;
};
class GpuFactory : public Plugin {
......
/** Logging routines that depend on jansson.
/** GPU Kernels.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
......@@ -23,15 +23,17 @@
#pragma once
struct log;
#include <cstdint>
#include <cuda_runtime.h>
#include <jansson.h>
namespace villas {
namespace gpu {
#include "log.h"
__global__ void
kernel_mailbox(volatile uint32_t *mailbox, volatile uint32_t* counter);
/** Parse logging configuration. */
int log_parse(struct log *l, json_t *cfg);
__global__ void
kernel_memcpy(volatile uint8_t* dst, volatile uint8_t* src, size_t length);
/** Print configuration error and exit. */
void jerror(json_error_t *err, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
} // namespace villas
} // namespace gpu
/** GPU managment.
*
* @file
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017-2018, 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/>.
*********************************************************************************/
#include <cstdio>
#include <cstdint>
#include <sys/mman.h>
......@@ -8,7 +31,7 @@
#include <villas/gpu.hpp>
#include <villas/log.hpp>
#include <villas/kernel/pci.h>
#include <memory_manager.hpp>
#include <villas/memory_manager.hpp>
#include <cuda.h>
#include <cuda_runtime.h>
......@@ -365,29 +388,53 @@ GpuAllocator::allocateBlock(size_t size)
cudaSetDevice(gpu.gpuId);
void* addr;
if(cudaSuccess != cudaMalloc(&addr, size)) {
logger->error("cudaMalloc(..., size={}) failed", size);
throw std::bad_alloc();
}
auto& mm = MemoryManager::get();
// assemble name for this block
std::stringstream name;
name << std::showbase << std::hex << reinterpret_cast<uintptr_t>(addr);
// search for an existing chunk that has enough free memory
auto chunk = std::find_if(chunks.begin(), chunks.end(), [&](const auto& chunk) {
return chunk->getAvailableMemory() >= size;
});
auto blockName = mm.getSlaveAddrSpaceName(getName(), name.str());
auto blockAddrSpaceId = mm.getOrCreateAddressSpace(blockName);
const auto localAddr = reinterpret_cast<uintptr_t>(addr);
std::unique_ptr<MemoryBlock, MemoryBlock::deallocator_fn>
mem(new MemoryBlock(localAddr, size, blockAddrSpaceId), this->free);
if(chunk != chunks.end()) {
logger->debug("Found existing chunk that can host the requested block");
insertMemoryBlock(*mem);
return (*chunk)->allocateBlock(size);
gpu.makeAccessibleToPCIeAndVA(*mem);
} else {
// allocate a new chunk
// rounded-up multiple of GPU page size
const size_t chunkSize = size - (size & (GpuPageSize - 1)) + GpuPageSize;
logger->debug("Allocate new chunk of {:#x} bytes", chunkSize);
if(cudaSuccess != cudaMalloc(&addr, chunkSize)) {
logger->error("cudaMalloc(..., size={}) failed", chunkSize);
throw std::bad_alloc();
}
return mem;
// assemble name for this block
std::stringstream name;
name << std::showbase << std::hex << reinterpret_cast<uintptr_t>(addr);
auto blockName = mm.getSlaveAddrSpaceName(getName(), name.str());
auto blockAddrSpaceId = mm.getOrCreateAddressSpace(blockName);
const auto localAddr = reinterpret_cast<uintptr_t>(addr);
std::unique_ptr<MemoryBlock, MemoryBlock::deallocator_fn>
mem(new MemoryBlock(localAddr, chunkSize, blockAddrSpaceId), this->free);
insertMemoryBlock(*mem);
// already make accessible to CPU
gpu.makeAccessibleToPCIeAndVA(*mem);
// create a new allocator to manage the chunk and push to chunk list
chunks.push_front(std::make_unique<LinearAllocator>(std::move(mem)));
// call again, this time there's a large enough chunk
return allocateBlock(size);
}
}
......
/** GPIO related helper functions
/** GPU Kernels.
*
* @file
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017, Daniel Krebs
* @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
......@@ -19,30 +20,47 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <stdio.h>
#include "config.h"
#include "plugin.h"
#include <villas/gpu.hpp>
#include "fpga/ip.h"
#include "fpga/card.h"
#include <cuda_runtime.h>
#include <cuda.h>
static int gpio_start(struct fpga_ip *c)
#include "kernels.hpp"
namespace villas {
namespace gpu {
__global__ void
kernel_mailbox(volatile uint32_t *mailbox, volatile uint32_t* counter)
{
(void) c;
printf("[gpu] hello!\n");
printf("[gpu] mailbox: %p\n", mailbox);
printf("[kernel] started\n");
return 0;
while(1) {
if (*mailbox == 1) {
*mailbox = 0;
printf("[gpu] counter = %d\n", *counter);
break;
}
}
printf("[gpu] quit\n");
}
static struct plugin p = {
.name = "Xilinx's GPIO controller",
.description = "",
.type = PLUGIN_TYPE_FPGA_IP,
.ip = {
.vlnv = { "xilinx.com", "ip", "axi_gpio", NULL },
.type = FPGA_IP_TYPE_MISC,
.start = gpio_start,
.size = 0
__global__ void
kernel_memcpy(volatile uint8_t* dst, volatile uint8_t* src, size_t length)
{
while(length > 0) {
*dst++ = *src++;
length--;
}
};
}
REGISTER_PLUGIN(&p)
} // namespace villas
} // namespace gpu
Subproject commit fcf4bc56687c01e71379c174b6875bd3a99b31c7
Subproject commit 2eaf71991d7b29e46105dbd0fa27bc3a130f16f9
/** 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
#pragma once
#include <map>
#include <list>
#include <memory>
#include <sstream>
#include <string>
#include <fstream>
#include <stdexcept>
#include <algorithm>
#include <villas/log.hpp>
namespace villas {
namespace graph {
// use vector indices as identifiers
// forward declarations
class Edge;
class Vertex;
class Vertex {
template<typename VertexType, typename EdgeType>
friend class DirectedGraph;
public:
using Identifier = std::size_t;
const Identifier&
getIdentifier() const
{ return id; }
friend std::ostream&
operator<< (std::ostream& stream, const Vertex& vertex)
{ return stream << vertex.id; }
bool
operator==(const Vertex& other)
{ return this->id == other.id; }
private:
Identifier id;
// HACK: how to resolve this circular type dependency?
std::list<std::size_t> edges;
};
class Edge {
template<typename VertexType, typename EdgeType>
friend class DirectedGraph;
public:
using Identifier = std::size_t;
friend std::ostream&
operator<< (std::ostream& stream, const Edge& edge)
{ return stream << edge.id; }
bool
operator==(const Edge& other)
{ return this->id == other.id; }
Vertex::Identifier getVertexTo() const
{ return to; }
Vertex::Identifier getVertexFrom() const
{ return from; }
private:
Identifier id;
Vertex::Identifier from;
Vertex::Identifier to;
};
template<typename VertexType = Vertex, typename EdgeType = Edge>
class DirectedGraph {
public:
using VertexIdentifier = Vertex::Identifier;
using EdgeIdentifier = Edge::Identifier;
using Path = std::list<EdgeIdentifier>;
DirectedGraph(const std::string& name = "DirectedGraph") :
lastVertexId(0), lastEdgeId(0)
{
logger = loggerGetOrCreate(name);
}
std::shared_ptr<VertexType> getVertex(VertexIdentifier vertexId) const
{
if(vertexId >= lastVertexId)
throw std::invalid_argument("vertex doesn't exist");
// cannot use [] operator, because creates non-existing elements
// at() will throw std::out_of_range if element does not exist
return vertices.at(vertexId);
}
template<class UnaryPredicate>
VertexIdentifier findVertex(UnaryPredicate p)
{
for(auto& v : vertices) {
auto& vertexId = v.first;
auto& vertex = v.second;
if(p(vertex)) {
return vertexId;
}
}
throw std::out_of_range("vertex not found");
}
std::shared_ptr<EdgeType> getEdge(EdgeIdentifier edgeId) const
{
if(edgeId >= lastEdgeId)
throw std::invalid_argument("edge doesn't exist");
// cannot use [] operator, because creates non-existing elements
// at() will throw std::out_of_range if element does not exist
return edges.at(edgeId);
}
std::size_t getEdgeCount() const
{ return edges.size(); }
std::size_t getVertexCount() const
{ return vertices.size(); }
VertexIdentifier addVertex(std::shared_ptr<VertexType> vertex)
{
vertex->id = lastVertexId++;
logger->debug("New vertex: {}", *vertex);
vertices[vertex->id] = vertex;
return vertex->id;
}
EdgeIdentifier addEdge(std::shared_ptr<EdgeType> edge,
VertexIdentifier fromVertexId,
VertexIdentifier toVertexId)
{
// allocate edge id
edge->id = lastEdgeId++;
// connect it
edge->from = fromVertexId;
edge->to = toVertexId;
logger->debug("New edge {}: {} -> {}", *edge, edge->from, edge->to);
// this is a directed graph, so only push edge to starting vertex
getVertex(edge->from)->edges.push_back(edge->id);
// add new edge to graph
edges[edge->id] = edge;
return edge->id;
}
EdgeIdentifier addDefaultEdge(VertexIdentifier fromVertexId,
VertexIdentifier toVertexId)
{
// create a new edge
std::shared_ptr<EdgeType> edge(new EdgeType);
return addEdge(edge, fromVertexId, toVertexId);
}
void removeEdge(EdgeIdentifier edgeId)
{
auto edge = getEdge(edgeId);
auto startVertex = getVertex(edge->from);
// remove edge only from starting vertex (this is a directed graph)
logger->debug("Remove edge {} from vertex {}", edgeId, edge->from);
startVertex->edges.remove(edgeId);
logger->debug("Remove edge {}", edgeId);
edges.erase(edgeId);
}
void removeVertex(VertexIdentifier vertexId)
{
// delete every edge that start or ends at this vertex
auto it = edges.begin();
while(it != edges.end()) {
auto& edgeId = it->first;
auto& edge = it->second;
bool removeEdge = false;
if(edge->to == vertexId) {
logger->debug("Remove edge {} from vertex {}'s edge list",
edgeId, edge->from);
removeEdge = true;
auto startVertex = getVertex(edge->from);
startVertex->edges.remove(edge->id);
}
if((edge->from == vertexId) or removeEdge) {
logger->debug("Remove edge {}", edgeId);
// remove edge from global edge list
it = edges.erase(it);
} else {
++it;
}
}
logger->debug("Remove vertex {}", vertexId);
vertices.erase(vertexId);
}
const std::list<EdgeIdentifier>&
vertexGetEdges(VertexIdentifier vertexId) const
{ return getVertex(vertexId)->edges; }
using check_path_fn = std::function<bool(const Path&)>;
static bool
checkPath(const Path&)
{ return true; }
bool getPath(VertexIdentifier fromVertexId,
VertexIdentifier toVertexId,
Path& path,
check_path_fn pathCheckFunc = checkPath)
{
if(fromVertexId == toVertexId) {
// arrived at the destination
return true;
} else {
auto fromVertex = getVertex(fromVertexId);
for(auto& edgeId : fromVertex->edges) {
auto edgeOfFromVertex = getEdge(edgeId);
// loop detection
bool loop = false;
for(auto& edgeIdInPath : path) {
auto edgeInPath = getEdge(edgeIdInPath);
if(edgeInPath->from == edgeOfFromVertex->to) {
loop = true;
break;
}
}
if(loop) {
logger->debug("Loop detected via edge {}", edgeId);
continue;
}
// remember the path we're investigating to detect loops
path.push_back(edgeId);
// recursive, depth-first search
if(getPath(edgeOfFromVertex->to, toVertexId, path, pathCheckFunc) and
pathCheckFunc(path)) {
// path found, we're done
return true;
} else {
// tear down path that didn't lead to the destination
path.pop_back();
}
}
}
return false;
}
void dump(const std::string& fileName = "")
{
logger->info("Vertices:");
for(auto& v : vertices) {
auto& vertex = v.second;
// format connected vertices into a list
std::stringstream ssEdges;
for(auto& edge : vertex->edges) {
ssEdges << getEdge(edge)->to << " ";
}
logger->info(" {} connected to: {}", *vertex, ssEdges.str());
}
std::fstream s(fileName, s.out | s.trunc);
if(s.is_open()) {
s << "digraph memgraph {" << std::endl;
}
logger->info("Edges:");
for(auto& e : edges) {
auto& edge = e.second;
logger->info(" {}: {} -> {}", *edge, edge->from, edge->to);
if(s.is_open()) {
auto from = getVertex(edge->from);
auto to = getVertex(edge->to);
s << std::dec;
s << " \"" << *from << "\" -> \"" << *to << "\""
<< " [label=\"" << *edge << "\"];" << std::endl;
}
}
if(s.is_open()) {
s << "}" << std::endl;
s.close();
}
}
protected:
VertexIdentifier lastVertexId;
EdgeIdentifier lastEdgeId;
std::map<VertexIdentifier, std::shared_ptr<VertexType>> vertices;
std::map<EdgeIdentifier, std::shared_ptr<EdgeType>> edges;
SpdLogger logger;
};
} // namespacae graph
} // namespace villas
......@@ -5,7 +5,7 @@
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
......@@ -36,12 +36,12 @@
#include <jansson.h>
#include <villas/plugin.hpp>
#include <villas/config.h>
#include <villas/memory.hpp>
#include <villas/kernel/pci.h>
#include <villas/kernel/vfio.hpp>
#include <villas/fpga/config.h>
#include <villas/fpga/ip.hpp>
#define PCI_FILTER_DEFAULT_FPGA { \
......
/** Some common defines, enums and datastructures.
/** Compile time 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
* @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
......@@ -23,14 +26,11 @@
#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 */
};
/** 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
......@@ -5,7 +5,7 @@
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
......
......@@ -5,7 +5,7 @@
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
......@@ -37,7 +37,7 @@
#include <villas/fpga/ip.hpp>
#include <villas/directed_graph.hpp>
#include <villas/graph/directed.hpp>
namespace villas {
namespace fpga {
......
/** Block-Raam related helper functions
* *
*
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2018, Daniel Krebs
* @license GNU General Public License (version 3)
......@@ -26,8 +26,8 @@
#pragma once
#include "memory.hpp"
#include "fpga/ip.hpp"
#include <villas/memory.hpp>
#include <villas/fpga/ip.hpp>
namespace villas {
namespace fpga {
......
......@@ -2,7 +2,7 @@
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
* @copyright 2017-2018, Steffen Vogel
* @license GNU General Public License (version 3)
*
* VILLASfpga
......
......@@ -4,7 +4,7 @@
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017, Steffen Vogel
* @copyright 2017-2018, Steffen Vogel
* @license GNU General Public License (version 3)
*
* VILLASfpga
......
......@@ -3,7 +3,7 @@
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017, Steffen Vogel
* @copyright 2017-2018, Steffen Vogel
* @license GNU General Public License (version 3)
*
* VILLASfpga
......
......@@ -2,7 +2,7 @@
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
* @copyright 2017-2018, Steffen Vogel
* @license GNU General Public License (version 3)
*
* VILLASfpga
......
......@@ -5,7 +5,7 @@
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017, Steffen Vogel
* @copyright 2017-2018, Steffen Vogel
* @license GNU General Public License (version 3)
*
* VILLASfpga
......
......@@ -2,7 +2,7 @@
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Steffen Vogel
* @copyright 2017-2018, Steffen Vogel
* @license GNU General Public License (version 3)
*
* VILLASfpga
......
......@@ -2,6 +2,8 @@
#define REGISTER_TYPES_H
#include <stdint.h>
#include <cstddef>
#include <cstdint>
union axilite_reg_status_t {
uint32_t value;
......@@ -25,6 +27,31 @@ union reg_doorbell_t {
count : 6,
is_valid : 1;
};
constexpr reg_doorbell_t() : value(0) {}
};
template<size_t N, typename T = uint32_t>
struct Rtds2GpuMemoryBuffer {
// this type is only for memory interpretation, it makes no sense to create
// an instance so it's forbidden
Rtds2GpuMemoryBuffer() = delete;
// T can be a more complex type that wraps multiple values
static constexpr size_t rawValueCount = N * (sizeof(T) / 4);
// As of C++14, offsetof() is not working for non-standard layout types (i.e.
// composed of non-POD members). This might work in C++17 though.
// More info: https://gist.github.com/graphitemaster/494f21190bb2c63c5516
//static constexpr size_t doorbellOffset = offsetof(Rtds2GpuMemoryBuffer, doorbell);
//static constexpr size_t dataOffset = offsetof(Rtds2GpuMemoryBuffer, data);
// HACK: This might break horribly, let's just hope C++17 will be there soon
static constexpr size_t dataOffset = 0;
static constexpr size_t doorbellOffset = N * sizeof(Rtds2GpuMemoryBuffer::data);
T data[N];
reg_doorbell_t doorbell;
};
#endif // REGISTER_TYPES_H
......@@ -5,7 +5,7 @@
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017, Steffen Vogel
* @copyright 2017-2018, Steffen Vogel
* @license GNU General Public License (version 3)
*
* VILLASfpga
......
......@@ -4,7 +4,7 @@
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017, Steffen Vogel
* @copyright 2017-2018, Steffen Vogel
* @license GNU General Public License (version 3)
*
* VILLASfpga
......@@ -32,8 +32,7 @@
#include <cstdint>
#include <xilinx/xtmrctr.h>
#include <villas/config.h>
#include <villas/fpga/config.h>
#include <villas/fpga/ip.hpp>
namespace villas {
......
......@@ -2,7 +2,7 @@
*
* @file
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASfpga
......
/** Linux kernel related functions.
*
* @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 Kernel @{ */
#pragma once
#include <string.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Forward declarations */
struct version;
//#include <sys/capability.h>
/** Check if current process has capability \p cap.
*
* @retval 0 If capabilty is present.
* @retval <0 If capability is not present.
*/
//int kernel_check_cap(cap_value_t cap);
/** Get number of reserved hugepages. */
int kernel_get_nr_hugepages();
/** Set number of reserved hugepages. */
int kernel_set_nr_hugepages(int nr);
/** Get kernel cmdline parameter
*
* See https://www.kernel.org/doc/Documentation/kernel-parameters.txt
*
* @param param The cmdline parameter to look for.
* @param buf The string buffer to which the parameter value will be copied to.
* @param len The length of the buffer \p value
* @retval 0 Parameter \p key was found and value was copied to \p value
* @reval <>0 Kernel was not booted with parameter \p key
*/
int kernel_get_cmdline_param(const char *param, char *buf, size_t len);
/** Get the version of the kernel. */
int kernel_get_version(struct version *v);
/** Checks if a kernel module is loaded
*
* @param module the name of the module
* @retval 0 Module is loaded.
* @reval <>0 Module is not loaded.
*/
int kernel_module_loaded(const char *module);
/** Load kernel module via modprobe */
int kernel_module_load(const char *module);
/** Set parameter of loaded kernel module */
int kernel_module_set_param(const char *module, const char *param, const char *value);
<